summaryrefslogtreecommitdiffstatshomepage
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/aueffectutil.mm133
-rw-r--r--src/tools/castool.cpp47
-rw-r--r--src/tools/chdman.cpp2008
-rw-r--r--src/tools/floptool.cpp815
-rw-r--r--src/tools/image_handler.cpp397
-rw-r--r--src/tools/image_handler.h119
-rw-r--r--src/tools/imgtool/charconv.cpp51
-rw-r--r--src/tools/imgtool/charconv.h15
-rw-r--r--src/tools/imgtool/filtbas.cpp355
-rw-r--r--src/tools/imgtool/filteoln.cpp9
-rw-r--r--src/tools/imgtool/filter.cpp32
-rw-r--r--src/tools/imgtool/filter.h47
-rw-r--r--src/tools/imgtool/formats/coco_dsk.cpp8
-rw-r--r--src/tools/imgtool/formats/coco_dsk.h2
-rw-r--r--src/tools/imgtool/formats/pc_dsk_legacy.cpp140
-rw-r--r--src/tools/imgtool/formats/pc_dsk_legacy.h21
-rw-r--r--src/tools/imgtool/formats/vt_dsk_legacy.cpp (renamed from src/tools/imgtool/formats/vt_dsk.cpp)13
-rw-r--r--src/tools/imgtool/formats/vt_dsk_legacy.h (renamed from src/tools/imgtool/formats/vt_dsk.h)12
-rw-r--r--src/tools/imgtool/iflopimg.cpp85
-rw-r--r--src/tools/imgtool/iflopimg.h11
-rw-r--r--src/tools/imgtool/imghd.cpp74
-rw-r--r--src/tools/imgtool/imghd.h11
-rw-r--r--src/tools/imgtool/imgterrs.cpp7
-rw-r--r--src/tools/imgtool/imgtool.cpp228
-rw-r--r--src/tools/imgtool/imgtool.h40
-rw-r--r--src/tools/imgtool/library.cpp80
-rw-r--r--src/tools/imgtool/library.h362
-rw-r--r--src/tools/imgtool/main.cpp63
-rw-r--r--src/tools/imgtool/modules.cpp20
-rw-r--r--src/tools/imgtool/modules/amiga.cpp275
-rw-r--r--src/tools/imgtool/modules/bml3.cpp52
-rw-r--r--src/tools/imgtool/modules/concept.cpp21
-rw-r--r--src/tools/imgtool/modules/cybiko.cpp57
-rw-r--r--src/tools/imgtool/modules/cybikoxt.cpp42
-rw-r--r--src/tools/imgtool/modules/dgndos.cpp1256
-rw-r--r--src/tools/imgtool/modules/fat.cpp177
-rw-r--r--src/tools/imgtool/modules/fat.h3
-rw-r--r--src/tools/imgtool/modules/hp48.cpp2
-rw-r--r--src/tools/imgtool/modules/hp85_tape.cpp83
-rw-r--r--src/tools/imgtool/modules/hp9845_tape.cpp84
-rw-r--r--src/tools/imgtool/modules/mac.cpp6439
-rw-r--r--src/tools/imgtool/modules/macbin.cpp381
-rw-r--r--src/tools/imgtool/modules/macutil.cpp116
-rw-r--r--src/tools/imgtool/modules/macutil.h43
-rw-r--r--src/tools/imgtool/modules/os9.cpp158
-rw-r--r--src/tools/imgtool/modules/pc_flop.cpp25
-rw-r--r--src/tools/imgtool/modules/pc_hard.cpp67
-rw-r--r--src/tools/imgtool/modules/prodos.cpp2267
-rw-r--r--src/tools/imgtool/modules/psion.cpp19
-rw-r--r--src/tools/imgtool/modules/rsdos.cpp45
-rw-r--r--src/tools/imgtool/modules/rt11.cpp33
-rw-r--r--src/tools/imgtool/modules/thomson.cpp249
-rw-r--r--src/tools/imgtool/modules/ti99.cpp113
-rw-r--r--src/tools/imgtool/modules/ti990hd.cpp145
-rw-r--r--src/tools/imgtool/modules/vzdos.cpp211
-rw-r--r--src/tools/imgtool/stream.cpp371
-rw-r--r--src/tools/imgtool/stream.h137
-rw-r--r--src/tools/jedutil.cpp2209
-rw-r--r--src/tools/ldresample.cpp96
-rw-r--r--src/tools/ldverify.cpp43
-rw-r--r--src/tools/pngcmp.cpp72
-rw-r--r--src/tools/regrep.cpp173
-rw-r--r--src/tools/romcmp.cpp754
-rw-r--r--src/tools/split.cpp97
-rw-r--r--src/tools/src2html.cpp905
-rw-r--r--src/tools/srcclean.cpp531
-rw-r--r--src/tools/testkeys.cpp4
-rw-r--r--src/tools/unidasm.cpp837
68 files changed, 8905 insertions, 14892 deletions
diff --git a/src/tools/aueffectutil.mm b/src/tools/aueffectutil.mm
index ccc090d0fa8..b8a83de4c64 100644
--- a/src/tools/aueffectutil.mm
+++ b/src/tools/aueffectutil.mm
@@ -13,32 +13,15 @@
#include <utility>
#include <vector>
-#include <stdlib.h>
-
-
-#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
+#include <cstdlib>
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;
}
}
@@ -772,7 +752,7 @@ static void UpdateChangeCountCallback(
NSMenu *submenu;
NSString *const appName = [(NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()) objectForKey:@"CFBundleName"];
- NSMenu *const menu = [[NSMenu allocWithZone:[NSMenu zone]] initWithTitle:@"Application"];
+ NSMenu *const menu = [[NSMenu alloc] initWithTitle:@"Application"];
item = [parent addItemWithTitle:@"Application" action:NULL keyEquivalent:@""];
[parent setSubmenu:menu forItem:item];
[menu release];
@@ -784,7 +764,7 @@ static void UpdateChangeCountCallback(
[menu addItem:[NSMenuItem separatorItem]];
item = [menu addItemWithTitle:@"Services" action:NULL keyEquivalent:@""];
- submenu = [[NSMenu allocWithZone:[NSMenu zone]] initWithTitle:@"Services"];
+ submenu = [[NSMenu alloc] initWithTitle:@"Services"];
[menu setSubmenu:submenu forItem:item];
[submenu release];
[NSApp setServicesMenu:submenu];
@@ -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/castool.cpp b/src/tools/castool.cpp
index 6c10cfe4ed8..b5fa9cf7d39 100644
--- a/src/tools/castool.cpp
+++ b/src/tools/castool.cpp
@@ -10,15 +10,6 @@
***************************************************************************/
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <time.h>
-#include <assert.h>
-
-#include "corestr.h"
-
#include "formats/a26_cas.h"
#include "formats/ace_tap.h"
#include "formats/adam_cas.h"
@@ -38,6 +29,7 @@
#include "formats/mz_cas.h"
#include "formats/orao_cas.h"
#include "formats/oric_tap.h"
+#include "formats/p2000t_cas.h"
#include "formats/p6001_cas.h"
#include "formats/phc25_cas.h"
#include "formats/pmd_cas.h"
@@ -60,10 +52,22 @@
#include "formats/x1_tap.h"
#include "formats/zx81_p.h"
+#include "corestr.h"
+#include "ioprocs.h"
+#include "osdcomm.h"
+
+#include <cassert>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+
+
struct SupportedCassetteFormats
{
const char *name;
- const struct CassetteFormat * const *formats;
+ const cassette_image::Format * const *formats;
const char *desc;
};
@@ -90,6 +94,7 @@ const struct SupportedCassetteFormats formats[] = {
{"mz", mz700_cassette_formats ,"Sharp MZ-700"},
{"orao", orao_cassette_formats ,"PEL Varazdin Orao"},
{"oric", oric_cassette_formats ,"Tangerine Oric"},
+ {"p2000t", p2000t_cassette_formats ,"Philips P2000T"},
{"pc6001", pc6001_cassette_formats ,"NEC PC-6001"},
{"phc25", phc25_cassette_formats ,"Sanyo PHC-25"},
{"pmd85", pmd85_cassette_formats ,"Tesla PMD-85"},
@@ -157,9 +162,8 @@ int CLIB_DECL main(int argc, char *argv[])
{
int i;
int found =0;
- const struct CassetteFormat * const *selected_formats = nullptr;
- cassette_image *cassette;
- FILE *f;
+ const cassette_image::Format * const *selected_formats = nullptr;
+ cassette_image::ptr cassette;
if (argc > 1)
{
@@ -185,21 +189,26 @@ int CLIB_DECL main(int argc, char *argv[])
return -1;
}
- f = fopen(argv[3], "rb");
+ FILE *f = fopen(argv[3], "rb");
if (!f) {
fprintf(stderr, "File %s not found.\n",argv[3]);
return -1;
}
- if (cassette_open_choices(f, &stdio_ioprocs, get_extension(argv[3]), selected_formats, CASSETTE_FLAG_READONLY, &cassette) != cassette_image::error::SUCCESS) {
+ auto io = util::stdio_read_write(f, 0x00);
+ f = nullptr;
+ if (!io) {
+ fprintf(stderr, "Out of memory.\n");
+ return -1;
+ }
+
+ if (cassette_image::open_choices(std::move(io), get_extension(argv[3]), selected_formats, cassette_image::FLAG_READONLY, cassette) != cassette_image::error::SUCCESS) {
fprintf(stderr, "Invalid format of input file.\n");
- fclose(f);
return -1;
}
- cassette_dump(cassette,argv[4]);
- cassette_close(cassette);
- fclose(f);
+ cassette->dump(argv[4]);
+ cassette.reset();
goto theend;
}
}
diff --git a/src/tools/chdman.cpp b/src/tools/chdman.cpp
index 153a4e34157..353ac88ce6b 100644
--- a/src/tools/chdman.cpp
+++ b/src/tools/chdman.cpp
@@ -5,39 +5,51 @@
CHD compression frontend
****************************************************************************/
-#include <stdio.h> // must be here otherwise issues with I64FMT in MINGW
-#include <assert.h>
+#include <stdio.h> // must be stdio.h and here otherwise issues with I64FMT in MINGW
-#include "osdcore.h"
-#include "corefile.h"
-#include "chdcd.h"
-#include "aviio.h"
+// lib/util
#include "avhuff.h"
+#include "aviio.h"
#include "bitmap.h"
+#include "cdrom.h"
+#include "corefile.h"
+#include "coretmpl.h"
+#include "hashing.h"
#include "md5.h"
-#include "sha1.h"
+#include "multibyte.h"
+#include "osdcore.h"
+#include "path.h"
+#include "strformat.h"
#include "vbiparse.h"
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <ctype.h>
-#include <iostream>
+#include <array>
#include <cassert>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
#include <cstring>
+#include <ctime>
+#include <iostream>
#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;
//**************************************************************************
// CONSTANTS & DEFINES
//**************************************************************************
-/* MINGW has adopted the MSVC formatting for 64-bit ints as of gcc 4.4 */
-#if defined(WIN32)
+// MINGW has adopted the MSVC formatting for 64-bit ints as of GCC 4.4 and deprecated it as of GCC 9.3
+#if defined(_WIN32) && defined(__GNUC__) && ((__GNUC__ < 9) || ((__GNUC__ == 9) && (__GNUC_MINOR__ < 3)))
#define I64FMT "I64"
#elif !defined(__APPLE__) && defined(__LP64__)
#define I64FMT "l"
@@ -45,16 +57,23 @@
#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 "~"
@@ -66,10 +85,12 @@ const int MODE_GDI = 2;
#define COMMAND_CREATE_RAW "createraw"
#define COMMAND_CREATE_HD "createhd"
#define COMMAND_CREATE_CD "createcd"
+#define COMMAND_CREATE_DVD "createdvd"
#define COMMAND_CREATE_LD "createld"
#define COMMAND_EXTRACT_RAW "extractraw"
#define COMMAND_EXTRACT_HD "extracthd"
#define COMMAND_EXTRACT_CD "extractcd"
+#define COMMAND_EXTRACT_DVD "extractdvd"
#define COMMAND_EXTRACT_LD "extractld"
#define COMMAND_COPY "copy"
#define COMMAND_ADD_METADATA "addmeta"
@@ -81,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"
@@ -112,23 +134,26 @@ const int MODE_GDI = 2;
// FUNCTION PROTOTYPES
//**************************************************************************
-typedef std::unordered_map<std::string,std::string *> parameters_t;
+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> static void report_error(int error, Format &&fmt, Params &&...args);
-static void do_info(parameters_t &params);
-static void do_verify(parameters_t &params);
-static void do_create_raw(parameters_t &params);
-static void do_create_hd(parameters_t &params);
-static void do_create_cd(parameters_t &params);
-static void do_create_ld(parameters_t &params);
-static void do_copy(parameters_t &params);
-static void do_extract_raw(parameters_t &params);
-static void do_extract_cd(parameters_t &params);
-static void do_extract_ld(parameters_t &params);
-static void do_add_metadata(parameters_t &params);
-static void do_del_metadata(parameters_t &params);
-static void do_dump_metadata(parameters_t &params);
-static void do_list_templates(parameters_t &params);
+static void do_info(parameters_map &params);
+static void do_verify(parameters_map &params);
+static void do_create_raw(parameters_map &params);
+static void do_create_hd(parameters_map &params);
+static void do_create_cd(parameters_map &params);
+static void do_create_dvd(parameters_map &params);
+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_ld(parameters_map &params);
+static void do_add_metadata(parameters_map &params);
+static void do_del_metadata(parameters_map &params);
+static void do_dump_metadata(parameters_map &params);
+static void do_list_templates(parameters_map &params);
@@ -136,6 +161,46 @@ static void do_list_templates(parameters_t &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
@@ -152,7 +217,7 @@ struct option_description
struct command_description
{
const char *name;
- void (*handler)(parameters_t &);
+ void (*handler)(parameters_map &);
const char *description;
const char *valid_options[16];
};
@@ -198,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; }
@@ -245,11 +309,16 @@ class chd_rawfile_compressor : public chd_file_compressor
{
public:
// construction/destruction
- chd_rawfile_compressor(util::core_file &file, std::uint64_t offset = 0, std::uint64_t maxoffset = std::numeric_limits<std::uint64_t>::max())
+ chd_rawfile_compressor(util::random_read &file, std::uint64_t offset = 0, std::uint64_t maxoffset = std::numeric_limits<std::uint64_t>::max())
: m_file(file)
, m_offset(offset)
- , m_maxoffset((std::min)(maxoffset, file.size()))
{
+ // TODO: what to do about error getting file size?
+ std::uint64_t filelen;
+ if (!file.length(filelen))
+ m_maxoffset = (std::min)(maxoffset, filelen);
+ else
+ m_maxoffset = maxoffset;
}
// read interface
@@ -260,13 +329,15 @@ public:
return 0;
if (offset + length > m_maxoffset)
length = m_maxoffset - offset;
- m_file.seek(offset, SEEK_SET);
- return m_file.read(dest, length);
+ if (m_file.seek(offset, SEEK_SET)) // FIXME: better error reporting?
+ return 0;
+ auto const [err, actual] = read(m_file, dest, length); // FIXME: check for error return
+ return actual;
}
private:
// internal state
- util::core_file & m_file;
+ util::random_read & m_file;
std::uint64_t m_offset;
std::uint64_t m_maxoffset;
};
@@ -279,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)
@@ -292,18 +365,18 @@ public:
return 0;
if (offset + length > m_maxoffset)
length = m_maxoffset - offset;
- chd_error err = m_file.read_bytes(offset, dest, length);
- if (err != CHDERR_NONE)
+ std::error_condition err = m_file.read_bytes(offset, dest, length);
+ if (err)
throw err;
// if we have TOC - detect audio sectors and swap data
if (m_toc)
{
- assert(offset % CD_FRAME_SIZE == 0);
- assert(length % CD_FRAME_SIZE == 0);
+ assert(offset % cdrom_file::FRAME_SIZE == 0);
+ assert(length % cdrom_file::FRAME_SIZE == 0);
- int startlba = offset / CD_FRAME_SIZE;
- int lenlba = length / CD_FRAME_SIZE;
+ int startlba = offset / cdrom_file::FRAME_SIZE;
+ int lenlba = length / cdrom_file::FRAME_SIZE;
uint8_t *_dest = reinterpret_cast<uint8_t *>(dest);
for (int chdlba = 0; chdlba < lenlba; chdlba++)
@@ -317,11 +390,11 @@ public:
break;
}
// is it audio ?
- if (m_toc->tracks[tracknum].trktype != CD_TRACK_AUDIO)
+ if (m_toc->tracks[tracknum].trktype != cdrom_file::CD_TRACK_AUDIO)
continue;
// byteswap if yes
- int dataoffset = chdlba * CD_FRAME_SIZE;
- for (uint32_t swapindex = dataoffset; swapindex < (dataoffset + CD_MAX_SECTOR_DATA); swapindex += 2)
+ int dataoffset = chdlba * cdrom_file::FRAME_SIZE;
+ for (uint32_t swapindex = dataoffset; swapindex < (dataoffset + cdrom_file::MAX_SECTOR_DATA); swapindex += 2)
{
uint8_t temp = _dest[swapindex];
_dest[swapindex] = _dest[swapindex + 1];
@@ -333,7 +406,7 @@ public:
return length;
}
-const cdrom_toc * m_toc;
+const cdrom_file::toc * m_toc;
private:
// internal state
@@ -349,10 +422,12 @@ class chd_cd_compressor : public chd_file_compressor
{
public:
// construction/destruction
- chd_cd_compressor(cdrom_toc &toc, chdcd_track_input_info &info)
- : m_file(),
- m_toc(toc),
- m_info(info) { }
+ chd_cd_compressor(cdrom_file::toc &toc, cdrom_file::track_input_info &info)
+ : m_file()
+ , m_toc(toc)
+ , m_info(info)
+ {
+ }
~chd_cd_compressor()
{
@@ -362,8 +437,8 @@ public:
virtual uint32_t read_data(void *_dest, uint64_t offset, uint32_t length)
{
// verify assumptions made below
- assert(offset % CD_FRAME_SIZE == 0);
- assert(length % CD_FRAME_SIZE == 0);
+ assert(offset % cdrom_file::FRAME_SIZE == 0);
+ assert(length % cdrom_file::FRAME_SIZE == 0);
// initialize destination to 0 so that unused areas are filled
uint8_t *dest = reinterpret_cast<uint8_t *>(_dest);
@@ -374,8 +449,9 @@ public:
uint32_t length_remaining = length;
for (int tracknum = 0; tracknum < m_toc.numtrks; tracknum++)
{
- const cdrom_track_info &trackinfo = m_toc.tracks[tracknum];
- uint64_t endoffs = startoffs + (uint64_t)(trackinfo.frames + trackinfo.extraframes) * CD_FRAME_SIZE;
+ 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
@@ -383,33 +459,56 @@ public:
{
m_file.reset();
m_lastfile = m_info.track[tracknum].fname;
- osd_file::error filerr = util::core_file::open(m_lastfile, OPEN_FLAG_READ, m_file);
- if (filerr != osd_file::error::NONE)
- report_error(1, "Error opening input file (%s)'", m_lastfile.c_str());
+ std::error_condition const filerr = util::core_file::open(m_lastfile, OPEN_FLAG_READ, m_file);
+ if (filerr)
+ report_error(1, "Error opening input file (%s): %s", m_lastfile, filerr.message());
}
// iterate over frames
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 = 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)trackinfo.splitframes == 0L)
+ split_track_start = UINT64_MAX;
+
while (length_remaining != 0 && offset < endoffs)
{
// determine start of current frame
- uint64_t src_frame_start = src_track_start + ((offset - startoffs) / CD_FRAME_SIZE) * bytesperframe;
+ 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 && 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;
+ std::error_condition const filerr = util::core_file::open(m_lastfile, OPEN_FLAG_READ, m_file);
+ if (filerr)
+ report_error(1, "Error opening input file (%s): %s", m_lastfile, filerr.message());
+ }
+
if (src_frame_start < src_track_end)
{
// 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);
}
else
{
- m_file->seek(src_frame_start, SEEK_SET);
- uint32_t count = m_file->read(dest, bytesperframe);
- if (count != bytesperframe)
- report_error(1, "Error reading input file (%s)'", m_lastfile.c_str());
+ std::error_condition err = m_file->seek(
+ (src_frame_start >= split_track_start)
+ ? src_frame_start - split_track_start
+ : src_frame_start,
+ SEEK_SET);
+ std::size_t count = 0;
+ if (!err)
+ std::tie(err, count) = read(*m_file, dest, bytesperframe);
+ if (err || (count != bytesperframe))
+ report_error(1, "Error reading input file (%s)'", m_lastfile);
}
// swap if appropriate
@@ -423,9 +522,9 @@ public:
}
// advance
- offset += CD_FRAME_SIZE;
- dest += CD_FRAME_SIZE;
- length_remaining -= CD_FRAME_SIZE;
+ offset += cdrom_file::FRAME_SIZE;
+ dest += cdrom_file::FRAME_SIZE;
+ length_remaining -= cdrom_file::FRAME_SIZE;
if (length_remaining == 0)
break;
}
@@ -439,10 +538,10 @@ public:
private:
// internal state
- std::string m_lastfile;
- util::core_file::ptr m_file;
- cdrom_toc & m_toc;
- chdcd_track_input_info & m_info;
+ std::string m_lastfile;
+ util::core_file::ptr m_file;
+ cdrom_file::toc & m_toc;
+ cdrom_file::track_input_info &m_info;
};
@@ -453,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; }
@@ -475,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
@@ -483,7 +585,7 @@ public:
uint32_t samples = (uint64_t(m_info.rate) * uint64_t(effframe + 1) * uint64_t(1000000) + m_info.fps_times_1million - 1) / uint64_t(m_info.fps_times_1million) - first_sample;
// loop over channels and read the samples
- int channels = unsigned((std::min<std::size_t>)(m_info.channels, ARRAY_LENGTH(m_audio)));
+ int channels = unsigned(std::min<std::size_t>(m_info.channels, std::size(m_audio)));
EQUIVALENT_ARRAY(m_audio, int16_t *) samplesptr;
for (int chnum = 0; chnum < channels; chnum++)
{
@@ -505,7 +607,7 @@ public:
if (m_info.height == 524/2 || m_info.height == 624/2)
{
vbi_metadata vbi;
- vbi_parse_all(&subbitmap.pix16(0), subbitmap.rowpixels(), subbitmap.width(), 8, &vbi);
+ vbi_parse_all(&subbitmap.pix(0), subbitmap.rowpixels(), subbitmap.width(), 8, &vbi);
vbi_metadata_pack(&m_ldframedata[framenum * VBI_PACKED_BYTES], framenum, &vbi);
}
@@ -531,6 +633,7 @@ public:
dest += bytes_to_copy;
length_remaining -= bytes_to_copy;
}
+ }
return length;
}
@@ -540,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;
};
@@ -558,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
@@ -571,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" },
@@ -583,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" },
@@ -611,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
}
},
@@ -625,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
}
@@ -664,6 +770,21 @@ static const command_description s_commands[] =
OPTION_NUMPROCESSORS
}
},
+ { COMMAND_CREATE_DVD, do_create_dvd, ": create a DVD CHD from the input file",
+ {
+ REQUIRED OPTION_OUTPUT,
+ 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
+ }
+ },
{ COMMAND_CREATE_LD, do_create_ld, ": create a laserdisc CHD from the input file",
{
@@ -709,12 +830,26 @@ 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_raw, ": extract DVD file from a CHD input file",
+ {
+ REQUIRED OPTION_OUTPUT,
+ 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
+ }
+ },
+
{ COMMAND_EXTRACT_LD, do_extract_ld, ": extract laserdisc AVI from a CHD input file",
{
REQUIRED OPTION_OUTPUT,
@@ -782,11 +917,19 @@ static const command_description s_commands[] =
// hard disk templates
static const hd_template s_hd_templates[] =
{
- { "Conner", "CFA170A", 332, 16, 63, 512 }, // 163 MB
- { "Rodime", "R0201", 321, 2, 16, 512 }, // 5 MB
- { "Rodime", "R0202", 321, 4, 16, 512 }, // 10 MB
- { "Rodime", "R0203", 321, 6, 16, 512 }, // 15 MB
- { "Rodime", "R0204", 321, 8, 16, 512 }, // 20 MB
+ { "Conner", "CFA170A", 332, 16, 63, 512 }, // 163 MB
+ { "Rodime", "R0201", 321, 2, 16, 512 }, // 5 MB
+ { "Rodime", "R0202", 321, 4, 16, 512 }, // 10 MB
+ { "Rodime", "R0203", 321, 6, 16, 512 }, // 15 MB
+ { "Rodime", "R0204", 321, 8, 16, 512 }, // 20 MB
+ { "Seagate", "ST-213", 615, 2, 17, 512 }, // 10 MB
+ { "Seagate", "ST-225", 615, 4, 17, 512 }, // 20 MB
+ { "Seagate", "ST-251", 820, 6, 17, 512 }, // 40 MB
+ { "Seagate", "ST-3600N", 1877, 7, 76, 512 }, // 525 MB
+ { "Maxtor", "LXT-213S", 1314, 7, 53, 512 }, // 200 MB
+ { "Maxtor", "LXT-340S", 1574, 7, 70, 512 }, // 340 MB
+ { "Maxtor", "MXT-540SL", 2466, 7, 87, 512 }, // 540 MB
+ { "Micropolis", "1528", 2094, 15, 83, 512 }, // 1342 MB
};
@@ -799,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)...);
@@ -815,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();
@@ -833,20 +978,20 @@ template <typename Format, typename... Params> static void progress(bool forceit
// print_help - print help for all the commands
//-------------------------------------------------
-static int print_help(const char *argv0, const char *error = nullptr)
+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, 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, 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;
}
@@ -856,16 +1001,16 @@ static int print_help(const char *argv0, const char *error = nullptr)
// command
//-------------------------------------------------
-static int print_help(const char *argv0, const command_description &desc, const char *error = nullptr)
+static int print_help(const std::string &argv0, const command_description &desc, const char *error = nullptr)
{
// 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, desc.name);
- for (int valid = 0; valid < ARRAY_LENGTH(desc.valid_options); valid++)
+ 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
const char *option = desc.valid_options[valid];
@@ -880,10 +1025,10 @@ static int print_help(const char *argv0, const command_description &desc, const
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;
@@ -967,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
@@ -979,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;
@@ -991,7 +1146,10 @@ static void guess_chs(std::string *filename, uint64_t filesize, int sectorsize,
sectors = cursectors;
return;
}
+ }
}
+ }
+ }
}
@@ -1000,24 +1158,24 @@ static void guess_chs(std::string *filename, uint64_t filesize, int sectorsize,
// standard set of input CHD parameters
//-------------------------------------------------
-static void parse_input_chd_parameters(const parameters_t &params, chd_file &input_chd, chd_file &input_parent_chd, bool writeable = false)
+static void parse_input_chd_parameters(const parameters_map &params, chd_file &input_chd, chd_file &input_parent_chd, bool writeable = false)
{
// process input parent file
auto input_chd_parent_str = params.find(OPTION_INPUT_PARENT);
if (input_chd_parent_str != params.end())
{
- chd_error err = input_parent_chd.open(input_chd_parent_str->second->c_str());
- if (err != CHDERR_NONE)
- report_error(1, "Error opening parent CHD file (%s): %s", input_chd_parent_str->second->c_str(), chd_file::error_string(err));
+ std::error_condition err = input_parent_chd.open(*input_chd_parent_str->second);
+ if (err)
+ report_error(1, "Error opening parent CHD file (%s): %s", *input_chd_parent_str->second, err.message());
}
// process input file
auto input_chd_str = params.find(OPTION_INPUT);
if (input_chd_str != params.end())
{
- chd_error err = input_chd.open(input_chd_str->second->c_str(), writeable, input_parent_chd.opened() ? &input_parent_chd : nullptr);
- if (err != CHDERR_NONE)
- report_error(1, "Error opening CHD file (%s): %s", input_chd_str->second->c_str(), chd_file::error_string(err));
+ std::error_condition err = input_chd.open(*input_chd_str->second, writeable, input_parent_chd.opened() ? &input_parent_chd : nullptr);
+ if (err)
+ report_error(1, "Error opening CHD file (%s): %s", *input_chd_str->second, err.message());
}
}
@@ -1027,38 +1185,80 @@ static void parse_input_chd_parameters(const parameters_t &params, chd_file &inp
// parameters in a standard way
//-------------------------------------------------
-static void parse_input_start_end(const parameters_t &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);
}
@@ -1068,13 +1268,13 @@ static void parse_input_start_end(const parameters_t &params, uint64_t logical_s
// unless --force is specified
//-------------------------------------------------
-static void check_existing_output_file(const parameters_t &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())
{
util::core_file::ptr file;
- osd_file::error filerr = util::core_file::open(filename, OPEN_FLAG_READ, file);
- if (filerr == osd_file::error::NONE)
+ std::error_condition const filerr = util::core_file::open(filename, OPEN_FLAG_READ, file);
+ if (!filerr)
{
file.reset();
report_error(1, "Error: file already exists (%s)\nUse --force (or -f) to force overwriting", filename);
@@ -1088,22 +1288,23 @@ static void check_existing_output_file(const parameters_t &params, const char *f
// standard set of output CHD parameters
//-------------------------------------------------
-static std::string *parse_output_chd_parameters(const parameters_t &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())
{
- chd_error err = output_parent_chd.open(output_chd_parent_str->second->c_str());
- if (err != CHDERR_NONE)
- report_error(1, "Error opening parent CHD file (%s): %s", output_chd_parent_str->second->c_str(), chd_file::error_string(err));
+ std::error_condition err = output_parent_chd.open(*output_chd_parent_str->second);
+ if (err)
+ report_error(1, "Error opening parent CHD file (%s): %s", *output_chd_parent_str->second, err.message());
}
// process output file
- 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;
}
@@ -1112,17 +1313,32 @@ static std::string *parse_output_chd_parameters(const parameters_t &params, chd_
// parameter in a standard way
//-------------------------------------------------
-static void parse_hunk_size(const parameters_t &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;
}
@@ -1131,15 +1347,18 @@ static void parse_hunk_size(const parameters_t &params, uint32_t required_granul
// compression parameter string
//-------------------------------------------------
-static void parse_compression(const parameters_t &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;
@@ -1151,10 +1370,10 @@ static void parse_compression(const parameters_t &params, chd_codec_type compres
{
std::string name(*compression_str->second, start, (end == -1) ? -1 : end - start);
if (name.length() != 4)
- report_error(1, "Invalid compressor '%s' specified", name.c_str());
+ report_error(1, "Invalid compressor '%s' specified", name);
chd_codec_type type = CHD_MAKE_TAG(name[0], name[1], name[2], name[3]);
if (!chd_codec_list::codec_exists(type))
- report_error(1, "Invalid compressor '%s' specified", name.c_str());
+ report_error(1, "Invalid compressor '%s' specified", name);
compression[index++] = type;
if (end == -1)
break;
@@ -1172,7 +1391,7 @@ static void parse_compression(const parameters_t &params, chd_codec_type compres
// command
//-------------------------------------------------
-static void parse_numprocessors(const parameters_t &params)
+static void parse_numprocessors(const parameters_map &params)
{
auto numprocessors_str = params.find(OPTION_NUMPROCESSORS);
if (numprocessors_str == params.end())
@@ -1218,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
//-------------------------------------------------
@@ -1228,16 +1490,16 @@ static void compress_common(chd_file_compressor &chd)
// loop until done
double complete, ratio;
- chd_error err;
- while ((err = chd.compress_continue(complete, ratio)) == CHDERR_WALKING_PARENT || err == CHDERR_COMPRESSING)
- if (err == CHDERR_WALKING_PARENT)
+ std::error_condition err;
+ while ((err = chd.compress_continue(complete, ratio)) == chd_file::error::WALKING_PARENT || err == chd_file::error::COMPRESSING)
+ if (err == chd_file::error::WALKING_PARENT)
progress(false, "Examining parent, %.1f%% complete... \r", 100.0 * complete);
else
progress(false, "Compressing, %.1f%% complete... (ratio=%.1f%%) \r", 100.0 * complete, 100.0 * ratio);
// handle errors
- if (err != CHDERR_NONE)
- report_error(1, "Error during compression: %-40s", chd_file::error_string(err));
+ if (err)
+ report_error(1, "Error during compression: %-40s", err.message());
// final progress update
progress(true, "Compression complete ... final ratio = %.1f%% \n", 100.0 * ratio);
@@ -1249,81 +1511,39 @@ 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_track_info &info, const char *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 CD_TRACK_MODE1:
- mode = 4;
- size = 2048;
- break;
-
- case CD_TRACK_MODE1_RAW:
- mode = 4;
- size = 2352;
- break;
-
- case CD_TRACK_MODE2:
- mode = 4;
- size = 2336;
- break;
-
- case CD_TRACK_MODE2_FORM1:
- mode = 4;
- size = 2048;
- break;
-
- case CD_TRACK_MODE2_FORM2:
- mode = 4;
- size = 2324;
- break;
-
- case CD_TRACK_MODE2_FORM_MIX:
- mode = 4;
- size = 2336;
- break;
-
- case CD_TRACK_MODE2_RAW:
- mode = 4;
- size = 2352;
- break;
-
- case CD_TRACK_AUDIO:
- mode = 0;
- size = 2352;
- break;
- }
- bool needquote = strchr(filename, ' ') != nullptr;
- file.printf("%d %d %d %d %s%s%s %d\n", tracknum+1, frameoffs, mode, size, needquote?"\"":"", filename, needquote?"\"":"", discoffs);
+ 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, 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
std::string tempstr;
switch (info.trktype)
{
- case CD_TRACK_MODE1:
- case CD_TRACK_MODE1_RAW:
+ case cdrom_file::CD_TRACK_MODE1:
+ case cdrom_file::CD_TRACK_MODE1_RAW:
tempstr = string_format("MODE1/%04d", info.datasize);
break;
- case CD_TRACK_MODE2:
- case CD_TRACK_MODE2_FORM1:
- case CD_TRACK_MODE2_FORM2:
- case CD_TRACK_MODE2_FORM_MIX:
- case CD_TRACK_MODE2_RAW:
+ case cdrom_file::CD_TRACK_MODE2:
+ case cdrom_file::CD_TRACK_MODE2_FORM1:
+ case cdrom_file::CD_TRACK_MODE2_FORM2:
+ case cdrom_file::CD_TRACK_MODE2_FORM_MIX:
+ case cdrom_file::CD_TRACK_MODE2_RAW:
tempstr = string_format("MODE2/%04d", info.datasize);
break;
- case CD_TRACK_AUDIO:
+ case cdrom_file::CD_TRACK_AUDIO:
tempstr.assign("AUDIO");
break;
}
@@ -1356,22 +1576,19 @@ void output_track_metadata(int mode, util::core_file &file, int tracknum, const
// non-CUE mode
else if (mode == MODE_NORMAL)
{
- // header on the first track
- if (tracknum == 0)
- file.printf("CD_ROM\n\n\n");
file.printf("// Track %d\n", tracknum + 1);
// write out the track type
std::string modesubmode;
- if (info.subtype != CD_SUB_NONE)
- modesubmode = string_format("%s %s", cdrom_get_type_string(info.trktype), cdrom_get_subtype_string(info.subtype));
+ if (info.subtype != cdrom_file::CD_SUB_NONE)
+ modesubmode = string_format("%s %s", cdrom_file::get_type_string(info.trktype), cdrom_file::get_subtype_string(info.subtype));
else
- modesubmode = string_format("%s", cdrom_get_type_string(info.trktype));
+ modesubmode = string_format("%s", cdrom_file::get_type_string(info.trktype));
file.printf("TRACK %s\n", modesubmode);
// write out the attributes
file.printf("NO COPY\n");
- if (info.trktype == CD_TRACK_AUDIO)
+ if (info.trktype == cdrom_file::CD_TRACK_AUDIO)
{
file.printf("NO PRE_EMPHASIS\n");
file.printf("TWO_CHANNEL_AUDIO\n");
@@ -1381,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)
@@ -1401,7 +1617,7 @@ void output_track_metadata(int mode, util::core_file &file, int tracknum, const
// a drive image
//-------------------------------------------------
-static void do_info(parameters_t &params)
+static void do_info(parameters_map &params)
{
bool verbose = params.find(OPTION_VERBOSE) != params.end();
// parse out input files
@@ -1410,34 +1626,36 @@ static void do_info(parameters_t &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());
// output cmpression and size information
chd_codec_type compression[4] = { input_chd.compression(0), input_chd.compression(1), input_chd.compression(2), input_chd.compression(3) };
- printf("Logical size: %s bytes\n", big_int_string(input_chd.logical_bytes()).c_str());
- printf("Hunk Size: %s bytes\n", big_int_string(input_chd.hunk_bytes()).c_str());
- printf("Total Hunks: %s\n", big_int_string(input_chd.hunk_count()).c_str());
- printf("Unit Size: %s bytes\n", big_int_string(input_chd.unit_bytes()).c_str());
- printf("Total Units: %s\n", big_int_string(input_chd.unit_count()).c_str());
- printf("Compression: %s\n", compression_string(compression).c_str());
- printf("CHD size: %s bytes\n", big_int_string(static_cast<util::core_file &>(input_chd).size()).c_str());
+ uint64_t filesize = 0;
+ input_chd.file().length(filesize);
+ 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(static_cast<util::core_file &>(input_chd).size()) / 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;
@@ -1447,8 +1665,8 @@ static void do_info(parameters_t &params)
// get the indexed metadata item; stop when we hit an error
chd_metadata_tag metatag;
uint8_t metaflags;
- chd_error err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index, buffer, metatag, metaflags);
- if (err != CHDERR_NONE)
+ std::error_condition err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index, buffer, metatag, metaflags);
+ if (err)
break;
// determine our index
@@ -1470,18 +1688,18 @@ static void do_info(parameters_t &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
@@ -1493,9 +1711,9 @@ static void do_info(parameters_t &params)
// get info on this hunk
chd_codec_type codec;
uint32_t compbytes;
- chd_error err = input_chd.hunk_info(hunknum, codec, compbytes);
- if (err != CHDERR_NONE)
- report_error(1, "Error getting info on hunk %d: %s", hunknum, chd_file::error_string(err));
+ std::error_condition err = input_chd.hunk_info(hunknum, codec, compbytes);
+ if (err)
+ report_error(1, "Error getting info on hunk %d: %s", hunknum, err.message());
// decode into our data
if (codec > CHD_CODEC_MINI)
@@ -1505,18 +1723,18 @@ static void do_info(parameters_t &params)
codec = CHD_CODEC_MINI + 1 + comptype;
break;
}
- if (codec > ARRAY_LENGTH(compression_types))
- codec = ARRAY_LENGTH(compression_types) - 1;
+ if (codec >= std::size(compression_types))
+ codec = std::size(compression_types) - 1;
// count stats
compression_types[codec]++;
}
// output the stats
- printf("\n");
- printf(" Hunks Percent Name\n");
- printf("---------- ------- ------------------------------------\n");
- for (int comptype = 0; comptype < ARRAY_LENGTH(compression_types); comptype++)
+ 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)
{
// determine the name
@@ -1535,8 +1753,8 @@ static void do_info(parameters_t &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);
}
@@ -1545,17 +1763,17 @@ static void do_info(parameters_t &params)
//-------------------------------------------------
-// do_verify - validate the SHA1 on a CHD
+// do_verify - validate the SHA-1 on a CHD
//-------------------------------------------------
-static void do_verify(parameters_t &params)
+static void do_verify(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);
- // 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();
@@ -1573,9 +1791,9 @@ static void do_verify(parameters_t &params)
// determine how much to read
uint32_t bytes_to_read = (std::min<uint64_t>)(buffer.size(), input_chd.logical_bytes() - offset);
- chd_error err = input_chd.read_bytes(offset, &buffer[0], bytes_to_read);
- if (err != CHDERR_NONE)
- report_error(1, "Error reading CHD file (%s): %s", params.find(OPTION_INPUT)->second->c_str(), chd_file::error_string(err));
+ std::error_condition err = input_chd.read_bytes(offset, &buffer[0], bytes_to_read);
+ if (err)
+ report_error(1, "Error reading CHD file (%s): %s", *params.find(OPTION_INPUT)->second, err.message());
// add to the checksum
rawsha1.append(&buffer[0], bytes_to_read);
@@ -1586,36 +1804,41 @@ static void do_verify(parameters_t &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");
}
}
}
@@ -1628,25 +1851,14 @@ static void do_verify(parameters_t &params)
// image from a raw file
//-------------------------------------------------
-static void do_create_raw(parameters_t &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())
- {
- osd_file::error filerr = util::core_file::open(*input_file_str->second, OPEN_FLAG_READ, input_file);
- if (filerr != osd_file::error::NONE)
- report_error(1, "Unable to open file (%s)", input_file_str->second->c_str());
- }
+ 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;
@@ -1654,49 +1866,49 @@ static void do_create_raw(parameters_t &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;
- parse_input_start_end(params, input_file->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());
- if (input_start != 0 || input_end != input_file->size())
+ 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));
- chd_error err;
- if (output_parent.opened())
- err = chd->create(output_chd_str->c_str(), input_end - input_start, hunk_size, compression, output_parent);
- else
- err = chd->create(output_chd_str->c_str(), input_end - input_start, hunk_size, unit_size, compression);
- if (err != CHDERR_NONE)
- report_error(1, "Error creating CHD file (%s): %s", output_chd_str->c_str(), chd_file::error_string(err));
+ 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())
@@ -1708,9 +1920,7 @@ static void do_create_raw(parameters_t &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;
}
}
@@ -1721,80 +1931,96 @@ static void do_create_raw(parameters_t &params)
// disk image from a raw file
//-------------------------------------------------
-static void do_create_hd(parameters_t &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())
- {
- osd_file::error filerr = util::core_file::open(*input_file_str->second, OPEN_FLAG_READ, input_file);
- if (filerr != osd_file::error::NONE)
- report_error(1, "Unable to open file (%s)", input_file_str->second->c_str());
- }
+ 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)
{
- parse_input_start_end(params, input_file->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())
@@ -1803,110 +2029,92 @@ static void do_create_hd(parameters_t &params)
if (ident_str != params.end())
{
// load the file
- osd_file::error filerr = util::core_file::load(ident_str->second->c_str(), identdata);
- if (filerr != osd_file::error::NONE)
- report_error(1, "Error reading ident file (%s)", ident_str->second->c_str());
+ std::error_condition const filerr = util::core_file::load(*ident_str->second, identdata);
+ if (filerr)
+ report_error(1, "Error reading ident file (%s): %s", *ident_str->second, filerr.message());
// must be at least 14 bytes; extract CHS data from there
if (identdata.size() < 14)
- report_error(1, "Ident file '%s' is invalid (too short)", ident_str->second->c_str());
- cylinders = (identdata[3] << 8) | identdata[2];
- heads = (identdata[7] << 8) | identdata[6];
- sectors = (identdata[13] << 8) | identdata[12];
+ report_error(1, "Ident file '%s' is invalid (too short)", *ident_str->second);
+ cylinders = get_u16le(&identdata[2]);
+ heads = get_u16le(&identdata[6]);
+ 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 >= ARRAY_LENGTH(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)
{
std::string metadata;
- if (output_parent.read_metadata(HARD_DISK_METADATA_TAG, 0, metadata) != CHDERR_NONE)
+ if (output_parent.read_metadata(HARD_DISK_METADATA_TAG, 0, metadata))
report_error(1, "Unable to find hard disk metadata in parent CHD");
if (sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, &cylinders, &heads, &sectors, &sector_size) != 4)
report_error(1, "Error parsing hard disk metadata in parent CHD");
}
// 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)
{
- printf("Input file: %s\n", input_file_str->second->c_str());
- if (input_start != 0 || input_end != input_file->size())
+ 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));
- chd_error 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 != CHDERR_NONE)
- report_error(1, "Error creating CHD file (%s): %s", output_chd_str->c_str(), chd_file::error_string(err));
+ 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 != CHDERR_NONE)
- report_error(1, "Error adding hard disk metadata: %s", chd_file::error_string(err));
+ if (err)
+ report_error(1, "Error adding hard disk metadata: %s", err.message());
// write the ident if present
if (!identdata.empty())
{
err = chd->write_metadata(HARD_DISK_IDENT_METADATA_TAG, 0, identdata);
- if (err != CHDERR_NONE)
- report_error(1, "Error adding hard disk metadata: %s", chd_file::error_string(err));
+ if (err)
+ report_error(1, "Error adding hard disk metadata: %s", err.message());
}
// compress it generically
@@ -1916,9 +2124,7 @@ static void do_create_hd(parameters_t &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;
}
}
@@ -1929,87 +2135,144 @@ static void do_create_hd(parameters_t &params)
// image from a raw file
//-------------------------------------------------
-static void do_create_cd(parameters_t &params)
+static void do_create_cd(parameters_map &params)
{
// process input file
- chdcd_track_input_info track_info;
- cdrom_toc toc = { 0 };
+ cdrom_file::track_input_info track_info;
+ cdrom_file::toc toc = { 0 };
auto input_file_str = params.find(OPTION_INPUT);
if (input_file_str != params.end())
{
- chd_error err = chdcd_parse_toc(input_file_str->second->c_str(), toc, track_info);
- if (err != CHDERR_NONE)
- report_error(1, "Error parsing input file (%s: %s)\n", input_file_str->second->c_str(), chd_file::error_string(err));
+ std::error_condition err = cdrom_file::parse_toc(*input_file_str->second, toc, track_info);
+ if (err)
+ report_error(1, "Error parsing input file (%s: %s)\n", *input_file_str->second, err.message());
}
// 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() : CD_FRAMES_PER_HUNK * CD_FRAME_SIZE;
- parse_hunk_size(params, CD_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++)
{
- cdrom_track_info &trackinfo = toc.tracks[tracknum];
- int padded = (trackinfo.frames + CD_TRACK_PADDING - 1) / CD_TRACK_PADDING;
- trackinfo.extraframes = padded * CD_TRACK_PADDING - trackinfo.frames;
+ cdrom_file::track_info &trackinfo = toc.tracks[tracknum];
+ int padded = (trackinfo.frames + cdrom_file::TRACK_PADDING - 1) / cdrom_file::TRACK_PADDING;
+ trackinfo.extraframes = padded * cdrom_file::TRACK_PADDING - trackinfo.frames;
origtotalsectors += trackinfo.frames;
totalsectors += trackinfo.frames + trackinfo.extraframes;
}
// 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) * CD_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);
- chd_error err;
- if (output_parent.opened())
- err = chd->create(output_chd_str->c_str(), uint64_t(totalsectors) * uint64_t(CD_FRAME_SIZE), hunk_size, compression, output_parent);
- else
- err = chd->create(output_chd_str->c_str(), uint64_t(totalsectors) * uint64_t(CD_FRAME_SIZE), hunk_size, CD_FRAME_SIZE, compression);
- if (err != CHDERR_NONE)
- report_error(1, "Error creating CHD file (%s): %s", output_chd_str->c_str(), chd_file::error_string(err));
+ 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_write_metadata(chd, &toc);
- if (err != CHDERR_NONE)
- report_error(1, "Error adding CD metadata: %s", chd_file::error_string(err));
+ 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;
+ }
+}
+
+
+//-------------------------------------------------
+// do_create_dvd - create a new compressed dvd
+// image from a raw file
+//-------------------------------------------------
+
+static void do_create_dvd(parameters_map &params)
+{
+ // process input file
+ auto [input_file, input_file_str] = open_input_file(params);
+
+ // process output CHD
+ chd_file 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
+ 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];
+ parse_compression(params, s_default_hd_compression, output_parent, compression); // No reason to be different than HD for compression
+
+ // process numprocessors
+ parse_numprocessors(params);
+
+ // print some info
+ util::stream_format(std::cout, "Output CHD: %s\n", *output_chd_str);
+ if (output_parent.opened())
+ 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
+ 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
+ const std::error_condition err = chd->write_metadata(DVD_METADATA_TAG, 0, "");
+ if (err)
+ report_error(1, "Error adding DVD metadata: %s", err.message());
+
+ // compress it generically
+ compress_common(*chd);
+ }
+ catch (...)
+ {
+ // delete the output file
+ osd_file::remove(*output_chd_str);
throw;
}
}
@@ -2020,7 +2283,7 @@ static void do_create_cd(parameters_t &params)
// input AVI file and metadata
//-------------------------------------------------
-static void do_create_ld(parameters_t &params)
+static void do_create_ld(parameters_map &params)
{
// process input file
avi_file::ptr input_file;
@@ -2029,18 +2292,16 @@ static void do_create_ld(parameters_t &params)
{
avi_file::error avierr = avi_file::open(*input_file_str->second, input_file);
if (avierr != avi_file::error::NONE)
- report_error(1, "Error opening AVI file (%s): %s\n", input_file_str->second->c_str(), avi_file::error_string(avierr));
+ report_error(1, "Error opening AVI file (%s): %s\n", *input_file_str->second, avi_file::error_string(avierr));
}
const avi_file::movie_info &aviinfo = input_file->get_movie_info();
// 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;
@@ -2065,13 +2326,11 @@ static void do_create_ld(parameters_t &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");
@@ -2080,42 +2339,36 @@ static void do_create_ld(parameters_t &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);
- chd_error err;
- if (output_parent.opened())
- err = chd->create(output_chd_str->c_str(), uint64_t(input_end - input_start) * hunk_size, hunk_size, compression, output_parent);
- else
- err = chd->create(output_chd_str->c_str(), uint64_t(input_end - input_start) * hunk_size, hunk_size, info.bytes_per_frame, compression);
- if (err != CHDERR_NONE)
- report_error(1, "Error creating CHD file (%s): %s", output_chd_str->c_str(), chd_file::error_string(err));
+ 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 != CHDERR_NONE)
- report_error(1, "Error adding AV metadata: %s\n", chd_file::error_string(err));
+ if (err)
+ report_error(1, "Error adding AV metadata: %s\n", err.message());
// create the compressor and then run it generically
compress_common(*chd);
@@ -2124,29 +2377,58 @@ static void do_create_ld(parameters_t &params)
if (info.height == 524/2 || info.height == 624/2)
{
err = chd->write_metadata(AV_LD_METADATA_TAG, 0, chd->ldframedata(), 0);
- if (err != CHDERR_NONE)
- report_error(1, "Error adding AVLD metadata: %s\n", chd_file::error_string(err));
+ if (err)
+ report_error(1, "Error adding AVLD metadata: %s\n", err.message());
}
- delete chd;
}
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
//-------------------------------------------------
-static void do_copy(parameters_t &params)
+static void do_copy(parameters_map &params)
{
// parse out input files
chd_file input_parent_chd;
@@ -2154,78 +2436,56 @@ static void do_copy(parameters_t &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) == CHDERR_NONE)
- memcpy(compression, s_default_hd_compression, sizeof(compression));
- else if (input_chd.read_metadata(AV_METADATA_TAG, 0, metadata) == CHDERR_NONE)
- memcpy(compression, s_default_ld_compression, sizeof(compression));
- else if (input_chd.read_metadata(CDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
- input_chd.read_metadata(CDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
- input_chd.read_metadata(CDROM_TRACK_METADATA2_TAG, 0, metadata) == CHDERR_NONE ||
- input_chd.read_metadata(GDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
- input_chd.read_metadata(GDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE)
- 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);
- chd_error err;
- if (output_parent.opened())
- err = chd->create(output_chd_str->c_str(), input_end - input_start, hunk_size, compression, output_parent);
- else
- err = chd->create(output_chd_str->c_str(), input_end - input_start, hunk_size, input_chd.unit_bytes(), compression);
- if (err != CHDERR_NONE)
- report_error(1, "Error creating CHD file (%s): %s", output_chd_str->c_str(), chd_file::error_string(err));
+ 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;
uint32_t index = 0;
bool redo_cd = false;
bool cdda_swap = false;
- for (err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index++, metadata, metatag, metaflags); err == CHDERR_NONE; err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index++, metadata, metatag, metaflags))
+ for (err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index++, metadata, metatag, metaflags); !err; err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index++, metadata, metatag, metaflags))
{
// if this is an old CD-CHD tag, note that we want to re-do it
if (metatag == CDROM_OLD_METADATA_TAG || metatag == CDROM_TRACK_METADATA_TAG)
@@ -2242,35 +2502,29 @@ static void do_copy(parameters_t &params)
// otherwise, clone it
err = chd->write_metadata(metatag, CHDMETAINDEX_APPEND, metadata, metaflags);
- if (err != CHDERR_NONE)
- report_error(1, "Error writing cloned metadata: %s", chd_file::error_string(err));
+ if (err)
+ report_error(1, "Error writing cloned metadata: %s", err.message());
}
// if we need to re-do the CD metadata, do it now
if (redo_cd)
{
- cdrom_file *cdrom = cdrom_open(&input_chd);
- if (cdrom == nullptr)
- report_error(1, "Error upgrading CD metadata");
- const cdrom_toc *toc = cdrom_get_toc(cdrom);
- err = cdrom_write_metadata(chd, toc);
- if (err != CHDERR_NONE)
- report_error(1, "Error writing upgraded CD metadata: %s", chd_file::error_string(err));
+ cdrom = std::make_unique<cdrom_file>(&input_chd);
+ const cdrom_file::toc &toc = cdrom->get_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)
- chd->m_toc = toc;
+ chd->m_toc = &toc;
}
// 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;
}
}
@@ -2281,7 +2535,7 @@ static void do_copy(parameters_t &params)
// CHD image
//-------------------------------------------------
-static void do_extract_raw(parameters_t &params)
+static void do_extract_raw(parameters_map &params)
{
// parse out input files
chd_file input_parent_chd;
@@ -2289,22 +2543,20 @@ static void do_extract_raw(parameters_t &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
@@ -2312,9 +2564,9 @@ static void do_extract_raw(parameters_t &params)
try
{
// process output file
- osd_file::error filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file);
- if (filerr != osd_file::error::NONE)
- report_error(1, "Unable to open file (%s)", output_file_str->second->c_str());
+ std::error_condition const filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file);
+ if (filerr)
+ report_error(1, "Unable to open file (%s): %s", *output_file_str->second, filerr.message());
// copy all data
std::vector<uint8_t> buffer((TEMP_BUFFER_SIZE / input_chd.hunk_bytes()) * input_chd.hunk_bytes());
@@ -2324,14 +2576,14 @@ static void do_extract_raw(parameters_t &params)
// determine how much to read
uint32_t bytes_to_read = (std::min<uint64_t>)(buffer.size(), input_end - offset);
- chd_error err = input_chd.read_bytes(offset, &buffer[0], bytes_to_read);
- if (err != CHDERR_NONE)
- report_error(1, "Error reading CHD file (%s): %s", params.find(OPTION_INPUT)->second->c_str(), chd_file::error_string(err));
+ std::error_condition err = input_chd.read_bytes(offset, &buffer[0], bytes_to_read);
+ if (err)
+ report_error(1, "Error reading CHD file (%s): %s", *params.find(OPTION_INPUT)->second, err.message());
// write to the output
- uint32_t count = output_file->write(&buffer[0], bytes_to_read);
- if (count != bytes_to_read)
- report_error(1, "Error writing to file; check disk space (%s)", output_file_str->second->c_str());
+ 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
offset += bytes_to_read;
@@ -2339,7 +2591,7 @@ static void do_extract_raw(parameters_t &params)
// finish up
output_file.reset();
- printf("Extraction complete \n");
+ util::stream_format(std::cout, "Extraction complete \n");
}
catch (...)
{
@@ -2359,7 +2611,7 @@ static void do_extract_raw(parameters_t &params)
// CHD image
//-------------------------------------------------
-static void do_extract_cd(parameters_t &params)
+static void do_extract_cd(parameters_map &params)
{
// parse out input files
chd_file input_parent_chd;
@@ -2367,123 +2619,320 @@ static void do_extract_cd(parameters_t &params)
parse_input_chd_parameters(params, input_chd, input_parent_chd);
// further process input file
- cdrom_file *cdrom = cdrom_open(&input_chd);
- if (cdrom == nullptr)
- report_error(1, "Unable to recognize CHD file as a CD");
- const cdrom_toc *toc = cdrom_get_toc(cdrom);
+ cdrom_file *cdrom = new cdrom_file(&input_chd);
+ const cdrom_file::toc &toc = cdrom->get_toc();
// 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());
- char basename[128];
- strncpy(basename, default_name.c_str(), 127);
- 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;
+ // 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());
- if (output_file_str->second->find(".cue") != -1)
+ uint64_t total_bytes = 0;
+ for (int tracknum = 0; tracknum < toc.numtrks; tracknum++)
{
- mode = MODE_CUEBIN;
+ // 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);
}
- else if (output_file_str->second->find(".gdi") != -1)
+
+ // GDI must start with the # of tracks
+ if (mode == MODE_GDI)
{
- mode = MODE_GDI;
+ output_toc_file->printf("%d\n", toc.numtrks);
}
+ else if (mode == MODE_NORMAL)
+ {
+ bool mode1 = false;
+ bool mode2 = false;
+ bool cdda = false;
- // process output file
- osd_file::error filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, output_toc_file);
- if (filerr != osd_file::error::NONE)
- report_error(1, "Unable to open file (%s)", output_file_str->second->c_str());
+ for (int tracknum = 0; tracknum < toc.numtrks; tracknum++)
+ {
+ switch (toc.tracks[tracknum].trktype)
+ {
+ case cdrom_file::CD_TRACK_MODE1:
+ case cdrom_file::CD_TRACK_MODE1_RAW:
+ mode1 = true;
+ break;
- // process output BIN file
- if (mode != MODE_GDI)
- {
- filerr = util::core_file::open(*output_bin_file_str, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_bin_file);
- if (filerr != osd_file::error::NONE)
- report_error(1, "Unable to open file (%s)", output_bin_file_str->c_str());
- }
+ case cdrom_file::CD_TRACK_MODE2:
+ case cdrom_file::CD_TRACK_MODE2_FORM1:
+ case cdrom_file::CD_TRACK_MODE2_FORM2:
+ case cdrom_file::CD_TRACK_MODE2_FORM_MIX:
+ case cdrom_file::CD_TRACK_MODE2_RAW:
+ mode2 = true;
+ break;
- // determine total frames
- uint64_t total_bytes = 0;
- for (int tracknum = 0; tracknum < toc->numtrks; tracknum++)
- total_bytes += toc->tracks[tracknum].frames * (toc->tracks[tracknum].datasize + toc->tracks[tracknum].subsize);
+ case cdrom_file::CD_TRACK_AUDIO:
+ cdda = true;
+ break;
+ }
+ }
- // GDI must start with the # of tracks
- if (mode == MODE_GDI)
+ if (mode2)
+ output_toc_file->printf("CD_ROM_XA\n\n\n");
+ else if (cdda && !mode1)
+ output_toc_file->printf("CD_DA\n\n\n");
+ else
+ output_toc_file->printf("CD_ROM\n\n\n");
+ }
+
+ if (cdrom->is_gdrom() && mode == MODE_CUEBIN)
{
- output_toc_file->printf("%d\n", toc->numtrks);
+ // 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)
+ for (int tracknum = 0; tracknum < toc.numtrks; tracknum++)
+ {
+ if (track_filenames[tracknum] != trackbin_name)
{
- char temp[11];
- sprintf(temp, "%02d", tracknum+1);
- trackbin_name.append(temp);
- if (toc->tracks[tracknum].trktype == CD_TRACK_AUDIO)
- trackbin_name.append(".raw");
- else
- trackbin_name.append(".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 != osd_file::error::NONE)
- report_error(1, "Unable to open file (%s)", trackbin_name.c_str());
+ if (filerr)
+ report_error(1, "Unable to open file (%s): %s", trackbin_name, filerr.message());
- outputoffs = 0;
+ output_bin_filenames.push_back(trackbin_name);
}
- // output the metadata about the track to the TOC file
- const cdrom_track_info &trackinfo = toc->tracks[tracknum];
- if (mode == MODE_GDI)
- {
- output_track_metadata(mode, *output_toc_file, tracknum, trackinfo, core_filename_extract_base(trackbin_name).c_str(), discoffs, outputoffs);
- }
- else
+ if (cdrom->is_gdrom() && mode == MODE_CUEBIN)
{
- output_track_metadata(mode, *output_toc_file, tracknum, trackinfo, core_filename_extract_base(*output_bin_file_str).c_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 != CD_SUB_NONE) ? trackinfo.subsize : 0);
- if (trackinfo.subtype != CD_SUB_NONE && ((mode == MODE_CUEBIN) || (mode == MODE_GDI)))
+ 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;
}
@@ -2492,40 +2941,53 @@ static void do_extract_cd(parameters_t &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, cdrom_get_track_start_phys(cdrom, 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 == 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 != CD_SUB_NONE && (mode == MODE_NORMAL))
+ if (toc.tracks[trk].subtype != cdrom_file::CD_SUB_NONE && (mode == MODE_NORMAL))
{
- cdrom_read_subcode(cdrom, cdrom_get_track_start_phys(cdrom, 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);
- uint32_t byteswritten = output_bin_file->write(&buffer[0], bufferoffs);
- if (byteswritten != bufferoffs)
- report_error(1, "Error writing frame %d to file (%s): %s\n", frame, output_file_str->second->c_str(), chd_file::error_string(CHDERR_WRITE_ERROR));
+ 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;
}
@@ -2537,26 +2999,29 @@ static void do_extract_cd(parameters_t &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_ld - extract an AVI file from a
// CHD image
//-------------------------------------------------
-static void do_extract_ld(parameters_t &params)
+static void do_extract_ld(parameters_map &params)
{
// parse out input files
chd_file input_parent_chd;
@@ -2565,8 +3030,8 @@ static void do_extract_ld(parameters_t &params)
// read core metadata
std::string metadata;
- chd_error err = input_chd.read_metadata(AV_METADATA_TAG, 0, metadata);
- if (err != CHDERR_NONE)
+ std::error_condition err = input_chd.read_metadata(AV_METADATA_TAG, 0, metadata);
+ if (err)
report_error(1, "Unable to find A/V metadata in the input CHD");
// parse the metadata
@@ -2594,15 +3059,13 @@ static void do_extract_ld(parameters_t &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;
// build up the movie info
avi_file::movie_info info;
- info.video_format = FORMAT_YUY2;
+ info.video_format = avi_file::FORMAT_YUY2;
info.video_timescale = fps_times_1million / interlace_factor;
info.video_sampletime = 1000000;
info.video_width = width;
@@ -2618,15 +3081,15 @@ static void do_extract_ld(parameters_t &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
@@ -2636,15 +3099,17 @@ static void do_extract_ld(parameters_t &params)
// process output file
avi_file::error avierr = avi_file::create(*output_file_str->second, info, output_file);
if (avierr != avi_file::error::NONE)
- report_error(1, "Unable to open file (%s)", output_file_str->second->c_str());
+ report_error(1, "Unable to open file (%s)", *output_file_str->second);
// create the codec configuration
- avhuff_decompress_config avconfig;
+ avhuff_decoder::config avconfig;
+ bitmap_yuy16 avvideo;
std::vector<int16_t> audio_data[16];
uint32_t actsamples;
+ avconfig.video = &avvideo;
avconfig.maxsamples = max_samples_per_frame;
avconfig.actsamples = &actsamples;
- for (int chnum = 0; chnum < ARRAY_LENGTH(audio_data); chnum++)
+ for (int chnum = 0; chnum < std::size(audio_data); chnum++)
{
audio_data[chnum].resize(std::max(1U,max_samples_per_frame));
avconfig.audio[chnum] = &audio_data[chnum][0];
@@ -2657,15 +3122,16 @@ static void do_extract_ld(parameters_t &params)
progress(framenum == input_start, "Extracting, %.1f%% complete... \r", 100.0 * double(framenum - input_start) / double(input_end - input_start));
// set up the fake bitmap for this frame
- avconfig.video.wrap(&fullbitmap.pix(framenum % interlace_factor), fullbitmap.width(), fullbitmap.height() / interlace_factor, fullbitmap.rowpixels() * interlace_factor);
+ avvideo.wrap(&fullbitmap.pix(framenum % interlace_factor), fullbitmap.width(), fullbitmap.height() / interlace_factor, fullbitmap.rowpixels() * interlace_factor);
input_chd.codec_configure(CHD_CODEC_AVHUFF, AVHUFF_CODEC_DECOMPRESS_CONFIG, &avconfig);
// read the hunk into the buffers
- chd_error err = input_chd.read_hunk(framenum, nullptr);
- if (err != CHDERR_NONE)
+ std::error_condition err = input_chd.codec_process_hunk(framenum);
+ if (err)
{
- uint64_t filepos = static_cast<util::core_file &>(input_chd).tell();
- report_error(1, "Error reading hunk %d at offset %d from CHD file (%s): %s\n", framenum, filepos, params.find(OPTION_INPUT)->second->c_str(), chd_file::error_string(err));
+ uint64_t filepos = ~uint64_t(0);
+ input_chd.file().tell(filepos);
+ report_error(1, "Error reading hunk %d at offset %d from CHD file (%s): %s\n", framenum, filepos, *params.find(OPTION_INPUT)->second, err.message());
}
// write audio
@@ -2673,7 +3139,7 @@ static void do_extract_ld(parameters_t &params)
{
avi_file::error avierr = output_file->append_sound_samples(chnum, avconfig.audio[chnum], actsamples, 0);
if (avierr != avi_file::error::NONE)
- report_error(1, "Error writing samples for hunk %d to file (%s): %s\n", framenum, output_file_str->second->c_str(), avi_file::error_string(avierr));
+ report_error(1, "Error writing samples for hunk %d to file (%s): %s\n", framenum, *output_file_str->second, avi_file::error_string(avierr));
}
// write video
@@ -2681,13 +3147,13 @@ static void do_extract_ld(parameters_t &params)
{
avi_file::error avierr = output_file->append_video_frame(fullbitmap);
if (avierr != avi_file::error::NONE)
- report_error(1, "Error writing video for hunk %d to file (%s): %s\n", framenum, output_file_str->second->c_str(), avi_file::error_string(avierr));
+ report_error(1, "Error writing video for hunk %d to file (%s): %s\n", framenum, *output_file_str->second, avi_file::error_string(avierr));
}
}
// close and return
output_file.reset();
- printf("Extraction complete \n");
+ util::stream_format(std::cout, "Extraction complete \n");
}
catch (...)
{
@@ -2704,7 +3170,7 @@ static void do_extract_ld(parameters_t &params)
// file
//-------------------------------------------------
-static void do_add_metadata(parameters_t &params)
+static void do_add_metadata(parameters_map &params)
{
// parse out input files
chd_file input_parent_chd;
@@ -2741,9 +3207,9 @@ static void do_add_metadata(parameters_t &params)
std::vector<uint8_t> file;
if (file_str != params.end())
{
- osd_file::error filerr = util::core_file::load(file_str->second->c_str(), file);
- if (filerr != osd_file::error::NONE)
- report_error(1, "Error reading metadata file (%s)", file_str->second->c_str());
+ std::error_condition const filerr = util::core_file::load(*file_str->second, file);
+ if (filerr)
+ report_error(1, "Error reading metadata file (%s): %s", *file_str->second, filerr.message());
}
// make sure we have one or the other
@@ -2758,24 +3224,24 @@ static void do_add_metadata(parameters_t &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
- chd_error err;
+ std::error_condition err;
if (text_str != params.end())
err = input_chd.write_metadata(tag, index, text, flags);
else
err = input_chd.write_metadata(tag, index, file, flags);
- if (err != CHDERR_NONE)
- report_error(1, "Error adding metadata: %s", chd_file::error_string(err));
+ if (err)
+ report_error(1, "Error adding metadata: %s", err.message());
else
- printf("Metadata added\n");
+ util::stream_format(std::cout, "Metadata added\n");
}
@@ -2783,7 +3249,7 @@ static void do_add_metadata(parameters_t &params)
// do_del_metadata - remove metadata from a CHD
//-------------------------------------------------
-static void do_del_metadata(parameters_t &params)
+static void do_del_metadata(parameters_map &params)
{
// parse out input files
chd_file input_parent_chd;
@@ -2806,16 +3272,16 @@ static void do_del_metadata(parameters_t &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
- chd_error err = input_chd.delete_metadata(tag, index);
- if (err != CHDERR_NONE)
- report_error(1, "Error removing metadata: %s", chd_file::error_string(err));
+ std::error_condition err = input_chd.delete_metadata(tag, index);
+ if (err)
+ report_error(1, "Error removing metadata: %s", err.message());
else
- printf("Metadata removed\n");
+ util::stream_format(std::cout, "Metadata removed\n");
}
@@ -2823,7 +3289,7 @@ static void do_del_metadata(parameters_t &params)
// do_dump_metadata - dump metadata from a CHD
//-------------------------------------------------
-static void do_dump_metadata(parameters_t &params)
+static void do_dump_metadata(parameters_map &params)
{
// parse out input files
chd_file input_parent_chd;
@@ -2833,7 +3299,7 @@ static void do_dump_metadata(parameters_t &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('?','?','?','?');
@@ -2852,9 +3318,9 @@ static void do_dump_metadata(parameters_t &params)
// write the metadata
std::vector<uint8_t> buffer;
- chd_error err = input_chd.read_metadata(tag, index, buffer);
- if (err != CHDERR_NONE)
- report_error(1, "Error reading metadata: %s", chd_file::error_string(err));
+ std::error_condition err = input_chd.read_metadata(tag, index, buffer);
+ if (err)
+ report_error(1, "Error reading metadata: %s", err.message());
// catch errors so we can close & delete the output file
util::core_file::ptr output_file;
@@ -2863,23 +3329,28 @@ static void do_dump_metadata(parameters_t &params)
// create the file
if (output_file_str != params.end())
{
- osd_file::error filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file);
- if (filerr != osd_file::error::NONE)
- report_error(1, "Unable to open file (%s)", output_file_str->second->c_str());
+ std::error_condition filerr;
+
+ filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file);
+ if (filerr)
+ report_error(1, "Unable to open file (%s): %s", *output_file_str->second, filerr.message());
// output the metadata
- uint32_t count = output_file->write(&buffer[0], buffer.size());
- if (count != buffer.size())
- report_error(1, "Error writing file (%s)", output_file_str->second->c_str());
+ size_t count;
+ std::tie(filerr, count) = write(*output_file, &buffer[0], buffer.size());
+ if (!filerr)
+ filerr = output_file->flush();
+ 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()));
}
-
- // flush to stdout
else
{
+ // flush to stdout
+ // FIXME: check for errors
fwrite(&buffer[0], 1, buffer.size(), stdout);
fflush(stdout);
}
@@ -2895,18 +3366,18 @@ static void do_dump_metadata(parameters_t &params)
//-------------------------------------------------
-// do_dump_metadata - dump metadata from a CHD
+// do_list_templates - list hard drive templates
//-------------------------------------------------
-static void do_list_templates(parameters_t &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 < ARRAY_LENGTH(s_hd_templates); id++)
+ 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,
@@ -2926,59 +3397,61 @@ static void do_list_templates(parameters_t &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 (argc < 2)
- return print_help(argv[0]);
+ if (args.size() < 2)
+ return print_help(args[0]);
int argnum = 1;
- const char *command = argv[argnum++];
- bool help = (strcmp(command, COMMAND_HELP) == 0);
+ std::string command = args[argnum++];
+ bool help(command == COMMAND_HELP);
if (help)
{
- if (argc <= 2)
- return print_help(argv[0]);
- command = argv[argnum++];
+ if (args.size() <= 2)
+ return print_help(args[0]);
+ command = args[argnum++];
}
// iterate over commands to find our match
for (auto & s_command : s_commands)
- if (strcmp(command, s_command.name) == 0)
+ {
+ if (command == s_command.name)
{
const command_description &desc = s_command;
// print help if that was requested
if (help)
- return print_help(argv[0], desc);
+ return print_help(args[0], desc);
// otherwise, verify the parameters
- parameters_t parameters;
- while (argnum < argc)
+ parameters_map parameters;
+ while (argnum < args.size())
{
// should be an option name
- const char *arg = argv[argnum++];
- if (arg[0] != '-')
- return print_help(argv[0], desc, "Expected option, not parameter");
+ const std::string &arg = args[argnum++];
+ if (arg.empty() || (arg[0] != '-'))
+ return print_help(args[0], desc, "Expected option, not parameter");
// iterate over valid options
int valid;
- for (valid = 0; valid < ARRAY_LENGTH(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++;
// find the matching option description
int optnum;
- for (optnum = 0; optnum < ARRAY_LENGTH(s_options); optnum++)
+ for (optnum = 0; optnum < std::size(s_options); optnum++)
if (strcmp(s_options[optnum].name, validname) == 0)
break;
- assert(optnum != ARRAY_LENGTH(s_options));
+ assert(optnum != std::size(s_options));
// do we match?
const option_description &odesc = s_options[optnum];
@@ -2989,31 +3462,31 @@ int CLIB_DECL main(int argc, char *argv[])
const char *param = "";
if (odesc.parameter)
{
- if (argnum >= argc || argv[argnum][0] == '-')
- return print_help(argv[0], desc, "Option is missing parameter");
- param = argv[argnum++];
+ if (argnum >= args.size() || (!args[argnum].empty() && args[argnum][0] == '-'))
+ return print_help(args[0], desc, "Option is missing parameter");
+ param = args[argnum++].c_str();
}
// add to the map
if (!parameters.insert(std::make_pair(odesc.name, new std::string(param))).second)
- return print_help(argv[0], desc, "Multiple parameters of the same type specified");
+ return print_help(args[0], desc, "Multiple parameters of the same type specified");
break;
}
}
// if not valid, error
- if (valid == ARRAY_LENGTH(desc.valid_options))
- return print_help(argv[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
- for (int valid = 0; valid < ARRAY_LENGTH(desc.valid_options); valid++)
+ for (int valid = 0; valid < std::size(desc.valid_options); valid++)
{
const char *validname = desc.valid_options[valid];
if (validname == nullptr)
break;
if (*validname == REQUIRED[0] && parameters.find(++validname) == parameters.end())
- return print_help(argv[0], desc, "Required parameters missing");
+ return print_help(args[0], desc, "Required parameters missing");
}
// all clear, run the command
@@ -3022,23 +3495,24 @@ int CLIB_DECL main(int argc, char *argv[])
(*s_command.handler)(parameters);
return 0;
}
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
- fprintf(stderr, "CHD error occurred (main): %s\n", chd_file::error_string(err));
+ 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(argv[0]);
+ return print_help(args[0]);
}
diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp
index 1953e7b0538..9ac9c3231ae 100644
--- a/src/tools/floptool.cpp
+++ b/src/tools/floptool.cpp
@@ -1,305 +1,728 @@
// license:BSD-3-Clause
-// copyright-holders:Miodrag Milanovic
+// copyright-holders:Olivier Galibert
/***************************************************************************
- main.c
-
- Floptool command line front end
-
- 20/07/2011 Initial version by Miodrag Milanovic
+ (Floppy) image command-line manager
***************************************************************************/
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <time.h>
-#include <stdarg.h>
-#include <assert.h>
+#include "image_handler.h"
+
+#include "formats/fsblk.h"
#include "corestr.h"
+#include "ioprocs.h"
+#include "path.h"
+#include "strformat.h"
-#include "formats/mfi_dsk.h"
-#include "formats/dfi_dsk.h"
-#include "formats/ipf_dsk.h"
+#include "osdcomm.h"
-#include "formats/hxcmfm_dsk.h"
-#include "formats/ami_dsk.h"
+#include <cassert>
+#include <cctype>
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <exception>
-#include "formats/st_dsk.h"
-#include "formats/pasti_dsk.h"
-#include "formats/dsk_dsk.h"
+static formats_table formats;
-#include "formats/d88_dsk.h"
-#include "formats/imd_dsk.h"
-#include "formats/td0_dsk.h"
-#include "formats/cqm_dsk.h"
-#include "formats/pc_dsk.h"
-#include "formats/naslite_dsk.h"
+static void display_usage(const char *first_argument)
+{
+ std::string exe_name(core_filename_extract_base(first_argument));
-#include "formats/ap_dsk35.h"
-#include "formats/ap2_dsk.h"
+ fprintf(stderr, "Usage: \n");
+ fprintf(stderr, " %s identify <inputfile> [<inputfile> ...] -- Identify an image format\n", exe_name.c_str());
+ fprintf(stderr, " %s flopconvert [input_format|auto] output_format <inputfile> <outputfile> -- Convert a floppy image\n", exe_name.c_str());
+ fprintf(stderr, " %s flopcreate output_format filesystem <outputfile> -- Create a preformatted floppy image\n", exe_name.c_str());
+ fprintf(stderr, " %s flopdir input_format filesystem <image> -- List the contents of a floppy image\n", exe_name.c_str());
+ fprintf(stderr, " %s flopread input_format filesystem <image> <path> <outputfile> -- Extract a file from a floppy image\n", exe_name.c_str());
+ fprintf(stderr, " %s flopwrite input_format filesystem <image> <inputfile> <path> -- Write a file into a floppy image\n", exe_name.c_str());
+ fprintf(stderr, " %s hddir filesystem <image> -- List the contents of a hard disk image\n", exe_name.c_str());
+ fprintf(stderr, " %s hdread filesystem <image> <path> <outputfile> -- Extract a file from a hard disk image\n", exe_name.c_str());
+ fprintf(stderr, " %s hdwrite filesystem <image> <inputfile> <path> -- Write a file into a hard disk image\n", exe_name.c_str());
+ fprintf(stderr, " %s version -- Display the current version of floptool\n", exe_name.c_str());
+}
-#include "formats/atom_dsk.h"
-#include "formats/acorn_dsk.h"
+static void display_formats()
+{
+ int sk = 0;
+ for(const auto &e : formats.floppy_format_info_by_key) {
+ int sz = e.first.size();
+ if(sz > sk)
+ sk = sz;
+ }
-#include "formats/oric_dsk.h"
+ for(const auto &e : formats.filesystem_format_by_key) {
+ int sz = e.first.size();
+ if(sz > sk)
+ sk = sz;
+ }
-#include "formats/applix_dsk.h"
+ for(const auto &e : formats.floppy_create_info_by_key) {
+ int sz = e.first.size();
+ if(sz > sk)
+ sk = sz;
+ }
-#include "formats/hpi_dsk.h"
+ fprintf(stderr, "Supported floppy formats:\n\n");
+ for(const auto &e : formats.floppy_format_info_by_category)
+ if(!e.second.empty()) {
+ fprintf(stderr, "%s:\n", e.first.c_str());
+ for(auto *fif : e.second)
+ fprintf(stderr, " %-*s r%c - %s [%s]\n", sk, fif->m_format->name(), fif->m_format->supports_save() ? 'w' : '-', fif->m_format->description(), fif->m_format->extensions());
+ }
-#include "formats/dvk_mx_dsk.h"
-#include "formats/aim_dsk.h"
-#include "formats/m20_dsk.h"
+ fprintf(stderr, "\n\n");
+ fprintf(stderr, "Supported filesystems (with floppy formatting names):\n\n");
+ for(const auto &e : formats.filesystem_format_by_category)
+ if(!e.second.empty()) {
+ fprintf(stderr, "%s:\n", e.first.c_str());
+ for(const auto &f : e.second) {
+ fprintf(stderr, " %-*s %c%c%c %c%c%c - %s\n",
+ sk,
+ f->m_manager->name(),
+ f->m_floppy || f->m_floppy_raw ? 'F' : '-',
+ f->m_hd ? 'H' : '-',
+ f->m_cd ? 'C' : '-',
+ f->m_manager->can_format() || f->m_floppy_raw ? 'f' : '-',
+ f->m_manager->can_read() ? 'r' : '-',
+ f->m_manager->can_write() ? 'w' : '-',
+ f->m_manager->description());
+ for(auto &f2 : f->m_floppy_create)
+ fprintf(stderr, " %-*s - %s\n",
+ sk,
+ f2->m_name,
+ f2->m_description);
+ }
+ }
+}
-#include "formats/flex_dsk.h"
-#include "formats/uniflex_dsk.h"
+static void display_full_usage(char *argv[])
+{
+ /* Usage */
+ fprintf(stderr, "floptool - Generic floppy image manipulation tool for use with MAME\n\n");
+ display_usage(argv[0]);
+ fprintf(stderr, "\n");
+ display_formats();
+}
+static int identify(int argc, char *argv[])
+{
+ // Need to detect CHDs too
-static floppy_format_type floppy_formats[] = {
- FLOPPY_MFI_FORMAT,
- FLOPPY_DFI_FORMAT,
- FLOPPY_IPF_FORMAT,
+ if(argc<3) {
+ fprintf(stderr, "Missing name of file to identify.\n\n");
+ display_usage(argv[0]);
+ return 1;
+ }
- FLOPPY_MFM_FORMAT,
- FLOPPY_ADF_FORMAT,
+ int sz = 0;
+ for(int i=2; i<argc; i++) {
+ int len = strlen(argv[i]);
+ if(len > sz)
+ sz = len;
+ }
- FLOPPY_ST_FORMAT,
- FLOPPY_MSA_FORMAT,
- FLOPPY_PASTI_FORMAT,
+ for(int i=2; i<argc; i++) {
+ image_handler ih;
+ ih.set_on_disk_path(argv[i]);
+ auto scores = ih.identify(formats);
+ if(scores.empty())
+ printf("%-*s : Unknown format\n", sz, argv[i]);
+ int sz2 = 0;
+ for(const auto &e : scores) {
+ int len = strlen(e.second->m_format->name());
+ if(len > sz2)
+ sz2 = len;
+ }
- FLOPPY_DSK_FORMAT,
+ bool first = true;
+ for(const auto &e : scores) {
+ printf("%-*s %c %c%c%c%c%c - %-*s %s\n", sz, first ? argv[i] : "", first ? ':' : ' ',
+ e.first & 0x10 ? '+' : '.',
+ e.first & 0x08 ? '+' : '.',
+ e.first & 0x04 ? '+' : '.',
+ e.first & 0x02 ? '+' : '.',
+ e.first & 0x01 ? '+' : '.',
+ sz2, e.second->m_format->name(), e.second->m_format->description());
+ first = false;
+ }
+ }
+ return 0;
+}
+
+static const floppy_format_info *find_floppy_source_format(const char *name, image_handler &ih)
+{
+ const floppy_format_info *source_format;
+ if(!core_stricmp(name, "auto")) {
+ auto scores = ih.identify(formats);
+ if(scores.empty()) {
+ fprintf(stderr, "Error: Could not identify the format of file %s\n", ih.get_on_disk_path().c_str());
+ return nullptr;
+ }
+ if(scores.size() >= 2 && scores[0].first == scores[1].first) {
+ fprintf(stderr, "Ambiguous source format. Possible formats:\n");
+ int sz = 0;
+ for(const auto &e : scores) {
+ int len = strlen(e.second->m_format->name());
+ if(len > sz)
+ sz = len;
+ }
+
+ for(const auto &e : scores)
+ printf(" %3d - %-*s %s\n", e.first, sz, e.second->m_format->name(), e.second->m_format->description());
+ return nullptr;
+ }
+ source_format = scores[0].second;
- FLOPPY_D88_FORMAT,
- FLOPPY_IMD_FORMAT,
- FLOPPY_TD0_FORMAT,
- FLOPPY_CQM_FORMAT,
- FLOPPY_PC_FORMAT,
- FLOPPY_NASLITE_FORMAT,
+ } else {
+ source_format = formats.find_floppy_format_info_by_key(name);
+ if(!source_format) {
+ fprintf(stderr, "Error: Format '%s' unknown\n", name);
+ return nullptr;
- FLOPPY_DC42_FORMAT,
- FLOPPY_A216S_FORMAT,
- FLOPPY_RWTS18_FORMAT,
- FLOPPY_EDD_FORMAT,
- FLOPPY_WOZ_FORMAT,
+ }
+ }
+ return source_format;
+}
- FLOPPY_ATOM_FORMAT,
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_ACORN_DOS_FORMAT,
- FLOPPY_ACORN_ADFS_OLD_FORMAT,
- FLOPPY_ACORN_ADFS_NEW_FORMAT,
+static int flopconvert(int argc, char *argv[])
+{
+ if(argc!=6) {
+ fprintf(stderr, "Incorrect number of arguments.\n\n");
+ display_usage(argv[0]);
+ return 1;
+ }
- FLOPPY_ORIC_DSK_FORMAT,
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
- FLOPPY_APPLIX_FORMAT,
+ const floppy_format_info *source_format = find_floppy_source_format(argv[2], ih);
+ if(!source_format)
+ return 1;
- FLOPPY_HPI_FORMAT,
+ const floppy_format_info *dest_format = formats.find_floppy_format_info_by_key(argv[3]);
+ if(!dest_format) {
+ fprintf(stderr, "Error: Format '%s' unknown\n", argv[3]);
+ return 1;
+ }
+ if(!dest_format->m_format->supports_save()) {
+ fprintf(stderr, "Error: Saving to format '%s' unsupported\n", argv[3]);
+ return 1;
+ }
- FLOPPY_DVK_MX_FORMAT,
- FLOPPY_AIM_FORMAT,
- FLOPPY_M20_FORMAT,
+ if(ih.floppy_load(*source_format)) {
+ fprintf(stderr, "Error: Loading as format '%s' failed\n", source_format->m_format->name());
+ return 1;
+ }
- FLOPPY_FLEX_FORMAT,
- FLOPPY_UNIFLEX_FORMAT
-};
+ ih.set_on_disk_path(argv[5]);
-void CLIB_DECL ATTR_PRINTF(1,2) logerror(const char *format, ...)
-{
- va_list arg;
- va_start(arg, format);
- vprintf(format, arg);
- va_end(arg);
+ if(ih.floppy_save(*dest_format)) {
+ fprintf(stderr, "Error: Saving as format '%s' failed\n", dest_format->m_format->name());
+ return 1;
+ }
+
+ return 0;
}
-enum { FORMAT_COUNT = ARRAY_LENGTH(floppy_formats) };
+static fs::meta_data extract_meta_data(int &argc, char *argv[])
+{
+ fs::meta_data result;
-static floppy_image_format_t *formats[FORMAT_COUNT];
+ int new_argc = 0;
+ for (int i = 0; i < argc; i++)
+ {
+ std::optional<fs::meta_name> attrname;
+ if (argv[i][0] == '-' && i < argc - 1)
+ attrname = fs::meta_data::from_entry_name(&argv[i][1]);
+
+ if (attrname)
+ {
+ // we found a metadata variable; set it
+ result.set(*attrname, argv[i + 1]);
+ i++;
+ }
+ else
+ {
+ // we didn't; update argv
+ argv[new_argc++] = argv[i];
+ }
+ }
+
+ // we're done; update the argument count
+ argc = new_argc;
+ return result;
+}
-static void init_formats()
+static int flopcreate(int argc, char *argv[])
{
- for(int i=0; i != FORMAT_COUNT; i++)
- formats[i] = floppy_formats[i]();
+ fs::meta_data meta = extract_meta_data(argc, argv);
+
+ if(argc!=5) {
+ fprintf(stderr, "Incorrect number of arguments.\n\n");
+ display_usage(argv[0]);
+ return 1;
+ }
+
+ auto dest_format = formats.find_floppy_format_info_by_key(argv[2]);
+ if(!dest_format) {
+ fprintf(stderr, "Error: Floppy format '%s' unknown\n", argv[2]);
+ return 1;
+ }
+ if(!dest_format->m_format->supports_save()) {
+ fprintf(stderr, "Error: Saving to format '%s' unsupported\n", argv[2]);
+ return 1;
+ }
+
+ auto create_fs = formats.find_floppy_create_info_by_key(argv[3]);
+ if(!create_fs) {
+ fprintf(stderr, "Error: Floppy creation format '%s' unknown\n", argv[3]);
+ return 1;
+ }
+ if(create_fs->m_manager && !create_fs->m_manager->can_format()) {
+ fprintf(stderr, "Error: Floppy creation format '%s' does not support creating new images\n", argv[3]);
+ return 1;
+ }
+
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
+
+ ih.floppy_create(*create_fs, meta);
+ return ih.floppy_save(*dest_format);
}
-static floppy_image_format_t *find_format_by_name(const char *name)
+static void dir_scan(fs::filesystem_t *fs, u32 depth, const std::vector<std::string> &path, std::vector<std::vector<std::string>> &entries, const std::unordered_map<fs::meta_name, size_t> &nmap, size_t nc, const std::vector<fs::meta_description> &dmetad, const std::vector<fs::meta_description> &fmetad)
{
- for(int i=0; i != FORMAT_COUNT; i++)
- if(!core_stricmp(name, formats[i]->name()))
- return formats[i];
- return nullptr;
+ std::string head;
+ for(u32 i = 0; i != depth; i++)
+ head += " ";
+ auto [err, contents] = fs->directory_contents(path);
+ if(err)
+ return; // FIXME: don't swallow errors
+ for(const auto &c : contents) {
+ size_t id = entries.size();
+ entries.resize(id+1);
+ entries[id].resize(nc);
+ switch(c.m_type) {
+ case fs::dir_entry_type::dir: {
+ for(const auto &m : dmetad) {
+ if(!c.m_meta.has(m.m_name))
+ continue;
+ size_t slot = nmap.find(m.m_name)->second;
+ std::string val = c.m_meta.get(m.m_name).as_string();
+ if(slot == 0)
+ val = head + "dir " + val;
+ entries[id][slot] = val;
+ }
+ auto npath = path;
+ npath.push_back(c.m_name);
+ dir_scan(fs, depth+1, npath, entries, nmap, nc, dmetad, fmetad);
+ break;
+ }
+ case fs::dir_entry_type::file: {
+ for(const auto &m : fmetad) {
+ if(!c.m_meta.has(m.m_name))
+ continue;
+ size_t slot = nmap.find(m.m_name)->second;
+ std::string val = c.m_meta.get(m.m_name).as_string();
+ if(slot == 0)
+ val = head + "file " + val;
+ entries[id][slot] = val;
+ }
+ break;
+ }
+ }
+ }
}
-static floppy_image_format_t *find_format_by_identify(io_generic *image)
+static int generic_dir(image_handler &ih)
{
- int best = 0;
- floppy_image_format_t *best_fif = nullptr;
-
- for(int i = 0; i != FORMAT_COUNT; i++) {
- floppy_image_format_t *fif = formats[i];
- int score = fif->identify(image, floppy_image::FF_UNKNOWN);
- if(score > best) {
- best = score;
- best_fif = fif;
+ auto [fsm, fs] = ih.get_fs();
+ auto vmetad = fsm->volume_meta_description();
+ auto fmetad = fsm->file_meta_description();
+ auto dmetad = fsm->directory_meta_description();
+
+ auto vmeta = fs->volume_metadata();
+ if(!vmeta.empty()) {
+ std::string vinf = "Volume:";
+ for(const auto &e : vmetad)
+ vinf += util::string_format(" %s=%s", fs::meta_data::entry_name(e.m_name), vmeta.get(e.m_name).as_string());
+ printf("%s\n\n", vinf.c_str());
+ }
+
+ std::vector<fs::meta_name> names;
+ names.push_back(fs::meta_name::name);
+ for(const auto &e : fmetad)
+ if(e.m_name != fs::meta_name::name)
+ names.push_back(e.m_name);
+ for(const auto &e : dmetad)
+ if(std::find(names.begin(), names.end(), e.m_name) == names.end())
+ names.push_back(e.m_name);
+
+ std::unordered_map<fs::meta_name, size_t> nmap;
+ for(size_t i = 0; i != names.size(); i++)
+ nmap[names[i]] = i;
+
+ std::vector<std::vector<std::string>> entries;
+
+ entries.resize(1);
+ for(fs::meta_name n : names)
+ entries[0].push_back(fs::meta_data::entry_name(n));
+
+ dir_scan(fs, 0, std::vector<std::string>(), entries, nmap, names.size(), dmetad, fmetad);
+
+ std::vector<u32> sizes(names.size());
+
+ for(const auto &e : entries)
+ for(unsigned int i=0; i != names.size(); i++)
+ sizes[i] = std::max<u32>(sizes[i], e[i].size());
+
+ for(const auto &e : entries) {
+ std::string l;
+ for(unsigned int i=0; i != names.size(); i++) {
+ if(i)
+ l += ' ';
+ l += util::string_format("%-*s", sizes[i], e[i]);
}
+ printf("%s\n", l.c_str());
}
- return best_fif;
+
+ return 0;
}
-static void display_usage()
+static int flopdir(int argc, char *argv[])
{
- fprintf(stderr, "Usage: \n");
- fprintf(stderr, " floptool.exe identify <inputfile> [<inputfile> ...]\n");
- fprintf(stderr, " floptool.exe convert [input_format|auto] output_format <inputfile> <outputfile>\n");
+ if(argc!=5) {
+ fprintf(stderr, "Incorrect number of arguments.\n\n");
+ display_usage(argv[0]);
+ return 1;
+ }
+
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
+
+ const floppy_format_info *source_format = find_floppy_source_format(argv[2], ih);
+ if(!source_format)
+ return 1;
+
+ auto fs = formats.find_filesystem_format_by_key(argv[3]);
+ if(!fs) {
+ fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[3]);
+ return 1;
+ }
+
+ if(!fs->m_manager || !fs->m_manager->can_read()) {
+ fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[3]);
+ return 1;
+ }
+
+ if(ih.floppy_load(*source_format)) {
+ fprintf(stderr, "Error: Loading as format '%s' failed\n", source_format->m_format->name());
+ return 1;
+ }
+
+ if(ih.floppy_mount_fs(*fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
+ return 1;
+ }
+
+ return generic_dir(ih);
}
-static void display_formats()
+static int hddir(int argc, char *argv[])
{
- fprintf(stderr, "Supported formats:\n\n");
- for(int i = 0; i != FORMAT_COUNT; i++)
- {
- floppy_image_format_t *fif = formats[i];
- fprintf(stderr, "%15s - %s [%s]\n", fif->name(), fif->description(), fif->extensions());
+ if(argc!=4) {
+ fprintf(stderr, "Incorrect number of arguments.\n\n");
+ display_usage(argv[0]);
+ return 1;
}
+
+ image_handler ih;
+ ih.set_on_disk_path(argv[3]);
+
+ auto fs = formats.find_filesystem_format_by_key(argv[2]);
+ if(!fs) {
+ fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[2]);
+ return 1;
+ }
+
+ if(!fs->m_manager || !fs->m_manager->can_read()) {
+ fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[2]);
+ return 1;
+ }
+
+ if(ih.hd_mount_fs(*fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
+ return 1;
+ }
+
+ return generic_dir(ih);
}
-static void display_full_usage()
+
+static int generic_read(image_handler &ih, const char *srcpath, const char *dstpath)
{
- /* Usage */
- fprintf(stderr, "floptool - Generic floppy image manipulation tool for use with MAME\n\n");
- display_usage();
- fprintf(stderr, "\n");
- display_formats();
- fprintf(stderr, "\nExample usage:\n");
- fprintf(stderr, " floptool.exe identify image.dsk\n\n");
+ auto [fsm, fs] = ih.get_fs();
+ std::ignore = fsm;
+
+ std::vector<std::string> path = ih.path_split(srcpath);
+ auto [err, dfork] = fs->file_read(path);
+ if(err) {
+ fprintf(stderr, "File reading failed: %s\n", err.message().c_str());
+ return 1;
+ }
+ image_handler::fsave(dstpath, dfork);
+
+ auto [err2, rfork] = fs->file_rsrc_read(path);
+ if(!err2 && !rfork.empty())
+ image_handler::fsave_rsrc(image_handler::path_make_rsrc(dstpath), rfork);
+
+ return 0;
}
-static int identify(int argc, char *argv[])
+
+static int flopread(int argc, char *argv[])
{
- if (argc<3) {
- fprintf(stderr, "Missing name of file to identify.\n\n");
- display_usage();
+ if(argc!=7) {
+ fprintf(stderr, "Incorrect number of arguments.\n\n");
+ display_usage(argv[0]);
return 1;
}
- for(int i=2; i<argc; i++) {
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[i]);
- FILE *f = fopen(argv[i], "rb");
- if (!f) {
- perror(msg);
- return 1;
- }
- io_generic io;
- io.file = f;
- io.procs = &stdio_ioprocs_noclose;
- io.filler = 0xff;
-
- floppy_image_format_t *best_fif = find_format_by_identify(&io);
- if (best_fif)
- printf("%s : %s\n", argv[i], best_fif->description());
- else
- printf("%s : Unknown format\n", argv[i]);
- fclose(f);
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
+
+ const floppy_format_info *source_format = find_floppy_source_format(argv[2], ih);
+ if(!source_format)
+ return 1;
+
+ auto fs = formats.find_filesystem_format_by_key(argv[3]);
+ if(!fs) {
+ fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[3]);
+ return 1;
}
- return 0;
+
+ if(!fs->m_manager || !fs->m_manager->can_read()) {
+ fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[3]);
+ return 1;
+ }
+
+ if(ih.floppy_load(*source_format)) {
+ fprintf(stderr, "Error: Loading as format '%s' failed\n", source_format->m_format->name());
+ return 1;
+ }
+
+ if(ih.floppy_mount_fs(*fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
+ return 1;
+ }
+
+ return generic_read(ih, argv[5], argv[6]);
}
-static int convert(int argc, char *argv[])
+static int hdread(int argc, char *argv[])
{
- if (argc!=6) {
+ if(argc!=6) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
- display_usage();
+ display_usage(argv[0]);
return 1;
}
- floppy_image_format_t *source_format, *dest_format;
+ image_handler ih;
+ ih.set_on_disk_path(argv[3]);
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[4]);
- FILE *f = fopen(argv[4], "rb");
- if (!f) {
- perror(msg);
+ auto fs = formats.find_filesystem_format_by_key(argv[2]);
+ if(!fs) {
+ fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[2]);
return 1;
}
- io_generic source_io;
- source_io.file = f;
- source_io.procs = &stdio_ioprocs_noclose;
- source_io.filler = 0xff;
- if(!core_stricmp(argv[2], "auto")) {
- source_format = find_format_by_identify(&source_io);
- if(!source_format) {
- fprintf(stderr, "Error: Could not identify the format of file %s\n", argv[4]);
+ if(!fs->m_manager || !fs->m_manager->can_read()) {
+ fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[2]);
+ return 1;
+ }
+
+ if(ih.hd_mount_fs(*fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
+ return 1;
+ }
+
+ return generic_read(ih, argv[4], argv[5]);
+}
+
+
+
+static int generic_write(image_handler &ih, const char *srcpath, const char *dstpath)
+{
+ auto [fsm, fs] = ih.get_fs();
+
+ std::vector<std::string> path = ih.path_split(dstpath);
+ auto [err, meta] = fs->metadata(path);
+ std::ignore = meta;
+
+ 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 failed: %s\n", err.message().c_str());
return 1;
}
+ }
- } else {
- source_format = find_format_by_name(argv[2]);
- if(!source_format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[2]);
- return 1;
+ auto dfork = image_handler::fload(srcpath);
+ err = fs->file_write(path, dfork);
+ if(err) {
+ fprintf(stderr, "File writing failed: %s\n", err.message().c_str());
+ return 1;
+ }
+
+ if(fsm->has_rsrc()) {
+ std::string rpath = image_handler::path_make_rsrc(dstpath);
+
+ if(image_handler::fexists(rpath)) {
+ auto rfork = image_handler::fload_rsrc(rpath);
+ if(!rfork.empty()) {
+ err = fs->file_rsrc_write(path, rfork);
+ fprintf(stderr, "File resource fork writing failed: %s\n", err.message().c_str());
+ return 1;
+ }
}
}
- dest_format = find_format_by_name(argv[3]);
- if(!dest_format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[3]);
+ return 0;
+}
+
+
+static int flopwrite(int argc, char *argv[])
+{
+ if(argc!=7) {
+ fprintf(stderr, "Incorrect number of arguments.\n\n");
+ display_usage(argv[0]);
+ return 1;
+ }
+
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
+
+ const floppy_format_info *source_format = find_floppy_source_format(argv[2], ih);
+ if(!source_format)
+ return 1;
+
+ auto fs = formats.find_filesystem_format_by_key(argv[3]);
+ if(!fs) {
+ fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[3]);
+ return 1;
+ }
+
+ if(!fs->m_manager || !fs->m_manager->can_read()) {
+ fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[3]);
return 1;
}
- if(!dest_format->supports_save()) {
- fprintf(stderr, "Error: saving to format '%s' unsupported\n", argv[3]);
+
+ if(ih.floppy_load(*source_format)) {
+ fprintf(stderr, "Error: Loading as format '%s' failed\n", source_format->m_format->name());
+ return 1;
+ }
+
+ if(ih.floppy_mount_fs(*fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
+ return 1;
+ }
+
+ int err = generic_write(ih, argv[5], argv[6]);
+ if(err)
+ return err;
+
+ ih.fs_to_floppy();
+ if(ih.floppy_save(*source_format))
+ return 1;
+
+ return 0;
+}
+
+static int hdwrite(int argc, char *argv[])
+{
+ if(argc!=6) {
+ fprintf(stderr, "Incorrect number of arguments.\n\n");
+ display_usage(argv[0]);
return 1;
}
- sprintf(msg, "Error opening %s for writing", argv[5]);
- f = fopen(argv[5], "wb");
- if (!f) {
- perror(msg);
+
+ image_handler ih;
+ ih.set_on_disk_path(argv[3]);
+
+ auto fs = formats.find_filesystem_format_by_key(argv[2]);
+ if(!fs) {
+ fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[2]);
return 1;
}
- io_generic dest_io;
- dest_io.file = f;
- dest_io.procs = &stdio_ioprocs_noclose;
- dest_io.filler = 0xff;
- floppy_image image(84, 2, floppy_image::FF_UNKNOWN);
- if(!source_format->load(&source_io, floppy_image::FF_UNKNOWN, &image)) {
- fprintf(stderr, "Error: parsing input file as '%s' failed\n", source_format->name());
+ if(!fs->m_manager || !fs->m_manager->can_read()) {
+ fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[2]);
return 1;
}
- if(!dest_format->save(&dest_io, &image)) {
- fprintf(stderr, "Error: writing output file as '%s' failed\n", dest_format->name());
+ if(ih.hd_mount_fs(*fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
return 1;
}
- fclose((FILE *)source_io.file);
- fclose((FILE *)dest_io.file);
+ return generic_write(ih, argv[4], argv[5]);
+}
+static int version(int argc, char *argv[])
+{
+ extern const char build_version[];
+ fprintf(stdout, "%s\n", build_version);
return 0;
}
int CLIB_DECL main(int argc, char *argv[])
{
- init_formats();
+ formats.init();
- if (argc == 1) {
- display_full_usage();
+ if(argc == 1) {
+ display_full_usage(argv);
return 0;
}
- if (!core_stricmp("identify", argv[1]))
- return identify(argc, argv);
- else if (!core_stricmp("convert", argv[1]))
- return convert(argc, argv);
- else {
- fprintf(stderr, "Unknown command '%s'\n\n", argv[1]);
- display_usage();
+ try {
+ if(!core_stricmp("identify", argv[1]))
+ return identify(argc, argv);
+ else if(!core_stricmp("flopconvert", argv[1]))
+ return flopconvert(argc, argv);
+ else if(!core_stricmp("flopcreate", argv[1]))
+ return flopcreate(argc, argv);
+ else if(!core_stricmp("flopdir", argv[1]))
+ return flopdir(argc, argv);
+ else if(!core_stricmp("flopread", argv[1]))
+ return flopread(argc, argv);
+ else if(!core_stricmp("flopwrite", argv[1]))
+ return flopwrite(argc, argv);
+ else if(!core_stricmp("hddir", argv[1]))
+ return hddir(argc, argv);
+ else if(!core_stricmp("hdread", argv[1]))
+ return hdread(argc, argv);
+ else if(!core_stricmp("hdwrite", argv[1]))
+ return hdwrite(argc, argv);
+ else if (!core_stricmp("version", argv[1]))
+ return version(argc, argv);
+ else {
+ fprintf(stderr, "Unknown command '%s'\n\n", argv[1]);
+ display_usage(argv[0]);
+ return 1;
+ }
+ } catch(const std::exception &err) {
+ fprintf(stderr, "Error: %s\n", err.what());
return 1;
}
}
diff --git a/src/tools/image_handler.cpp b/src/tools/image_handler.cpp
new file mode 100644
index 00000000000..14976516e1c
--- /dev/null
+++ b/src/tools/image_handler.cpp
@@ -0,0 +1,397 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Image generic handler class and helpers
+
+#include "image_handler.h"
+
+#include "formats/all.h"
+#include "formats/fsblk_vec.h"
+#include "formats/fs_unformatted.h"
+
+#include "ioprocs.h"
+#include "ioprocsfill.h"
+#include "ioprocsvec.h"
+#include "multibyte.h"
+#include "strformat.h"
+
+#include <algorithm>
+
+
+// Format enumeration
+
+namespace {
+ struct enumerator : public mame_formats_enumerator {
+ formats_table *m_table;
+ std::string m_category;
+
+ enumerator(formats_table *table) : mame_formats_enumerator(), m_table(table), m_category("None") {}
+
+ virtual ~enumerator() = default;
+ virtual void add(const cassette_image::Format *const *formats) {}
+
+ virtual void category(const char *name) {
+ m_category = name;
+ }
+
+ virtual void add(const floppy_image_format_t &format) {
+ m_table->floppy_format_infos.emplace_back(std::make_unique<floppy_format_info>(&format, m_category));
+ }
+
+ virtual void add(const fs::manager_t &fs) {
+ m_table->filesystem_formats.emplace_back(std::make_unique<filesystem_format>(&fs, m_category));
+ }
+ };
+
+ struct fs_enum : public fs::manager_t::floppy_enumerator {
+ filesystem_format *m_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;
+ m_format->m_floppy_create.emplace_back(std::make_unique<floppy_create_info>(m_format->m_manager, &type, image_size, name, description));
+ }
+
+ virtual void add_raw(const char *name, u32 key, const char *description) override {
+ m_format->m_floppy_raw = true;
+ m_format->m_floppy_create.emplace_back(std::make_unique<floppy_create_info>(name, key, description));
+ }
+ };
+}
+
+void formats_table::init()
+{
+ std::vector<uint32_t> variants;
+
+ enumerator en(this);
+ mame_formats_full_list(en);
+
+ for(auto &f : filesystem_formats) {
+ fs_enum fen(f.get(), floppy_image::FF_UNKNOWN, variants);
+ f->m_manager->enumerate_f(fen);
+ }
+
+ for(auto &f : floppy_format_infos) {
+ auto *ff = f.get();
+ std::string key = ff->m_format->name();
+ auto i = floppy_format_info_by_key.find(key);
+ if(i != floppy_format_info_by_key.end()) {
+ fprintf(stderr, "Collision on floppy format name %s between \"%s\" and \"%s\".\n",
+ ff->m_format->name(),
+ ff->m_format->description(),
+ i->second->m_format->description());
+ exit(1);
+ }
+
+ floppy_format_info_by_key[key] = ff;
+ floppy_format_info_by_category[ff->m_category].push_back(ff);
+ }
+
+ for(auto &f : filesystem_formats) {
+ auto *ff = f.get();
+ std::string key = ff->m_manager->name();
+ auto i = filesystem_format_by_key.find(key);
+ if(i != filesystem_format_by_key.end()) {
+ fprintf(stderr, "Collision on filesystem name %s between \"%s\" and \"%s\".\n",
+ ff->m_manager->name(),
+ ff->m_manager->description(),
+ i->second->m_manager->description());
+ exit(1);
+ }
+
+ filesystem_format_by_key[key] = ff;
+ filesystem_format_by_category[ff->m_category].push_back(ff);
+
+ for(auto &f2 : ff->m_floppy_create) {
+ auto *ff2 = f2.get();
+ key = ff2->m_name;
+ auto i = floppy_create_info_by_key.find(key);
+ if(i != floppy_create_info_by_key.end()) {
+ fprintf(stderr, "Collision on floppy create name %s between \"%s\" and \"%s\".\n",
+ ff2->m_name,
+ ff2->m_description,
+ i->second->m_description);
+ exit(1);
+ }
+
+ floppy_create_info_by_key[key] = ff2;
+ }
+ }
+}
+
+const floppy_format_info *formats_table::find_floppy_format_info_by_key(const std::string &key) const
+{
+ auto i = floppy_format_info_by_key.find(key);
+ return i == floppy_format_info_by_key.end() ? nullptr : i->second;
+}
+
+const filesystem_format *formats_table::find_filesystem_format_by_key(const std::string &key) const
+{
+ auto i = filesystem_format_by_key.find(key);
+ return i == filesystem_format_by_key.end() ? nullptr : i->second;
+}
+
+const floppy_create_info *formats_table::find_floppy_create_info_by_key(const std::string &key) const
+{
+ auto i = floppy_create_info_by_key.find(key);
+ return i == floppy_create_info_by_key.end() ? nullptr : i->second;
+}
+
+
+// Image handling
+
+std::vector<u8> image_handler::fload(std::string path)
+{
+ auto fi = fopen(path.c_str(), "rb");
+ if(!fi) {
+ perror(util::string_format("Error opening %s for reading", path).c_str());
+ exit(1);
+ }
+ fseek(fi, 0, SEEK_END);
+ long size = ftell(fi);
+ std::vector<u8> filedata(size);
+ fseek(fi, 0, SEEK_SET);
+ fread(filedata.data(), filedata.size(), 1, fi);
+ fclose(fi);
+
+ return filedata;
+}
+
+std::vector<u8> image_handler::fload_rsrc(std::string path)
+{
+ auto filedata = fload(path);
+ const u8 *head = filedata.data();
+
+ if(get_u32be(head+0x00) == 0x00051607 &&
+ get_u32be(head+0x04) == 0x00020000) {
+ u16 nent = get_u16be(head+0x18);
+ for(u16 i=0; i != nent; i++) {
+ const u8 *e = head + 12*i;
+ if(get_u32be(e+0) == 2) {
+ u32 start = get_u32be(e+4);
+ u32 len = get_u32be(e+8);
+ filedata.erase(filedata.begin(), filedata.begin() + start);
+ filedata.erase(filedata.begin() + len, filedata.end());
+ return filedata;
+ }
+ }
+ }
+ filedata.clear();
+ return filedata;
+}
+
+void image_handler::fsave(std::string path, const std::vector<u8> &data)
+{
+ auto fo = fopen(path.c_str(), "wb");
+ if(!fo) {
+ perror(util::string_format("Error opening %s for writing", path).c_str());
+ exit(1);
+ }
+
+ fwrite(data.data(), data.size(), 1, fo);
+ fclose(fo);
+}
+
+void image_handler::fsave_rsrc(std::string path, const std::vector<u8> &data)
+{
+ u8 head[0x2a];
+
+ put_u32be(head+0x00, 0x00051607); // Magic
+ put_u32be(head+0x04, 0x00020000); // Version
+ memset(head+0x08, 0, 16); // Filler
+ put_u16be(head+0x18, 1); // Number of entries
+ put_u32be(head+0x1a, 2); // Resource fork
+ put_u32be(head+0x22, 0x2a); // Offset in the file
+ put_u32be(head+0x26, data.size()); // Length
+
+ auto fo = fopen(path.c_str(), "wb");
+ if(!fo) {
+ perror(util::string_format("Error opening %s for writing", path).c_str());
+ exit(1);
+ }
+
+ fwrite(head, sizeof(head), 1, fo);
+ fwrite(data.data(), data.size(), 1, fo);
+ fclose(fo);
+}
+
+image_handler::image_handler() : m_floppy_image(84, 2, floppy_image::FF_UNKNOWN)
+{
+}
+
+void image_handler::set_on_disk_path(std::string path)
+{
+ m_on_disk_path = path;
+}
+
+std::vector<std::pair<u8, const floppy_format_info *>> image_handler::identify(const formats_table &formats)
+{
+ std::vector<std::pair<u8, const floppy_format_info *>> res;
+ std::vector<uint32_t> variants;
+
+ FILE *f = fopen(m_on_disk_path.c_str(), "rb");
+ if (!f) {
+ std::string msg = util::string_format("Error opening %s for reading", m_on_disk_path);
+ perror(msg.c_str());
+ return res;
+ }
+
+ auto io = util::stdio_read(f, 0xff);
+
+ for(const auto &e : formats.floppy_format_info_by_key) {
+ u8 score = e.second->m_format->identify(*io, floppy_image::FF_UNKNOWN, variants);
+ if(score && e.second->m_format->extension_matches(m_on_disk_path.c_str()))
+ score |= floppy_image_format_t::FIFID_EXT;
+ if(score)
+ 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;
+}
+
+bool image_handler::floppy_load(const floppy_format_info &format)
+{
+ std::vector<uint32_t> variants;
+ FILE *f = fopen(m_on_disk_path.c_str(), "rb");
+ if (!f) {
+ std::string msg = util::string_format("Error opening %s for reading", m_on_disk_path);
+ perror(msg.c_str());
+ return true;
+ }
+
+ auto io = util::stdio_read(f, 0xff);
+
+ return !format.m_format->load(*io, floppy_image::FF_UNKNOWN, variants, m_floppy_image);
+}
+
+bool image_handler::floppy_save(const floppy_format_info &format) const
+{
+ std::vector<uint32_t> variants;
+ FILE *f = fopen(m_on_disk_path.c_str(), "wb");
+ if (!f) {
+ auto msg = util::string_format("Error opening %s for writing", m_on_disk_path);
+ perror(msg.c_str());
+ return true;
+ }
+
+ auto io = util::stdio_read_write(f, 0xff);
+
+ return !format.m_format->save(*io, variants, m_floppy_image);
+}
+
+void image_handler::floppy_create(const floppy_create_info &format, fs::meta_data meta)
+{
+ if(format.m_type) {
+ std::vector<uint32_t> variants;
+ std::vector<u8> img(format.m_image_size);
+ fs::fsblk_vec_t blockdev(img);
+ auto fs = format.m_manager->mount(blockdev);
+ fs->format(meta);
+
+ auto io = util::ram_read(img.data(), img.size(), 0xff);
+ format.m_type->load(*io, floppy_image::FF_UNKNOWN, variants, m_floppy_image);
+ } else {
+ fs::unformatted_image::format(format.m_key, &m_floppy_image);
+ }
+}
+
+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 : fmtcopy.m_floppy_create) {
+ if(ci->m_type != m_floppy_fs_converter) {
+ std::vector<uint32_t> variants;
+ m_floppy_fs_converter = ci->m_type;
+ m_sector_image.clear();
+ util::random_read_write_fill_wrapper<util::vector_read_write_adapter<u8>, 0xff> io(m_sector_image);
+ m_floppy_fs_converter->save(io, variants, m_floppy_image);
+ }
+
+ if(ci->m_image_size == m_sector_image.size())
+ goto success;
+ }
+ m_floppy_fs_converter = nullptr;
+ m_sector_image.clear();
+ return true;
+
+ success:
+ m_fsblk.reset(new fs::fsblk_vec_t(m_sector_image));
+ m_fsm = format.m_manager;
+ m_fs = m_fsm->mount(*m_fsblk);
+ return false;
+}
+
+bool image_handler::hd_mount_fs(const filesystem_format &format)
+{
+ // Should use the chd mechanisms, one thing at a time...
+
+ m_sector_image = fload(m_on_disk_path);
+ m_fsblk.reset(new fs::fsblk_vec_t(m_sector_image));
+ m_fsm = format.m_manager;
+ m_fs = m_fsm->mount(*m_fsblk);
+ return false;
+}
+
+void image_handler::fs_to_floppy()
+{
+ std::vector<uint32_t> variants;
+ auto io = util::ram_read(m_sector_image.data(), m_sector_image.size(), 0xff);
+ m_floppy_fs_converter->load(*io, floppy_image::FF_UNKNOWN, variants, m_floppy_image);
+}
+
+std::vector<std::string> image_handler::path_split(std::string path) const
+{
+ std::string opath = path;
+ std::vector<std::string> rpath;
+ if(m_fsm->has_subdirectories()) {
+ std::string element;
+ char sep = m_fsm->directory_separator();
+ for(char c : opath) {
+ if(c == sep) {
+ if(!element.empty()) {
+ rpath.push_back(element);
+ element.clear();
+ }
+ } else
+ element += c;
+ }
+ if(!element.empty())
+ rpath.push_back(element);
+
+ } else
+ rpath.push_back(opath);
+
+ return rpath;
+}
+
+bool image_handler::fexists(std::string path)
+{
+ auto f = fopen(path.c_str(), "rb");
+ if(f != nullptr) {
+ fclose(f);
+ return true;
+ }
+ return false;
+}
+
+
+std::string image_handler::path_make_rsrc(std::string path)
+{
+ auto p = path.end();
+ while(p != path.begin() && p[-1] != '/')
+ p--;
+ std::string rpath(path.begin(), p);
+ rpath += "._";
+ rpath += std::string(p, path.end());
+ return rpath;
+}
+
diff --git a/src/tools/image_handler.h b/src/tools/image_handler.h
new file mode 100644
index 00000000000..3577f60dbf8
--- /dev/null
+++ b/src/tools/image_handler.h
@@ -0,0 +1,119 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Image generic handler class and helpers
+
+#ifndef MAME_TOOLS_IMAGE_HANDLER_H
+#define MAME_TOOLS_IMAGE_HANDLER_H
+
+#pragma once
+
+#include "formats/flopimg.h"
+#include "formats/fsmgr.h"
+#include "harddisk.h"
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+
+using u8 = uint8_t;
+using u16 = uint16_t;
+using u32 = uint32_t;
+
+struct floppy_format_info {
+ const floppy_image_format_t *m_format;
+ std::string m_category;
+
+ floppy_format_info(const floppy_image_format_t *format, std::string category) : m_format(format), m_category(category) {}
+};
+
+struct floppy_create_info {
+ const fs::manager_t *m_manager;
+
+ const floppy_image_format_t *m_type;
+ u32 m_image_size;
+ u32 m_key;
+ const char *m_name;
+ const char *m_description;
+
+ floppy_create_info(const fs::manager_t *manager, const floppy_image_format_t *type, u32 image_size, const char *name, const char *description) :
+ m_manager(manager), m_type(type), m_image_size(image_size), m_key(0), m_name(name), m_description(description)
+ { }
+
+ floppy_create_info(const char *name, u32 key, const char *description) :
+ m_manager(nullptr), m_type(nullptr), m_image_size(0), m_key(key), m_name(name), m_description(description)
+ { }
+};
+
+struct filesystem_format {
+ const fs::manager_t *m_manager;
+ std::vector<std::unique_ptr<floppy_create_info>> m_floppy_create;
+ std::string m_category;
+ bool m_floppy, m_floppy_raw, m_hd, m_cd;
+
+ filesystem_format(const fs::manager_t *manager, std::string category) : m_manager(manager), m_category(category), m_floppy(false), m_floppy_raw(false), m_hd(false), m_cd(false) {}
+};
+
+struct formats_table {
+ std::vector<std::unique_ptr<floppy_format_info>> floppy_format_infos;
+ std::vector<std::unique_ptr<filesystem_format>> filesystem_formats;
+
+ std::map<std::string, const floppy_format_info *> floppy_format_info_by_key;
+ std::map<std::string, const filesystem_format *> filesystem_format_by_key;
+ std::map<std::string, const floppy_create_info *> floppy_create_info_by_key;
+
+ std::map<std::string, std::vector<const floppy_format_info *>> floppy_format_info_by_category;
+ std::map<std::string, std::vector<const filesystem_format *>> filesystem_format_by_category;
+
+ void init();
+
+ const floppy_format_info *find_floppy_format_info_by_key(const std::string &key) const;
+ const filesystem_format *find_filesystem_format_by_key(const std::string &key) const;
+ const floppy_create_info *find_floppy_create_info_by_key(const std::string &key) const;
+};
+
+class image_handler {
+public:
+ image_handler();
+
+ void set_on_disk_path(std::string path);
+ const std::string &get_on_disk_path() const { return m_on_disk_path; }
+
+ std::vector<std::pair<u8, const floppy_format_info *>> identify(const formats_table &formats);
+
+ bool floppy_load(const floppy_format_info &format);
+ bool floppy_save(const floppy_format_info &format) const;
+
+ void floppy_create(const floppy_create_info &format, fs::meta_data meta);
+ bool floppy_mount_fs(const filesystem_format &format);
+ bool hd_mount_fs(const filesystem_format &format);
+ void fs_to_floppy();
+
+ std::pair<const fs::manager_t *, fs::filesystem_t *> get_fs() const { return std::make_pair(m_fsm, m_fs.get()); }
+
+ std::vector<std::string> path_split(std::string path) const;
+
+ static std::vector<u8> fload(std::string path);
+ static std::vector<u8> fload_rsrc(std::string path);
+ static void fsave(std::string path, const std::vector<u8> &data);
+ static void fsave_rsrc(std::string path, const std::vector<u8> &data);
+ static bool fexists(std::string path);
+ static std::string path_make_rsrc(std::string path);
+
+private:
+ std::string m_on_disk_path;
+
+ floppy_image m_floppy_image;
+
+ const floppy_image_format_t *m_floppy_fs_converter = nullptr;
+ std::vector<u8> m_sector_image;
+ std::unique_ptr<fs::fsblk_t> m_fsblk;
+ const fs::manager_t *m_fsm = nullptr;
+ std::unique_ptr<fs::filesystem_t> m_fs;
+
+};
+
+#endif // MAME_TOOLS_IMAGE_HANDLER_H
diff --git a/src/tools/imgtool/charconv.cpp b/src/tools/imgtool/charconv.cpp
index 0dadc8acb88..3ff6de62081 100644
--- a/src/tools/imgtool/charconv.cpp
+++ b/src/tools/imgtool/charconv.cpp
@@ -8,32 +8,13 @@
***************************************************************************/
-#include "corestr.h"
#include "charconv.h"
-#include "unicode.h"
-#include "coretmpl.h"
-
-imgtool::simple_charconverter imgtool::charconverter_iso_8859_1(nullptr, nullptr);
-
-
-//-------------------------------------------------
-// from_utf8
-//-------------------------------------------------
-
-void imgtool::charconverter::from_utf8(std::ostream &dest, const std::string &src) const
-{
- from_utf8(dest, src.c_str(), src.size());
-}
+#include "corestr.h"
-//-------------------------------------------------
-// to_utf8
-//-------------------------------------------------
+#include <algorithm>
-void imgtool::charconverter::to_utf8(std::ostream &dest, const std::string &src) const
-{
- to_utf8(dest, src.c_str(), src.size());
-}
+imgtool::simple_charconverter imgtool::charconverter_iso_8859_1(nullptr, nullptr);
//-------------------------------------------------
@@ -63,23 +44,23 @@ imgtool::simple_charconverter::simple_charconverter(const char32_t lowpage[0x80]
// from_utf8
//-------------------------------------------------
-void imgtool::simple_charconverter::from_utf8(std::ostream &dest, const char *src, size_t src_length) const
+void imgtool::simple_charconverter::from_utf8(std::ostream &dest, std::string_view src) const
{
// normalize the incoming unicode
- std::string normalized_src = normalize_unicode(src, src_length, m_norm);
+ std::string const normalized_src = normalize_unicode(src, m_norm);
- auto iter = normalized_src.begin();
- while (iter != normalized_src.end())
+ auto nsrc = std::string_view(normalized_src);
+ while (!nsrc.empty())
{
// get the next character
char32_t ch;
- int rc = uchar_from_utf8(&ch, &*iter, normalized_src.end() - iter);
+ int rc = uchar_from_utf8(&ch, nsrc);
if (rc < 0)
{
ch = 0xFFFD;
rc = 1;
}
- iter += rc;
+ nsrc.remove_prefix(rc);
// do the reverse lookup
auto lookup = std::lower_bound(m_reverse_lookup.begin(), m_reverse_lookup.end(), ch, [](const std::pair<char32_t, char> &a, const char32_t &b)
@@ -99,24 +80,24 @@ void imgtool::simple_charconverter::from_utf8(std::ostream &dest, const char *sr
// to_utf8
//-------------------------------------------------
-void imgtool::simple_charconverter::to_utf8(std::ostream &dest, const char *src, size_t src_length) const
+void imgtool::simple_charconverter::to_utf8(std::ostream &dest, std::string_view src) const
{
- for (size_t i = 0; i < src_length; i++)
+ for (uint8_t c : src)
{
// which page is this in?
- const char32_t *page = ((src[i] & 0x80) == 0) ? m_lowpage : m_highpage;
+ const char32_t *page = ((c & 0x80) == 0) ? m_lowpage : m_highpage;
// is this page present?
- if ((src[i] & 0x80) == 0)
+ if ((c & 0x80) == 0)
{
// no - pass it on
- dest << src[i];
+ dest << c;
}
else
{
// yes - we need to do a lookup
- size_t base = ((src[i] & 0x80) == 0) ? 0x00 : 0x80;
- char32_t ch = page[((unsigned char)(src[i])) - base];
+ size_t base = ((c & 0x80) == 0) ? 0x00 : 0x80;
+ char32_t ch = page[((unsigned char)(c)) - base];
if (ch == 0)
throw charconverter_exception();
diff --git a/src/tools/imgtool/charconv.h b/src/tools/imgtool/charconv.h
index 1fe91385a2f..7df16f8a615 100644
--- a/src/tools/imgtool/charconv.h
+++ b/src/tools/imgtool/charconv.h
@@ -14,6 +14,10 @@
#include "unicode.h"
+#include <sstream>
+#include <utility>
+#include <vector>
+
namespace imgtool
{
// ======================> charconverter
@@ -22,11 +26,8 @@ namespace imgtool
class charconverter
{
public:
- virtual void from_utf8(std::ostream &dest, const char *src, size_t src_length) const = 0;
- virtual void to_utf8(std::ostream &dest, const char *src, size_t src_length) const = 0;
-
- void from_utf8(std::ostream &dest, const std::string &src) const;
- void to_utf8(std::ostream &dest, const std::string &src) const;
+ virtual void from_utf8(std::ostream &dest, std::string_view src) const = 0;
+ virtual void to_utf8(std::ostream &dest, std::string_view src) const = 0;
std::string from_utf8(const std::string &src) const
{
@@ -59,8 +60,8 @@ namespace imgtool
simple_charconverter(const char32_t lowpage[0x80], const char32_t highpage[0x80], unicode_normalization_form norm = unicode_normalization_form::C);
- virtual void from_utf8(std::ostream &dest, const char *src, size_t src_length) const override;
- virtual void to_utf8(std::ostream &dest, const char *src, size_t src_length) const override;
+ virtual void from_utf8(std::ostream &dest, std::string_view src) const override;
+ virtual void to_utf8(std::ostream &dest, std::string_view src) const override;
private:
std::vector<std::pair<char32_t, char> > m_reverse_lookup;
diff --git a/src/tools/imgtool/filtbas.cpp b/src/tools/imgtool/filtbas.cpp
index 37bf5f0ef71..f4098202c32 100644
--- a/src/tools/imgtool/filtbas.cpp
+++ b/src/tools/imgtool/filtbas.cpp
@@ -18,19 +18,21 @@
*****************************************************************************/
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
+#include <cstring>
+#include <cstdarg>
+#include <cctype>
#include "imgtool.h"
-#include "formats/imageutl.h"
+#include "filter.h"
+
+#include "multibyte.h"
/***************************************************************************
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)))
@@ -51,7 +53,9 @@ struct basictoken_tableent
struct basictokens
{
uint16_t baseaddress;
+ uint8_t size_pos;
unsigned int skip_bytes : 15;
+ unsigned char bytes[20];
unsigned int be : 1;
const basictoken_tableent *entries;
int num_entries;
@@ -75,7 +79,8 @@ static imgtoolerr_t basic_readfile(const basictokens *tokens,
imgtoolerr_t err;
imgtool::stream::ptr mem_stream;
uint8_t line_header[4];
- uint16_t line_number; //, address;
+ [[maybe_unused]] uint16_t address;
+ uint16_t line_number;
uint8_t b, shift;
int i;
int in_string = false;
@@ -101,15 +106,13 @@ static imgtoolerr_t basic_readfile(const basictokens *tokens,
/* pluck the address and line number out */
if (tokens->be)
{
- //address = (uint16_t)
- pick_integer_be(line_header, 0, 2);
- line_number = (uint16_t) pick_integer_be(line_header, 2, 2);
+ address = get_u16be(&line_header[0]);
+ line_number = get_u16be(&line_header[2]);
}
else
{
- //address = (uint16_t)
- pick_integer_le(line_header, 0, 2);
- line_number = (uint16_t) pick_integer_le(line_header, 2, 2);
+ address = get_u16le(&line_header[0]);
+ line_number = get_u16le(&line_header[2]);
}
/* write the line number */
@@ -181,7 +184,7 @@ static imgtoolerr_t basic_writefile(const basictokens *tokens,
int i, j, pos, in_quotes;
uint16_t line_number;
uint8_t line_header[4];
- uint8_t file_header[3];
+ uint8_t file_size[2];
const basictoken_tableent *token_table;
const char *token;
uint8_t token_shift, token_value;
@@ -192,9 +195,8 @@ static imgtoolerr_t basic_writefile(const basictokens *tokens,
if (!mem_stream)
return IMGTOOLERR_OUTOFMEMORY;
- /* skip first few bytes */
- mem_stream->fill(0x00, tokens->skip_bytes);
-
+ /* write header */
+ mem_stream->write(tokens->bytes, tokens->skip_bytes);
/* loop until the file is complete */
while(!eof)
{
@@ -206,7 +208,7 @@ static imgtoolerr_t basic_writefile(const basictokens *tokens,
if ((c == '\r') || (c == '\n'))
break;
- if (pos <= ARRAY_LENGTH(buf) - 1)
+ if (pos <= std::size(buf) - 1)
{
buf[pos++] = c;
}
@@ -242,13 +244,13 @@ static imgtoolerr_t basic_writefile(const basictokens *tokens,
memset(&line_header, 0, sizeof(line_header));
if (tokens->be)
{
- place_integer_be(line_header, 0, 2, address);
- place_integer_be(line_header, 2, 2, line_number);
+ put_u16be(&line_header[0], address);
+ put_u16be(&line_header[2], line_number);
}
else
{
- place_integer_le(line_header, 0, 2, address);
- place_integer_le(line_header, 2, 2, line_number);
+ put_u16le(&line_header[0], address);
+ put_u16le(&line_header[2], line_number);
}
/* emit line header */
@@ -320,22 +322,20 @@ static imgtoolerr_t basic_writefile(const basictokens *tokens,
mem_stream->fill(0x00, 2);
/* reset stream */
- mem_stream->seek(0, SEEK_SET);
+ mem_stream->seek(tokens->size_pos, SEEK_SET);
/* this is somewhat gross */
if (tokens->skip_bytes >= 3)
{
if (tokens->be)
{
- place_integer_be(file_header, 0, 1, 0xFF);
- place_integer_be(file_header, 1, 2, mem_stream->size());
+ put_u16be(file_size, mem_stream->size());
}
else
{
- place_integer_le(file_header, 0, 1, 0xFF);
- place_integer_le(file_header, 1, 2, mem_stream->size());
+ put_u16le(file_size, mem_stream->size());
}
- mem_stream->write(file_header, 3);
+ mem_stream->write(file_size, 2);
mem_stream->seek(0, SEEK_SET);
}
@@ -603,25 +603,32 @@ static const char *const dragonbas_statements[] =
"=", /* 0xcb */
"<", /* 0xcc */
"USING", /* 0xcd */
- "DIR", /* 0xce */
- "DRIVE", /* 0xcf */
- "FIELD", /* 0xd0 */
- "FILES", /* 0xd1 */
- "KILL", /* 0xd2 */
- "LOAD", /* 0xd3 */
- "LSET", /* 0xd4 */
- "MERGE", /* 0xd5 */
- "RENAME", /* 0xd6 */
- "RSET", /* 0xd7 */
- "SAVE", /* 0xd8 */
- "WRITE", /* 0xd9 */
- "VERIFY", /* 0xda */
- "UNLOAD", /* 0xdb */
- "DSKINI", /* 0xdc */
- "BACKUP", /* 0xdd */
- "COPY", /* 0xde */
- "DSKI$", /* 0xdf */
- "DSKO$" /* 0xe0 */
+ "AUTO", /* 0xce */
+ "BACKUP", /* 0xcf */
+ "BEEP", /* 0xd0 */
+ "BOOT", /* 0xd1 */
+ "CHAIN", /* 0xd2 */
+ "COPY", /* 0xd3 */
+ "CREATE", /* 0xd4 */
+ "DIR", /* 0xd5 */
+ "DRIVE", /* 0xd6 */
+ "DSKINIT", /* 0xd7 */
+ "FREAD", /* 0xd8 */
+ "FWRITE", /* 0xd9 */
+ "ERROR", /* 0xda */
+ "KILL", /* 0xdb */
+ "LOAD", /* 0xdc */
+ "MERGE", /* 0xdd */
+ "PROTECT", /* 0xde */
+ "WAIT", /* 0xdf */
+ "RENAME", /* 0xe0 */
+ "SAVE", /* 0xe1 */
+ "SREAD", /* 0xe2 */
+ "SWRITE", /* 0xe3 */
+ "VERIFY", /* 0xe4 */
+ "FROM", /* 0xe5 */
+ "FLREAD", /* 0xe6 */
+ "SWAP" /* 0xe7 */
};
static const char *const dragonbas_functions[] =
@@ -660,11 +667,13 @@ static const char *const dragonbas_functions[] =
"PPOINT", /* 0xff9f */
"STRING$", /* 0xffa0 */
"USR", /* 0xffa1 */
- "CVN", /* 0xffa2 */
+ "LOF", /* 0xffa2 */
"FREE", /* 0xffa3 */
- "LOC", /* 0xffa4 */
- "LOF", /* 0xffa5 */
- "MKN$" /* 0xffa6 */
+ "ERL", /* 0xffa4 */
+ "ERR", /* 0xffa5 */
+ "HIMEM", /* 0xffa6 */
+ "LOC", /* 0xffa7 */
+ "FRE$" /* 0xffa8 */
};
static const char *const vzbas[] =
@@ -1024,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' */
};
@@ -1157,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' */
};
@@ -2935,17 +2944,19 @@ static const char *const basic_100[] = /* "BASIC 10.0" - supported by c65 & clon
static const basictoken_tableent cocobas_tokenents[] =
{
- { 0x00, 0x80, cocobas_statements, ARRAY_LENGTH(cocobas_statements) },
- { 0xff, 0x80, cocobas_functions, ARRAY_LENGTH(cocobas_functions) }
+ { 0x00, 0x80, cocobas_statements, std::size(cocobas_statements) },
+ { 0xff, 0x80, cocobas_functions, std::size(cocobas_functions) }
};
static const basictokens cocobas_tokens =
{
0x2600,
+ 1,
3,
+ {0xFF, 0x00, 0x00},
true,
cocobas_tokenents,
- ARRAY_LENGTH(cocobas_tokenents)
+ std::size(cocobas_tokenents)
};
static imgtoolerr_t cocobas_readfile(imgtool::partition &partition, const char *filename,
@@ -2960,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)
{
@@ -2979,17 +2990,19 @@ void filter_cocobas_getinfo(uint32_t state, union filterinfo *info)
static const basictoken_tableent dragonbas_tokenents[] =
{
- { 0x00, 0x80, dragonbas_statements, ARRAY_LENGTH(dragonbas_statements) },
- { 0xff, 0x80, dragonbas_functions, ARRAY_LENGTH(dragonbas_functions) }
+ { 0x00, 0x80, dragonbas_statements, std::size(dragonbas_statements) },
+ { 0xff, 0x80, dragonbas_functions, std::size(dragonbas_functions) }
};
static const basictokens dragonbas_tokens =
{
- 0x2600,
+ 0x2415,
4,
+ 9,
+ {0x55, 0x01, 0x24, 0x01, 0x00, 0x2A, 0x8B, 0x8D, 0xAA},
true,
dragonbas_tokenents,
- ARRAY_LENGTH(dragonbas_tokenents)
+ std::size(dragonbas_tokenents)
};
static imgtoolerr_t dragonbas_readfile(imgtool::partition &partition, const char *filename,
@@ -3004,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)
{
@@ -3023,7 +3036,7 @@ void filter_dragonbas_getinfo(uint32_t state, union filterinfo *info)
static const basictoken_tableent vzbas_tokenents[] =
{
- { 0x00, 0x80, vzbas, ARRAY_LENGTH(vzbas) }
+ { 0x00, 0x80, vzbas, std::size(vzbas) }
};
@@ -3032,9 +3045,11 @@ static const basictokens vzbas_tokens =
{
0x7ae9,
0,
+ 0,
+ {0x00},
false,
vzbas_tokenents,
- ARRAY_LENGTH(vzbas_tokenents)
+ std::size(vzbas_tokenents)
};
static imgtoolerr_t vzbas_readfile(imgtool::partition &partition, const char *filename,
@@ -3049,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)
{
@@ -3068,17 +3083,19 @@ void filter_vzbas_getinfo(uint32_t state, union filterinfo *info)
static const basictoken_tableent bml3bas_tokenents[] =
{
- { 0x00, 0x80, bml3bas_statements, ARRAY_LENGTH(bml3bas_statements) },
- { 0xff, 0x80, bml3bas_functions, ARRAY_LENGTH(bml3bas_functions) }
+ { 0x00, 0x80, bml3bas_statements, std::size(bml3bas_statements) },
+ { 0xff, 0x80, bml3bas_functions, std::size(bml3bas_functions) }
};
static const basictokens bml3bas_tokens =
{
0x2600,
+ 1,
3,
+ {0xFF, 0x00, 0x00},
true,
bml3bas_tokenents,
- ARRAY_LENGTH(bml3bas_tokenents)
+ std::size(bml3bas_tokenents)
};
static imgtoolerr_t bml3bas_readfile(imgtool::partition &partition, const char *filename,
@@ -3093,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 bb589e8fafe..41f11769747 100644
--- a/src/tools/imgtool/filteoln.cpp
+++ b/src/tools/imgtool/filteoln.cpp
@@ -8,11 +8,12 @@
*****************************************************************************/
-#include <string.h>
-
#include "imgtool.h"
+#include "filter.h"
+
+#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)))
@@ -95,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 e26c51a623b..9df7c3c1692 100644
--- a/src/tools/imgtool/filter.cpp
+++ b/src/tools/imgtool/filter.cpp
@@ -8,39 +8,39 @@
***************************************************************************/
-#include <string.h>
+#include "filter.h"
-#include "imgtool.h"
+#include <cstring>
/* ----------------------------------------------------------------------- */
-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,12 +48,11 @@ 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,
filter_dragonbas_getinfo,
- filter_macbinary_getinfo,
filter_vzsnapshot_getinfo,
filter_vzbas_getinfo,
filter_thombas5_getinfo,
@@ -67,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 7ddd999c2a2..0b9b1f14884 100644
--- a/src/tools/imgtool/filter.h
+++ b/src/tools/imgtool/filter.h
@@ -8,11 +8,10 @@
***************************************************************************/
-#ifndef FILTER_H
-#define FILTER_H
+#ifndef MAME_TOOLS_IMGTOOL_FILTER_H
+#define MAME_TOOLS_IMGTOOL_FILTER_H
-#include <stdlib.h>
-#include <stdio.h>
+#pragma once
#include "library.h"
@@ -37,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/formats/coco_dsk.cpp b/src/tools/imgtool/formats/coco_dsk.cpp
index 6f509c92767..33363b2245e 100644
--- a/src/tools/imgtool/formats/coco_dsk.cpp
+++ b/src/tools/imgtool/formats/coco_dsk.cpp
@@ -8,14 +8,14 @@
*********************************************************************/
-#include <string.h>
-#include <time.h>
-#include <assert.h>
+#include <cstring>
+#include <ctime>
+#include <cassert>
#include "formats/coco_dsk.h"
#include "formats/basicdsk.h"
#include "formats/imageutl.h"
-#include "coretmpl.h"
+#include "opresolv.h"
#include <algorithm>
/* -----------------------------------------------------------------------
diff --git a/src/tools/imgtool/formats/coco_dsk.h b/src/tools/imgtool/formats/coco_dsk.h
index 797911d40a1..bf9bccc5621 100644
--- a/src/tools/imgtool/formats/coco_dsk.h
+++ b/src/tools/imgtool/formats/coco_dsk.h
@@ -11,7 +11,7 @@
#ifndef COCO_DSK_H
#define COCO_DSK_H
-#include "formats/flopimg.h"
+#include "formats/flopimg_legacy.h"
/**************************************************************************/
diff --git a/src/tools/imgtool/formats/pc_dsk_legacy.cpp b/src/tools/imgtool/formats/pc_dsk_legacy.cpp
new file mode 100644
index 00000000000..771f0de8638
--- /dev/null
+++ b/src/tools/imgtool/formats/pc_dsk_legacy.cpp
@@ -0,0 +1,140 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+/*********************************************************************
+
+ formats/pc_dsk_legacy.cpp
+
+ PC disk images (legacy support for imgtool)
+
+*********************************************************************/
+
+#include "formats/pc_dsk_legacy.h"
+#include "formats/basicdsk.h"
+
+#include "opresolv.h"
+
+struct pc_disk_sizes
+{
+ uint32_t image_size;
+ int sectors;
+ int heads;
+};
+
+
+
+static const struct pc_disk_sizes disk_sizes[] =
+{
+ { 8*1*40*512, 8, 1}, /* 5 1/4 inch double density single sided */
+ { 8*2*40*512, 8, 2}, /* 5 1/4 inch double density */
+ { 9*1*40*512, 9, 1}, /* 5 1/4 inch double density single sided */
+ { 9*2*40*512, 9, 2}, /* 5 1/4 inch double density */
+ {10*2*40*512, 10, 2}, /* 5 1/4 inch double density single sided */
+ { 9*2*80*512, 9, 2}, /* 80 tracks 5 1/4 inch drives rare in PCs */
+ { 9*2*80*512, 9, 2}, /* 3 1/2 inch double density */
+ {15*2*80*512, 15, 2}, /* 5 1/4 inch high density (or japanese 3 1/2 inch high density) */
+ {18*2*80*512, 18, 2}, /* 3 1/2 inch high density */
+ {21*2*80*512, 21, 2}, /* 3 1/2 inch high density DMF */
+ {36*2*80*512, 36, 2} /* 3 1/2 inch enhanced density */
+};
+
+
+
+static floperr_t pc_dsk_compute_geometry(floppy_image_legacy *floppy, struct basicdsk_geometry *geometry)
+{
+ int i;
+ uint64_t size;
+
+ memset(geometry, 0, sizeof(*geometry));
+ size = floppy_image_size(floppy);
+
+ for (i = 0; i < std::size(disk_sizes); i++)
+ {
+ if (disk_sizes[i].image_size == size)
+ {
+ geometry->sectors = disk_sizes[i].sectors;
+ geometry->heads = disk_sizes[i].heads;
+ geometry->sector_length = 512;
+ geometry->first_sector_id = 1;
+ geometry->tracks = (int) (size / disk_sizes[i].sectors / disk_sizes[i].heads / geometry->sector_length);
+ return FLOPPY_ERROR_SUCCESS;
+ }
+ }
+
+ if (size >= 0x1a)
+ {
+ /*
+ * get info from boot sector.
+ * not correct on all disks
+ */
+ uint8_t scl, spt, heads;
+ floppy_image_read(floppy, &scl, 0x0c, 1);
+ floppy_image_read(floppy, &spt, 0x18, 1);
+ floppy_image_read(floppy, &heads, 0x1A, 1);
+
+ if (size == ((uint64_t) scl) * spt * heads * 0x200)
+ {
+ geometry->sectors = spt;
+ geometry->heads = heads;
+ geometry->sector_length = 512;
+ geometry->first_sector_id = 1;
+ geometry->tracks = scl;
+ return FLOPPY_ERROR_SUCCESS;
+ }
+ }
+
+ return FLOPPY_ERROR_SUCCESS;
+}
+
+
+
+static FLOPPY_IDENTIFY(pc_dsk_identify)
+{
+ floperr_t err;
+ struct basicdsk_geometry geometry;
+
+ err = pc_dsk_compute_geometry(floppy, &geometry);
+ if (err)
+ return err;
+
+ *vote = geometry.heads ? 100 : 0;
+ return FLOPPY_ERROR_SUCCESS;
+}
+
+
+
+static FLOPPY_CONSTRUCT(pc_dsk_construct)
+{
+ floperr_t err;
+ struct basicdsk_geometry geometry;
+
+ if (params)
+ {
+ /* create */
+ memset(&geometry, 0, sizeof(geometry));
+ geometry.heads = params->lookup_int(PARAM_HEADS);
+ geometry.tracks = params->lookup_int(PARAM_TRACKS);
+ geometry.sectors = params->lookup_int(PARAM_SECTORS);
+ geometry.first_sector_id = 1;
+ geometry.sector_length = 512;
+ }
+ else
+ {
+ /* open */
+ err = pc_dsk_compute_geometry(floppy, &geometry);
+ if (err)
+ return err;
+ }
+
+ return basicdsk_construct(floppy, &geometry);
+}
+
+
+
+/* ----------------------------------------------------------------------- */
+
+LEGACY_FLOPPY_OPTIONS_START( pc )
+ LEGACY_FLOPPY_OPTION( pc_dsk, "dsk,ima,img,ufi,360", "PC floppy disk image", pc_dsk_identify, pc_dsk_construct, nullptr,
+ HEADS([1]-2)
+ TRACKS(40/[80])
+ SECTORS(8/[9]/10/15/18/36))
+LEGACY_FLOPPY_OPTIONS_END
diff --git a/src/tools/imgtool/formats/pc_dsk_legacy.h b/src/tools/imgtool/formats/pc_dsk_legacy.h
new file mode 100644
index 00000000000..14cb33f389d
--- /dev/null
+++ b/src/tools/imgtool/formats/pc_dsk_legacy.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+/*********************************************************************
+
+ formats/pc_dsk_legacy.h
+
+ PC disk images (legacy support for imgtool)
+
+*********************************************************************/
+
+#ifndef PC_DSK_LEGACY_H
+#define PC_DSK_LEGACY_H
+
+#include "formats/flopimg_legacy.h"
+
+
+/**************************************************************************/
+
+LEGACY_FLOPPY_OPTIONS_EXTERN(pc);
+
+#endif /* PC_DSK_LEGACY_H */
diff --git a/src/tools/imgtool/formats/vt_dsk.cpp b/src/tools/imgtool/formats/vt_dsk_legacy.cpp
index 02f74668b0f..6cf57856574 100644
--- a/src/tools/imgtool/formats/vt_dsk.cpp
+++ b/src/tools/imgtool/formats/vt_dsk_legacy.cpp
@@ -2,18 +2,19 @@
// copyright-holders:Juergen Buchmueller
/*********************************************************************
- formats/vt_dsk.c
+ formats/vt_dsk_legacy.cpp
- VTech Laser/VZ disk images
+ VTech Laser/VZ disk images (legacy support)
*********************************************************************/
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include "formats/vt_dsk.h"
+#include "formats/vt_dsk_legacy.h"
#include "formats/basicdsk.h"
+#include "opresolv.h"
+
+#include <cstring>
+
static FLOPPY_IDENTIFY(vz_identify)
{
uint64_t size = floppy_image_size(floppy);
diff --git a/src/tools/imgtool/formats/vt_dsk.h b/src/tools/imgtool/formats/vt_dsk_legacy.h
index a3f9a86b44e..fe8f0ddf6a3 100644
--- a/src/tools/imgtool/formats/vt_dsk.h
+++ b/src/tools/imgtool/formats/vt_dsk_legacy.h
@@ -2,17 +2,17 @@
// copyright-holders:Juergen Buchmueller
/*********************************************************************
- formats/vt_dsk.h
+ formats/vt_dsk_legacy.h
- Tandy Color Computer / Dragon disk images
+ VTech Laser/VZ disk images (legacy support)
*********************************************************************/
-#ifndef VT_DSK_H
-#define VT_DSK_H
+#ifndef VT_DSK_LEGACY_H
+#define VT_DSK_LEGACY_H
-#include "formats/flopimg.h"
+#include "formats/flopimg_legacy.h"
LEGACY_FLOPPY_OPTIONS_EXTERN(vz);
-#endif /* VT_DSK_H */
+#endif /* VT_DSK_LEGACY_H */
diff --git a/src/tools/imgtool/iflopimg.cpp b/src/tools/imgtool/iflopimg.cpp
index f6e79e6cd5d..2d785c92a0d 100644
--- a/src/tools/imgtool/iflopimg.cpp
+++ b/src/tools/imgtool/iflopimg.cpp
@@ -8,10 +8,15 @@
*********************************************************************/
+#include "iflopimg.h"
+
#include "imgtool.h"
-#include "formats/flopimg.h"
#include "library.h"
-#include "iflopimg.h"
+
+#include "ioprocs.h"
+
+#include <cstdio>
+
imgtoolerr_t imgtool_floppy_error(floperr_t err)
{
@@ -40,57 +45,6 @@ imgtoolerr_t imgtool_floppy_error(floperr_t err)
/*********************************************************************
- Imgtool ioprocs
-*********************************************************************/
-
-static void imgtool_floppy_closeproc(void *file)
-{
- delete reinterpret_cast<imgtool::stream *>(file);
-}
-
-static int imgtool_floppy_seekproc(void *file, int64_t offset, int whence)
-{
- reinterpret_cast<imgtool::stream *>(file)->seek(offset, whence);
- return 0;
-}
-
-static size_t imgtool_floppy_readproc(void *file, void *buffer, size_t length)
-{
- return reinterpret_cast<imgtool::stream *>(file)->read(buffer, length);
-}
-
-static size_t imgtool_floppy_writeproc(void *file, const void *buffer, size_t length)
-{
- reinterpret_cast<imgtool::stream *>(file)->write(buffer, length);
- return length;
-}
-
-static uint64_t imgtool_floppy_filesizeproc(void *file)
-{
- return reinterpret_cast<imgtool::stream *>(file)->size();
-}
-
-static const struct io_procs imgtool_ioprocs =
-{
- imgtool_floppy_closeproc,
- imgtool_floppy_seekproc,
- imgtool_floppy_readproc,
- imgtool_floppy_writeproc,
- imgtool_floppy_filesizeproc
-};
-
-static const struct io_procs imgtool_noclose_ioprocs =
-{
- nullptr,
- imgtool_floppy_seekproc,
- imgtool_floppy_readproc,
- imgtool_floppy_writeproc,
- imgtool_floppy_filesizeproc
-};
-
-
-
-/*********************************************************************
Imgtool handlers
*********************************************************************/
@@ -102,11 +56,10 @@ struct imgtool_floppy_image
-static imgtoolerr_t imgtool_floppy_open_internal(imgtool::image &image, imgtool::stream::ptr &&stream, int noclose)
+static imgtoolerr_t imgtool_floppy_open_internal(imgtool::image &image, imgtool::stream::ptr &&stream)
{
floperr_t ferr;
imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- imgtool::stream *f = nullptr;
struct imgtool_floppy_image *fimg;
const imgtool_class *imgclass;
const struct FloppyFormat *format;
@@ -117,18 +70,13 @@ static imgtoolerr_t imgtool_floppy_open_internal(imgtool::image &image, imgtool:
format = (const struct FloppyFormat *) imgclass->derived_param;
open = (imgtoolerr_t (*)(imgtool::image &, imgtool::stream *)) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_OPEN);
- // extract the pointer
- f = stream.release();
-
// open up the floppy
- ferr = floppy_open(f, noclose ? &imgtool_noclose_ioprocs : &imgtool_ioprocs,
- "", format, FLOPPY_FLAGS_READWRITE, &fimg->floppy);
+ ferr = floppy_open(imgtool::stream_read_write(std::move(stream), 0xff), "", format, FLOPPY_FLAGS_READWRITE, &fimg->floppy);
if (ferr)
{
err = imgtool_floppy_error(ferr);
goto done;
}
- f = nullptr; // the floppy object has the stream now
if (open)
{
@@ -138,8 +86,6 @@ static imgtoolerr_t imgtool_floppy_open_internal(imgtool::image &image, imgtool:
}
done:
- if (f)
- delete f;
if (err && fimg->floppy)
{
floppy_close(fimg->floppy);
@@ -152,7 +98,7 @@ done:
static imgtoolerr_t imgtool_floppy_open(imgtool::image &image, imgtool::stream::ptr &&stream)
{
- return imgtool_floppy_open_internal(image, std::move(stream), false);
+ return imgtool_floppy_open_internal(image, std::move(stream));
}
@@ -161,7 +107,6 @@ static imgtoolerr_t imgtool_floppy_create(imgtool::image &image, imgtool::stream
{
floperr_t ferr;
imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- imgtool::stream *f = nullptr;
struct imgtool_floppy_image *fimg;
const imgtool_class *imgclass;
const struct FloppyFormat *format;
@@ -174,17 +119,13 @@ static imgtoolerr_t imgtool_floppy_create(imgtool::image &image, imgtool::stream
create = (imgtoolerr_t (*)(imgtool::image &, imgtool::stream *, util::option_resolution *)) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_CREATE);
open = (imgtoolerr_t (*)(imgtool::image &, imgtool::stream *)) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_OPEN);
- // extract the pointer
- f = stream.release();
-
// open up the floppy
- ferr = floppy_create(f, &imgtool_ioprocs, format, opts, &fimg->floppy);
+ ferr = floppy_create(imgtool::stream_read_write(std::move(stream), 0xff), format, opts, &fimg->floppy);
if (ferr)
{
err = imgtool_floppy_error(ferr);
goto done;
}
- f = nullptr; // the floppy object has the stream now
// do we have to do extra stuff when creating the image?
if (create)
@@ -203,8 +144,6 @@ static imgtoolerr_t imgtool_floppy_create(imgtool::image &image, imgtool::stream
}
done:
- if (f)
- delete f;
if (err && fimg->floppy)
{
floppy_close(fimg->floppy);
@@ -292,7 +231,7 @@ static void imgtool_floppy_get_info(const imgtool_class *imgclass, uint32_t stat
case IMGTOOLINFO_PTR_OPEN: info->open = imgtool_floppy_open; break;
case IMGTOOLINFO_PTR_CREATE: info->create = imgtool_floppy_create; break;
case IMGTOOLINFO_PTR_CLOSE: info->close = imgtool_floppy_close; break;
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = format->param_guidelines ? &floppy_option_guide : nullptr; break;
+ case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = format->param_guidelines ? &floppy_option_guide() : nullptr; break;
case IMGTOOLINFO_PTR_READ_SECTOR: info->read_sector = imgtool_floppy_read_sector; break;
case IMGTOOLINFO_PTR_WRITE_SECTOR: info->write_sector = imgtool_floppy_write_sector; break;
diff --git a/src/tools/imgtool/iflopimg.h b/src/tools/imgtool/iflopimg.h
index 078a1247ae3..43bbb1ecda3 100644
--- a/src/tools/imgtool/iflopimg.h
+++ b/src/tools/imgtool/iflopimg.h
@@ -7,13 +7,16 @@
Bridge code for Imgtool into the standard floppy code
*********************************************************************/
+#ifndef MAME_TOOLS_IMGTOOL_IFLOPIMG_H
+#define MAME_TOOLS_IMGTOOL_IFLOPIMG_H
-#ifndef IFLOPIMG_H
-#define IFLOPIMG_H
+#pragma once
-#include "formats/flopimg.h"
#include "library.h"
+#include "formats/flopimg_legacy.h"
+
+
/***************************************************************************
Prototypes
@@ -38,4 +41,4 @@ imgtoolerr_t imgtool_floppy_write_sector_from_stream(imgtool::image &img, int he
void *imgtool_floppy_extrabytes(imgtool::image &img);
-#endif /* IFLOPIMG_H */
+#endif // MAME_TOOLS_IMGTOOL_IFLOPIMG_H
diff --git a/src/tools/imgtool/imghd.cpp b/src/tools/imgtool/imghd.cpp
index b868b692c63..60a79469051 100644
--- a/src/tools/imgtool/imghd.cpp
+++ b/src/tools/imgtool/imghd.cpp
@@ -9,34 +9,24 @@
Raphael Nabet 2003
*/
-#include "imgtool.h"
-#include "harddisk.h"
#include "imghd.h"
+#include "library.h"
+#include "stream.h"
+#include "harddisk.h"
+#include "opresolv.h"
-static imgtoolerr_t map_chd_error(chd_error chderr)
-{
- imgtoolerr_t err;
- switch(chderr)
- {
- case CHDERR_NONE:
- err = IMGTOOLERR_SUCCESS;
- break;
- case CHDERR_OUT_OF_MEMORY:
- err = IMGTOOLERR_OUTOFMEMORY;
- break;
- case CHDERR_FILE_NOT_WRITEABLE:
- err = IMGTOOLERR_READONLY;
- break;
- case CHDERR_NOT_SUPPORTED:
- err = IMGTOOLERR_UNIMPLEMENTED;
- break;
- default:
- err = IMGTOOLERR_UNEXPECTED;
- break;
- }
- return err;
+static imgtoolerr_t map_chd_error(std::error_condition chderr)
+{
+ if (!chderr)
+ return IMGTOOLERR_SUCCESS;
+ else if (std::errc::not_enough_memory == chderr)
+ return IMGTOOLERR_OUTOFMEMORY;
+ else if (chd_file::error::FILE_NOT_WRITEABLE == chderr)
+ return IMGTOOLERR_READONLY;
+ else
+ return IMGTOOLERR_UNEXPECTED;
}
@@ -50,7 +40,7 @@ imgtoolerr_t imghd_create(imgtool::stream &stream, uint32_t hunksize, uint32_t c
{
imgtoolerr_t err = IMGTOOLERR_SUCCESS;
chd_file chd;
- chd_error rc;
+ std::error_condition rc;
chd_codec_type compression[4] = { CHD_CODEC_NONE };
/* sanity check args -- see parse_hunk_size() in src/lib/util/chd.cpp */
@@ -73,17 +63,17 @@ imgtoolerr_t imghd_create(imgtool::stream &stream, uint32_t hunksize, uint32_t c
const uint64_t logicalbytes = (uint64_t)cylinders * heads * sectors * seclen;
/* create the new hard drive */
- rc = chd.create(*stream.core_file(), logicalbytes, hunksize, seclen, compression);
- if (rc != CHDERR_NONE)
+ rc = chd.create(stream_read_write(stream, 0), logicalbytes, hunksize, seclen, compression);
+ if (rc)
{
err = map_chd_error(rc);
return err;
}
/* write the metadata */
- const std::string metadata = string_format(HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, seclen);
- err = (imgtoolerr_t)chd.write_metadata(HARD_DISK_METADATA_TAG, 0, metadata);
- if (rc != CHDERR_NONE)
+ const std::string metadata = util::string_format(HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, seclen);
+ rc = chd.write_metadata(HARD_DISK_METADATA_TAG, 0, metadata);
+ if (rc)
{
err = map_chd_error(rc);
return err;
@@ -118,19 +108,19 @@ imgtoolerr_t imghd_create(imgtool::stream &stream, uint32_t hunksize, uint32_t c
*/
imgtoolerr_t imghd_open(imgtool::stream &stream, struct mess_hard_disk_file *hard_disk)
{
- chd_error chderr;
+ std::error_condition chderr;
imgtoolerr_t err = IMGTOOLERR_SUCCESS;
hard_disk->hard_disk = nullptr;
- chderr = hard_disk->chd.open(*stream.core_file(), !stream.is_read_only());
+ chderr = hard_disk->chd.open(stream_read_write(stream, 0), !stream.is_read_only());
if (chderr)
{
err = map_chd_error(chderr);
goto done;
}
- hard_disk->hard_disk = hard_disk_open(&hard_disk->chd);
+ hard_disk->hard_disk = new hard_disk_file(&hard_disk->chd);
if (!hard_disk->hard_disk)
{
err = IMGTOOLERR_UNEXPECTED;
@@ -155,7 +145,7 @@ void imghd_close(struct mess_hard_disk_file *disk)
{
if (disk->hard_disk)
{
- hard_disk_close(disk->hard_disk);
+ delete disk->hard_disk;
disk->hard_disk = nullptr;
}
if (disk->stream)
@@ -174,9 +164,8 @@ void imghd_close(struct mess_hard_disk_file *disk)
*/
imgtoolerr_t imghd_read(struct mess_hard_disk_file *disk, uint32_t lbasector, void *buffer)
{
- uint32_t reply;
- reply = hard_disk_read(disk->hard_disk, lbasector, buffer);
- return (imgtoolerr_t)(reply ? IMGTOOLERR_SUCCESS : map_chd_error((chd_error)reply));
+ uint32_t reply = disk->hard_disk->read(lbasector, buffer);
+ return reply ? IMGTOOLERR_SUCCESS : IMGTOOLERR_READERROR;
}
@@ -188,9 +177,8 @@ imgtoolerr_t imghd_read(struct mess_hard_disk_file *disk, uint32_t lbasector, vo
*/
imgtoolerr_t imghd_write(struct mess_hard_disk_file *disk, uint32_t lbasector, const void *buffer)
{
- uint32_t reply;
- reply = hard_disk_write(disk->hard_disk, lbasector, buffer);
- return (imgtoolerr_t)(reply ? IMGTOOLERR_SUCCESS : map_chd_error((chd_error)reply));
+ uint32_t reply = disk->hard_disk->write(lbasector, buffer);
+ return reply ? IMGTOOLERR_SUCCESS : IMGTOOLERR_WRITEERROR;
}
@@ -200,11 +188,9 @@ imgtoolerr_t imghd_write(struct mess_hard_disk_file *disk, uint32_t lbasector, c
Return pointer to the header of MAME HD image
*/
-const hard_disk_info *imghd_get_header(struct mess_hard_disk_file *disk)
+const hard_disk_file::info &imghd_get_header(struct mess_hard_disk_file *disk)
{
- const hard_disk_info *reply;
- reply = hard_disk_get_info(disk->hard_disk);
- return reply;
+ return disk->hard_disk->get_info();
}
diff --git a/src/tools/imgtool/imghd.h b/src/tools/imgtool/imghd.h
index d4ae341af1e..c49e87fe8db 100644
--- a/src/tools/imgtool/imghd.h
+++ b/src/tools/imgtool/imghd.h
@@ -11,8 +11,17 @@
#ifndef IMGHD_H
#define IMGHD_H
+#include "imgterrs.h"
+
+#include "chd.h"
#include "harddisk.h"
+
+namespace imgtool
+{
+ class stream;
+}
+
struct mess_hard_disk_file
{
imgtool::stream *stream;
@@ -37,6 +46,6 @@ imgtoolerr_t imghd_read(struct mess_hard_disk_file *disk, uint32_t lbasector, vo
imgtoolerr_t imghd_write(struct mess_hard_disk_file *disk, uint32_t lbasector, const void *buffer);
/* gets the header from a hard disk */
-const hard_disk_info *imghd_get_header(struct mess_hard_disk_file *disk);
+const hard_disk_file::info &imghd_get_header(struct mess_hard_disk_file *disk);
#endif /* IMGHD_H */
diff --git a/src/tools/imgtool/imgterrs.cpp b/src/tools/imgtool/imgterrs.cpp
index bd679440309..9018ed79170 100644
--- a/src/tools/imgtool/imgterrs.cpp
+++ b/src/tools/imgtool/imgterrs.cpp
@@ -8,9 +8,10 @@
***************************************************************************/
-#include "imgtool.h"
#include "imgterrs.h"
-#include "osdcomm.h"
+
+#include <cassert>
+#include <iterator>
static const char *const msgs[] =
{
@@ -50,6 +51,6 @@ const char *imgtool_error(imgtoolerr_t err)
{
err = (imgtoolerr_t)(ERRORCODE(err) - 1);
assert(err >= 0);
- assert(err < ARRAY_LENGTH(msgs));
+ assert(err < std::size(msgs));
return msgs[err];
}
diff --git a/src/tools/imgtool/imgtool.cpp b/src/tools/imgtool/imgtool.cpp
index b51d7b4d478..e10558dcce1 100644
--- a/src/tools/imgtool/imgtool.cpp
+++ b/src/tools/imgtool/imgtool.cpp
@@ -8,15 +8,25 @@
***************************************************************************/
-#include <string.h>
-#include <ctype.h>
-#include <iostream>
-
#include "imgtool.h"
-#include "formats/imageutl.h"
+#include "charconv.h"
+#include "filter.h"
#include "library.h"
#include "modules.h"
-#include "pool.h"
+
+#include "formats/imageutl.h"
+
+#include "corestr.h"
+#include "opresolv.h"
+#include "path.h"
+#include "strformat.h"
+
+#include <cstdarg>
+#include <cstdio>
+#include <cstring>
+#include <cctype>
+#include <iostream>
+
/***************************************************************************
@@ -83,10 +93,11 @@ char *strncpyz(char *dest, const char *source, size_t len)
// extract_padded_string
//-------------------------------------------------
-static std::string extract_padded_string(const char *source, size_t len)
+static std::string extract_padded_string(const char *source, size_t len, char pad)
{
- while ((len > 0) && (source[len - 1] == ' '))
+ while ((len > 0) && (source[len - 1] == pad))
len--;
+
return std::string(source, len);
}
@@ -97,10 +108,10 @@ static std::string extract_padded_string(const char *source, size_t len)
// this in common code
//-------------------------------------------------
-std::string extract_padded_filename(const char *source, size_t filename_length, size_t extension_length)
+std::string extract_padded_filename(const char *source, size_t filename_length, size_t extension_length, char pad)
{
- std::string filename = extract_padded_string(source, filename_length);
- std::string extension = extract_padded_string(source + filename_length, extension_length);
+ std::string filename = extract_padded_string(source, filename_length, pad);
+ std::string extension = extract_padded_string(source + filename_length, extension_length, pad);
return extension.empty() ? filename : filename + "." + extension;
}
@@ -139,7 +150,7 @@ static imgtoolerr_t markerrorsource(imgtoolerr_t err)
static void internal_error(const imgtool_module *module, const char *message)
{
#ifdef MAME_DEBUG
- printf("%s: %s\n", module->name, message);
+ printf("%s: %s\n", module->name.c_str(), message);
#endif
}
@@ -249,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;
+
+ 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;
+ result = current_result;
+ }
}
done:
@@ -334,7 +339,7 @@ imgtoolerr_t imgtool::image::identify_file(const char *fname, imgtool_module **m
/* iterate through all modules */
for (const auto &module : library.modules())
{
- if (!extension || image_find_extension(module->extensions, extension))
+ if (!extension || image_find_extension(module->extensions.c_str(), extension))
{
err = evaluate_module(fname, module.get(), val);
if (err)
@@ -532,16 +537,6 @@ imgtoolerr_t imgtool::image::list_partitions(std::vector<imgtool::partition_info
}
-//-------------------------------------------------
-// malloc - allocates memory associated with an image
-//-------------------------------------------------
-
-void *imgtool::image::malloc(size_t size)
-{
- return pool_malloc_lib(m_pool, size);
-}
-
-
/***************************************************************************
Imgtool partition management
@@ -588,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);
@@ -849,17 +844,17 @@ bool imgtool_validitychecks(void)
{
features = imgtool_get_module_features(module.get());
- if (!module->name)
+ if (module->name.empty())
{
- util::stream_format(std::wcerr, L"imgtool module %s has null 'name'\n", wstring_from_utf8(module->name));
+ util::stream_format(std::wcerr, L"imgtool module has null 'name'\n");
error = true;
}
- if (!module->description)
+ if (module->description.empty())
{
util::stream_format(std::wcerr, L"imgtool module %s has null 'description'\n", wstring_from_utf8(module->name));
error = true;
}
- if (!module->extensions)
+ if (module->extensions.empty())
{
util::stream_format(std::wcerr, L"imgtool module %s has null 'extensions'\n", wstring_from_utf8(module->extensions));
error = true;
@@ -893,24 +888,24 @@ bool imgtool_validitychecks(void)
#endif
/* sanity checks on creation options */
- if (module->createimage_optguide || module->createimage_optspec)
+ if (module->createimage_optguide || !module->createimage_optspec.empty())
{
if (!module->create)
{
util::stream_format(std::wcerr, L"imgtool module %s has creation options without supporting create\n", wstring_from_utf8(module->name));
error = true;
}
- if ((!module->createimage_optguide && module->createimage_optspec)
- || (module->createimage_optguide && !module->createimage_optspec))
+ if ((!module->createimage_optguide && !module->createimage_optspec.empty())
+ || (module->createimage_optguide && module->createimage_optspec.empty()))
{
- util::stream_format(std::wcerr, L"imgtool module %s does has partially incomplete creation options\n", wstring_from_utf8(module->name));
+ util::stream_format(std::wcerr, L"imgtool module %s has partially incomplete creation options\n", wstring_from_utf8(module->name));
error = true;
}
- if (module->createimage_optguide && module->createimage_optspec)
+ if (module->createimage_optguide && !module->createimage_optspec.empty())
{
auto resolution = std::make_unique<util::option_resolution>(*module->createimage_optguide);
- resolution->set_specification(module->createimage_optspec);
+ resolution->set_specification(module->createimage_optspec.c_str());
}
}
}
@@ -936,7 +931,7 @@ char *imgtool_temp_str(void)
{
static int index;
static char temp_string_pool[32][256];
- return temp_string_pool[index++ % ARRAY_LENGTH(temp_string_pool)];
+ return temp_string_pool[index++ % std::size(temp_string_pool)];
}
@@ -953,8 +948,6 @@ imgtoolerr_t imgtool::image::internal_open(const imgtool_module *module, const s
imgtoolerr_t err;
imgtool::stream::ptr stream;
imgtool::image::ptr image;
- object_pool *pool = nullptr;
- void *extra_bytes = nullptr;
outimg.reset();
@@ -965,14 +958,6 @@ imgtoolerr_t imgtool::image::internal_open(const imgtool_module *module, const s
goto done;
}
- // create a memory pool
- pool = pool_alloc_lib(nullptr);
- if (!pool)
- {
- err = imgtoolerr_t(IMGTOOLERR_OUTOFMEMORY);
- goto done;
- }
-
// open the stream
stream = imgtool::stream::open(filename, read_or_write);
if (!stream)
@@ -981,29 +966,14 @@ imgtoolerr_t imgtool::image::internal_open(const imgtool_module *module, const s
goto done;
}
- // allocate extra
- if (module->image_extra_bytes > 0)
- {
- extra_bytes = pool_malloc_lib(pool, module->image_extra_bytes);
- if (!extra_bytes)
- {
- err = imgtoolerr_t(IMGTOOLERR_OUTOFMEMORY);
- goto done;
- }
- memset(extra_bytes, 0, module->image_extra_bytes);
- }
-
// setup the image structure
- try { image = std::make_unique<imgtool::image>(*module, pool, extra_bytes); }
+ try { image = std::make_unique<imgtool::image>(*module); }
catch (std::bad_alloc const &)
{
err = imgtoolerr_t(IMGTOOLERR_OUTOFMEMORY);
goto done;
}
- // the pool is no longer owned by this function
- pool = nullptr;
-
// actually call create or open
err = (read_or_write == OSD_FOPEN_RW_CREATE)
? module->create(*image, std::move(stream), createopts)
@@ -1020,8 +990,6 @@ imgtoolerr_t imgtool::image::internal_open(const imgtool_module *module, const s
outimg = std::move(image);
done:
- if (pool)
- pool_free_lib(pool);
return err;
}
@@ -1057,12 +1025,16 @@ imgtoolerr_t imgtool::image::open(const std::string &modulename, const std::stri
// imgtool::image::image
//-------------------------------------------------
-imgtool::image::image(const imgtool_module &module, object_pool *pool, void *extra_bytes)
+imgtool::image::image(const imgtool_module &module)
: m_module(module)
- , m_pool(pool)
- , m_extra_bytes(extra_bytes)
, m_okay_to_close(false)
{
+ if (module.image_extra_bytes > 0)
+ {
+ m_extra_bytes = std::make_unique<uint8_t[]>(module.image_extra_bytes);
+ std::fill_n(&m_extra_bytes[0], module.image_extra_bytes, 0);
+ }
+
}
@@ -1074,7 +1046,6 @@ imgtool::image::~image()
{
if (m_okay_to_close && module().close)
module().close(*this);
- pool_free_lib(m_pool);
}
@@ -1093,8 +1064,8 @@ imgtoolerr_t imgtool::image::create(const imgtool_module *module, const std::str
try { alloc_resolution.reset(new util::option_resolution(*module->createimage_optguide)); }
catch (...) { return (imgtoolerr_t)IMGTOOLERR_OUTOFMEMORY; }
- if (module->createimage_optspec)
- alloc_resolution->set_specification(module->createimage_optspec);
+ if (!module->createimage_optspec.empty())
+ alloc_resolution->set_specification(module->createimage_optspec.c_str());
opts = alloc_resolution.get();
}
@@ -1316,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;
}
@@ -1489,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);
@@ -1516,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)
@@ -1552,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;
}
@@ -1563,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;
@@ -1592,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;
@@ -1602,7 +1563,7 @@ imgtoolerr_t imgtool::partition::get_chain_string(const char *path, char *buffer
chain[0].block = ~0;
last_block = chain[0].block;
- err = get_chain(path, chain, ARRAY_LENGTH(chain));
+ err = get_chain(path, chain, std::size(chain));
if (err)
return err;
@@ -1883,7 +1844,7 @@ imgtoolerr_t imgtool::partition::put_file(const char *newfname, const char *fork
if (!newfname)
{
- basename = core_filename_extract_base(source);
+ basename = std::string(core_filename_extract_base(source));
newfname = basename.c_str();
}
@@ -2276,7 +2237,7 @@ imgtool::directory::directory(imgtool::partition &partition)
if (partition.m_directory_extra_bytes > 0)
{
m_extra_bytes = std::make_unique<uint8_t[]>(partition.m_directory_extra_bytes);
- memset(m_extra_bytes.get(), 0, sizeof(m_extra_bytes.get()[0] * partition.m_directory_extra_bytes));
+ memset(m_extra_bytes.get(), 0, sizeof(m_extra_bytes[0]) * partition.m_directory_extra_bytes);
}
}
@@ -2341,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)
@@ -2361,7 +2321,7 @@ imgtoolerr_t imgtool::directory::get_next(imgtool_dirent &ent)
{
return imgtoolerr_t(IMGTOOLERR_BADFILENAME);
}
- snprintf(ent.filename, ARRAY_LENGTH(ent.filename), "%s", new_fname.c_str());
+ snprintf(ent.filename, std::size(ent.filename), "%s", new_fname.c_str());
}
// don't trust the module!
@@ -2393,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 aa4ae79e29e..4ad7fc5479d 100644
--- a/src/tools/imgtool/imgtool.h
+++ b/src/tools/imgtool/imgtool.h
@@ -8,19 +8,19 @@
***************************************************************************/
-#ifndef IMGTOOL_H
-#define IMGTOOL_H
+#ifndef MAME_TOOLS_IMGTOOL_IMGTOOL_H
+#define MAME_TOOLS_IMGTOOL_IMGTOOL_H
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <functional>
+#pragma once
-#include "corestr.h"
-#include "formats/flopimg.h"
-#include "opresolv.h"
#include "library.h"
-#include "filter.h"
+#include "stream.h"
+
+#include "osdcomm.h"
+
+#include <cassert>
+#include <cstdlib>
+#include <functional>
/* ----------------------------------------------------------------------- */
@@ -94,7 +94,7 @@ namespace imgtool
public:
typedef std::unique_ptr<image> ptr;
- image(const imgtool_module &module, object_pool *pool, void *extra_bytes);
+ image(const imgtool_module &module);
~image();
static imgtoolerr_t identify_file(const char *filename, imgtool_module **modules, size_t count);
@@ -114,14 +114,12 @@ namespace imgtool
imgtoolerr_t write_block(uint64_t block, const void *buffer);
imgtoolerr_t clear_block(uint64_t block, uint8_t data);
imgtoolerr_t list_partitions(std::vector<imgtool::partition_info> &partitions);
- void *malloc(size_t size);
const imgtool_module &module() { return m_module; }
- void *extra_bytes() { return m_extra_bytes; }
+ void *extra_bytes() { return m_extra_bytes.get(); }
private:
const imgtool_module &m_module;
- object_pool *m_pool;
- void *m_extra_bytes;
+ std::unique_ptr<uint8_t[]> m_extra_bytes;
// because of an idiosyncrasy of how imgtool::image::internal_open() works, we are only "okay to close"
// by invoking the module's close function once internal_open() succeeds. the long term solution is
@@ -168,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);
@@ -217,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;
@@ -264,6 +262,6 @@ void unknown_partition_get_info(const imgtool_class *imgclass, uint32_t state, u
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);
+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.cpp b/src/tools/imgtool/library.cpp
index 785054575b0..3b05d947a49 100644
--- a/src/tools/imgtool/library.cpp
+++ b/src/tools/imgtool/library.cpp
@@ -9,12 +9,12 @@
****************************************************************************/
-#include <string.h>
-#include <algorithm>
-
-#include "imgtool.h"
#include "library.h"
-#include "pool.h"
+
+#include "corestr.h"
+
+#include <algorithm>
+#include <cstring>
namespace imgtool {
@@ -145,9 +145,6 @@ time_t datetime::to_time_t() const
library::library()
{
- m_pool = pool_alloc_lib(nullptr);
- if (!m_pool)
- throw std::bad_alloc();
}
@@ -157,7 +154,6 @@ library::library()
library::~library()
{
- pool_free_lib(m_pool);
}
@@ -167,30 +163,25 @@ library::~library()
void library::add_class(const imgtool_class *imgclass)
{
- char *s1, *s2;
+ char const *temp;
// allocate the module and place it in the chain
m_modules.emplace_back(std::make_unique<imgtool_module>());
imgtool_module *module = m_modules.back().get();
- memset(module, 0, sizeof(*module));
-
- // extensions have a weird format
- s1 = imgtool_get_info_string(imgclass, IMGTOOLINFO_STR_FILE_EXTENSIONS);
- s2 = (char*)imgtool_library_malloc(strlen(s1) + 1);
- strcpy(s2, s1);
- module->extensions = s2;
module->imgclass = *imgclass;
- module->name = imgtool_library_strdup(imgtool_get_info_string(imgclass, IMGTOOLINFO_STR_NAME));
- module->description = imgtool_library_strdup(imgtool_get_info_string(imgclass, IMGTOOLINFO_STR_DESCRIPTION));
- module->eoln = imgtool_library_strdup_allow_null(imgtool_get_info_string(imgclass, IMGTOOLINFO_STR_EOLN));
- module->initial_path_separator = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_INITIAL_PATH_SEPARATOR) ? 1 : 0;
- module->open_is_strict = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_OPEN_IS_STRICT) ? 1 : 0;
- module->tracks_are_called_cylinders = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_TRACKS_ARE_CALLED_CYLINDERS) ? 1 : 0;
- module->writing_untested = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_WRITING_UNTESTED) ? 1 : 0;
- module->creation_untested = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_CREATION_UNTESTED) ? 1 : 0;
- module->open = (imgtoolerr_t (*)(imgtool::image &, imgtool::stream::ptr &&)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_OPEN);
- module->create = (imgtoolerr_t (*)(imgtool::image &, imgtool::stream::ptr &&, util::option_resolution *)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_CREATE);
+ module->name = imgtool_get_info_string(imgclass, IMGTOOLINFO_STR_NAME);
+ module->description = imgtool_get_info_string(imgclass, IMGTOOLINFO_STR_DESCRIPTION);
+ module->extensions = imgtool_get_info_string(imgclass, IMGTOOLINFO_STR_FILE_EXTENSIONS);
+ temp = imgtool_get_info_string(imgclass, IMGTOOLINFO_STR_EOLN);
+ module->eoln = (temp != nullptr) ? temp : "";
+ module->initial_path_separator = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_INITIAL_PATH_SEPARATOR) ? true : false;
+ module->open_is_strict = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_OPEN_IS_STRICT) ? true : false;
+ module->tracks_are_called_cylinders = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_TRACKS_ARE_CALLED_CYLINDERS) ? true : false;
+ module->writing_untested = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_WRITING_UNTESTED) ? true : false;
+ module->creation_untested = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_CREATION_UNTESTED) ? true : false;
+ module->open = (imgtoolerr_t (*)(imgtool::image &, std::unique_ptr<imgtool::stream> &&)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_OPEN);
+ module->create = (imgtoolerr_t (*)(imgtool::image &, std::unique_ptr<imgtool::stream> &&, util::option_resolution *)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_CREATE);
module->close = (void (*)(imgtool::image &)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_CLOSE);
module->info = (void (*)(imgtool::image &, std::ostream &)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_INFO);
module->read_sector = (imgtoolerr_t (*)(imgtool::image &, uint32_t, uint32_t, uint32_t, std::vector<uint8_t> &)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_READ_SECTOR);
@@ -201,7 +192,8 @@ void library::add_class(const imgtool_class *imgclass)
module->list_partitions = (imgtoolerr_t (*)(imgtool::image &, std::vector<imgtool::partition_info> &)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_LIST_PARTITIONS);
module->block_size = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_BLOCK_SIZE);
module->createimage_optguide = (const util::option_guide *) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE);
- module->createimage_optspec = imgtool_library_strdup_allow_null((const char*)imgtool_get_info_ptr(imgclass, IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC));
+ temp = (char const *)imgtool_get_info_ptr(imgclass, IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC);
+ module->createimage_optspec = (temp != nullptr) ? temp : "";
module->image_extra_bytes += imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES);
}
@@ -269,7 +261,7 @@ int library::module_compare(const imgtool_module *m1, const imgtool_module *m2,
switch(sort)
{
case sort_type::NAME:
- rc = strcmp(m1->name, m2->name);
+ rc = strcmp(m1->name.c_str(), m2->name.c_str());
break;
case sort_type::DESCRIPTION:
rc = core_stricmp(m1->description, m2->description);
@@ -319,34 +311,4 @@ const imgtool_module *library::findmodule(const std::string &module_name)
}
-//-------------------------------------------------
-// imgtool_library_malloc
-//-------------------------------------------------
-
-void *library::imgtool_library_malloc(size_t mem)
-{
- return pool_malloc_lib(m_pool, mem);
-}
-
-
-//-------------------------------------------------
-// imgtool_library_malloc
-//-------------------------------------------------
-
-char *library::imgtool_library_strdup(const char *s)
-{
- return pool_strdup_lib(m_pool, s);
-}
-
-
-//-------------------------------------------------
-// imgtool_library_strdup_allow_null
-//-------------------------------------------------
-
-char *library::imgtool_library_strdup_allow_null(const char *s)
-{
- return s ? imgtool_library_strdup(s) : nullptr;
-}
-
-
} // namespace imgtool
diff --git a/src/tools/imgtool/library.h b/src/tools/imgtool/library.h
index c709a70201b..023b5fb948f 100644
--- a/src/tools/imgtool/library.h
+++ b/src/tools/imgtool/library.h
@@ -4,39 +4,44 @@
library.h
- Code relevant to the Imgtool library; analogous to the MESS/MAME driver
- list.
+ Code relevant to the Imgtool library; analogous to the MAME driver list.
- Unlike MESS and MAME which have static driver lists, Imgtool has a
- concept of a library and this library is built at startup time.
+ Unlike MAME which has a static driver lists, Imgtool has a concept of a
+ library and this library is built at startup time.
dynamic for which modules are added to. This makes "dynamic" modules
much easier
****************************************************************************/
+#ifndef MAME_TOOLS_IMGTOOL_LIBRARY_H
+#define MAME_TOOLS_IMGTOOL_LIBRARY_H
-#ifndef LIBRARY_H
-#define LIBRARY_H
+#pragma once
-#include <time.h>
-#include <list>
-#include <chrono>
+#include "imgterrs.h"
-#include "corestr.h"
-#include "opresolv.h"
-#include "stream.h"
-#include "unicode.h"
-#include "charconv.h"
-#include "pool.h"
#include "timeconv.h"
+#include "utilfwd.h"
-namespace imgtool
-{
- class image;
- class partition;
- class directory;
-};
+#include <algorithm>
+#include <chrono>
+#include <cstdint>
+#include <ctime>
+#include <iosfwd>
+#include <list>
+#include <memory>
+#include <string>
+#include <vector>
-enum imgtool_suggestion_viability_t
+
+namespace imgtool {
+
+class image;
+class partition;
+class directory;
+class charconverter;
+class stream;
+
+enum suggestion_viability_t
{
SUGGESTION_END,
SUGGESTION_POSSIBLE,
@@ -52,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 --- */
@@ -381,9 +395,9 @@ union imgtoolinfo
void * f; /* generic function pointers */
char * s; /* generic strings */
- imgtoolerr_t (*open) (imgtool::image &image, imgtool::stream::ptr &&stream);
+ imgtoolerr_t (*open) (imgtool::image &image, std::unique_ptr<imgtool::stream> &&stream);
void (*close) (imgtool::image &image);
- imgtoolerr_t (*create) (imgtool::image &image, imgtool::stream::ptr &&stream, util::option_resolution *opts);
+ imgtoolerr_t (*create) (imgtool::image &image, std::unique_ptr<imgtool::stream> &&stream, util::option_resolution *opts);
imgtoolerr_t (*create_partition) (imgtool::image &image, uint64_t first_block, uint64_t block_count);
void (*info) (imgtool::image &image, std::ostream &stream);
imgtoolerr_t (*begin_enum) (imgtool::directory &enumeration, const char *path);
@@ -402,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);
@@ -459,39 +473,39 @@ char *imgtool_temp_str(void);
struct imgtool_module
{
- imgtool_class imgclass;
+ imgtool_class imgclass = { 0 };
- const char *name;
- const char *description;
- const char *extensions;
- const char *eoln;
+ std::string name;
+ std::string description;
+ std::string extensions;
+ std::string eoln;
- size_t image_extra_bytes;
+ size_t image_extra_bytes = 0;
/* flags */
- unsigned int initial_path_separator : 1;
- unsigned int open_is_strict : 1;
- unsigned int tracks_are_called_cylinders : 1; /* used for hard drivers */
- unsigned int writing_untested : 1; /* used when we support writing, but not in main build */
- unsigned int creation_untested : 1; /* used when we support creation, but not in main build */
-
- imgtoolerr_t (*open) (imgtool::image &image, imgtool::stream::ptr &&stream);
- void (*close) (imgtool::image &image);
- void (*info) (imgtool::image &image, std::ostream &stream);
- imgtoolerr_t (*create) (imgtool::image &image, imgtool::stream::ptr &&stream, util::option_resolution *opts);
- imgtoolerr_t (*get_geometry) (imgtool::image &image, uint32_t *track, 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);
- imgtoolerr_t (*read_block) (imgtool::image &image, void *buffer, uint64_t block);
- imgtoolerr_t (*write_block) (imgtool::image &image, const void *buffer, uint64_t block);
- imgtoolerr_t (*list_partitions)(imgtool::image &image, std::vector<imgtool::partition_info> &partitions);
-
- uint32_t block_size;
-
- const util::option_guide *createimage_optguide;
- const char *createimage_optspec;
-
- const void *extra;
+ bool initial_path_separator = false;
+ bool open_is_strict = false;
+ bool tracks_are_called_cylinders = false; /* used for hard drivers */
+ bool writing_untested = false; /* used when we support writing, but not in main build */
+ bool creation_untested = false; /* used when we support creation, but not in main build */
+
+ imgtoolerr_t (*open) (imgtool::image &image, std::unique_ptr<imgtool::stream> &&stream) = nullptr;
+ void (*close) (imgtool::image &image) = nullptr;
+ void (*info) (imgtool::image &image, std::ostream &stream) = nullptr;
+ imgtoolerr_t (*create) (imgtool::image &image, std::unique_ptr<imgtool::stream> &&stream, util::option_resolution *opts) = nullptr;
+ imgtoolerr_t (*get_geometry) (imgtool::image &image, uint32_t *track, uint32_t *heads, uint32_t *sectors) = nullptr;
+ imgtoolerr_t (*read_sector) (imgtool::image &image, uint32_t track, uint32_t head, uint32_t sector, std::vector<uint8_t> &buffer) = nullptr;
+ imgtoolerr_t (*write_sector) (imgtool::image &image, uint32_t track, uint32_t head, uint32_t sector, const void *buffer, size_t len) = nullptr;
+ imgtoolerr_t (*read_block) (imgtool::image &image, void *buffer, uint64_t block) = nullptr;
+ imgtoolerr_t (*write_block) (imgtool::image &image, const void *buffer, uint64_t block) = nullptr;
+ imgtoolerr_t (*list_partitions)(imgtool::image &image, std::vector<imgtool::partition_info> &partitions) = nullptr;
+
+ uint32_t block_size = 0;
+
+ const util::option_guide *createimage_optguide = nullptr;
+ std::string createimage_optspec;
+
+ const void *extra = nullptr;
};
namespace imgtool {
@@ -531,7 +545,6 @@ public:
const modulelist &modules() { return m_modules; }
private:
- object_pool * m_pool;
modulelist m_modules;
// internal lookup and iteration
@@ -540,13 +553,8 @@ private:
// helpers
void add_class(const imgtool_class *imgclass);
int module_compare(const imgtool_module *m1, const imgtool_module *m2, sort_type sort);
-
- // memory allocators for pooled library memory (these should go away in further C++-ification)
- void *imgtool_library_malloc(size_t mem);
- char *imgtool_library_strdup(const char *s);
- char *imgtool_library_strdup_allow_null(const char *s);
};
} // namespace imgtool
-#endif // LIBRARY_H
+#endif // MAME_TOOLS_IMGTOOL_LIBRARY_H
diff --git a/src/tools/imgtool/main.cpp b/src/tools/imgtool/main.cpp
index d5320beb347..ca38d7905cb 100644
--- a/src/tools/imgtool/main.cpp
+++ b/src/tools/imgtool/main.cpp
@@ -9,15 +9,23 @@
***************************************************************************/
#include "imgtool.h"
+#include "filter.h"
#include "main.h"
#include "modules.h"
+
+#include "corestr.h"
+#include "opresolv.h"
+#include "path.h"
#include "strformat.h"
+#include "unicode.h"
+
+#include "osdcore.h" // osd_get_command_line
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <time.h>
+#include <cstdio>
+#include <cstring>
+#include <cctype>
+#include <cstdlib>
+#include <ctime>
#include <iostream>
#ifdef _WIN32
@@ -29,7 +37,7 @@
static void writeusage(std::wostream &output, bool write_word_usage, const struct command *c, char *argv[])
{
- std::string cmdname = core_filename_extract_base(argv[0]);
+ std::string cmdname(core_filename_extract_base(argv[0]));
util::stream_format(output,
L"%s %s %s %s\n",
@@ -43,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;
@@ -97,7 +105,7 @@ static int parse_options(int argc, char *argv[], int minunnamed, int maxunnamed,
if (*fork)
goto optionalreadyspecified;
- snprintf(buf, ARRAY_LENGTH(buf), "%s", value);
+ snprintf(buf, std::size(buf), "%s", value);
*fork = buf;
}
else
@@ -107,6 +115,9 @@ static int parse_options(int argc, char *argv[], int minunnamed, int maxunnamed,
goto error; /* Too few unnamed */
util::option_resolution::entry *entry = resolution->find(name);
+ if (entry == nullptr)
+ goto error; /* Unknown option */
+
if (entry->option_type() == util::option_guide::entry::option_type::ENUM_BEGIN)
{
const util::option_guide::entry *enum_value;
@@ -231,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;
@@ -248,7 +258,7 @@ static int cmd_dir(const struct command *c, int argc, char *argv[])
{
std::string filesize_string = ent.directory
? "<DIR>"
- : string_format("%u", (unsigned int) ent.filesize);
+ : util::string_format("%u", (unsigned int) ent.filesize);
if (!ent.lastmodified_time.empty())
{
@@ -266,16 +276,16 @@ static int cmd_dir(const struct command *c, int argc, char *argv[])
columnwidth_attributes, wstring_from_utf8(ent.attr),
columnwidth_lastmodified, wstring_from_utf8(last_modified));
- if (ent.softlink && ent.softlink[0] != '\0')
+ if (ent.softlink[0] != '\0')
util::stream_format(std::wcout, L"-> %s\n", wstring_from_utf8(ent.softlink));
- if (ent.comment && ent.comment[0] != '\0')
+ if (ent.comment[0] != '\0')
util::stream_format(std::wcout, L": %s\n", wstring_from_utf8(ent.comment));
total_count++;
total_size += ent.filesize;
- memset(&ent, 0, sizeof(ent));
+ ent = imgtool_dirent();
}
freespace_err = partition->get_free_space(freespace);
@@ -306,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;
@@ -343,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;
@@ -406,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));
@@ -430,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;
@@ -458,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);
@@ -564,7 +571,7 @@ static int cmd_identify(const struct command *c, int argc, char *argv[])
imgtoolerr_t err;
int i;
- err = imgtool::image::identify_file(argv[0], modules, ARRAY_LENGTH(modules));
+ err = imgtool::image::identify_file(argv[0], modules, std::size(modules));
if (err)
{
reporterror(err, c, nullptr, argv[0], nullptr, nullptr, nullptr);
@@ -597,7 +604,7 @@ static int cmd_create(const struct command *c, int argc, char *argv[])
goto error;
}
- if (module->createimage_optguide && module->createimage_optspec)
+ if (module->createimage_optguide && !module->createimage_optspec.empty())
{
try { resolution.reset(new util::option_resolution(*module->createimage_optguide)); }
catch (...)
@@ -605,7 +612,7 @@ static int cmd_create(const struct command *c, int argc, char *argv[])
err = IMGTOOLERR_OUTOFMEMORY;
goto error;
}
- resolution->set_specification(module->createimage_optspec);
+ resolution->set_specification(module->createimage_optspec.c_str());
}
unnamedargs = parse_options(argc, argv, 2, 3, resolution.get(), nullptr, nullptr);
@@ -748,7 +755,7 @@ static void listoptions(const util::option_guide &opt_guide, const char *opt_spe
const util::option_resolution::entry &entry = *iter;
std::stringstream description_buffer;
- std::string opt_name = string_format("--%s", entry.identifier());
+ std::string opt_name = util::string_format("--%s", entry.identifier());
const char *opt_desc = entry.display_name();
// is this option relevant?
@@ -831,7 +838,7 @@ static int cmd_listdriveroptions(const struct command *c, int argc, char *argv[]
if (opt_guide)
{
util::stream_format(std::wcout, L"Image specific creation options (usable on the 'create' command):\n\n");
- listoptions(*opt_guide, mod->createimage_optspec);
+ listoptions(*opt_guide, mod->createimage_optspec.c_str());
util::stream_format(std::wcout, L"\n");
}
else
@@ -873,7 +880,7 @@ int main(int argc, char *argv[])
int result;
const struct command *c;
const char *sample_format = "coco_jvc_rsdos";
- std::string cmdname = core_filename_extract_base(argv[0]);
+ std::string cmdname(core_filename_extract_base(argv[0]));
#ifdef _WIN32
_setmode(_fileno(stdout), _O_U8TEXT);
@@ -895,7 +902,7 @@ int main(int argc, char *argv[])
if (argc > 1)
{
/* figure out what command they are running, and run it */
- for (i = 0; i < ARRAY_LENGTH(cmds); i++)
+ for (i = 0; i < std::size(cmds); i++)
{
c = &cmds[i];
if (!core_stricmp(c->name, argv[1]))
@@ -934,7 +941,7 @@ int main(int argc, char *argv[])
// Usage
util::stream_format(std::wcerr, L"imgtool - Generic image manipulation tool for use with MAME\n\n");
- for (i = 0; i < ARRAY_LENGTH(cmds); i++)
+ for (i = 0; i < std::size(cmds); i++)
{
writeusage(std::wcerr, (i == 0), &cmds[i], argv);
}
diff --git a/src/tools/imgtool/modules.cpp b/src/tools/imgtool/modules.cpp
index 1c573e3bcc9..fb443435a3b 100644
--- a/src/tools/imgtool/modules.cpp
+++ b/src/tools/imgtool/modules.cpp
@@ -8,7 +8,6 @@
***************************************************************************/
-#include "imgtool.h"
#include "modules.h"
#ifndef MODULES_RECURSIVE
@@ -29,8 +28,6 @@ static void (*const modules[])(const imgtool_class *imgclass, uint32_t state, un
/* step 3: declare imgtool_create_canonical_library() */
imgtoolerr_t imgtool_create_canonical_library(bool omit_untested, std::unique_ptr<imgtool::library> &library)
{
- size_t i;
-
/* list of modules that we drop */
static const char *const irrelevant_modules[] =
{
@@ -42,14 +39,12 @@ imgtoolerr_t imgtool_create_canonical_library(bool omit_untested, std::unique_pt
return IMGTOOLERR_OUTOFMEMORY;
// create all modules
- for (i = 0; i < ARRAY_LENGTH(modules); i++)
- library->add(modules[i]);
+ for (auto &module : modules)
+ library->add(module);
// remove irrelevant modules
- for (i = 0; i < ARRAY_LENGTH(irrelevant_modules); i++)
- {
- library->unlink(irrelevant_modules[i]);
- }
+ for (auto &module : irrelevant_modules)
+ library->unlink(module);
// if we are omitting untested, go through and block out the functionality in question
if (omit_untested)
@@ -64,7 +59,7 @@ imgtoolerr_t imgtool_create_canonical_library(bool omit_untested, std::unique_pt
{
module->create = nullptr;
module->createimage_optguide = nullptr;
- module->createimage_optspec = nullptr;
+ module->createimage_optspec.clear();
}
}
}
@@ -77,10 +72,9 @@ imgtoolerr_t imgtool_create_canonical_library(bool omit_untested, std::unique_pt
MODULE(amiga_floppy)
MODULE(concept)
-MODULE(mac_mfs)
-MODULE(mac_hfs)
MODULE(hd)
MODULE(rsdos)
+MODULE(dgndos)
MODULE(vzdos)
MODULE(os9)
MODULE(ti99_old)
@@ -91,8 +85,6 @@ MODULE(ti99_ti99hd)
MODULE(ti990)
MODULE(pc_floppy)
MODULE(pc_chd)
-MODULE(prodos_525)
-MODULE(prodos_35)
MODULE(thom_fd_basic)
MODULE(thom_qd_basic)
MODULE(thom_sap_basic)
diff --git a/src/tools/imgtool/modules/amiga.cpp b/src/tools/imgtool/modules/amiga.cpp
index c1c5563012e..fcf1bd779a6 100644
--- a/src/tools/imgtool/modules/amiga.cpp
+++ b/src/tools/imgtool/modules/amiga.cpp
@@ -1,4 +1,4 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Dirk Best
/****************************************************************************
@@ -13,14 +13,17 @@
Includes
*****************************************************************************/
-
-#include <time.h>
-#include <string.h>
-#include <ctype.h>
-
#include "imgtool.h"
+#include "charconv.h"
#include "iflopimg.h"
-#include "formats/imageutl.h"
+
+#include "corestr.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <cctype>
+#include <cstring>
+#include <ctime>
@@ -252,15 +255,22 @@ static int intl_toupper(int c)
/* Amiga filename case insensitive string compare */
-static int intl_stricmp(const char *s1, const char *s2)
+static int intl_stricmp(std::string_view s1, std::string_view s2)
{
- for (;;)
+ auto s1_iter = s1.begin();
+ auto s2_iter = s2.begin();
+ while (true)
{
- int c1 = intl_toupper(*s1++);
- int c2 = intl_toupper(*s2++);
+ if (s1.end() == s1_iter)
+ return (s2.end() == s2_iter) ? 0 : -1;
+ else if (s2.end() == s2_iter)
+ return 1;
- if (c1 == 0 || c1 != c2)
- return c1 - c2;
+ const int c1 = intl_toupper(uint8_t(*s1_iter++));
+ const int c2 = intl_toupper(uint8_t(*s2_iter++));
+ const int diff = c1 - c2;
+ if (diff)
+ return diff;
}
}
@@ -388,7 +398,7 @@ static uint32_t block_checksum(uint8_t *buffer, int length)
for (i = 0; i < length/4; i++)
{
- chksum += pick_integer_be(buffer, i*4, 4);
+ chksum += get_u32be(&buffer[i*4]);
}
return -chksum;
@@ -464,7 +474,7 @@ static sec_type get_block_type(imgtool::image &img, int block)
if (ret) return ST_INVALID;
/* return type */
- switch ((int32_t) pick_integer_be(buffer, BSIZE-4, 4))
+ switch (get_s32be(&buffer[BSIZE-4]))
{
case 1: return ST_ROOT;
case 2: return ST_USERDIR;
@@ -488,7 +498,7 @@ static imgtoolerr_t read_bitmap_block(imgtool::image &img, int block, bitmap_blo
if (ret) return ret;
/* fill in data */
- bm->chksum = pick_integer_be(buffer, 0, 4);
+ bm->chksum = get_u32be(&buffer[0]);
copy_integer_array_be(bm->map, (uint32_t *) &buffer[4], MSIZE);
return IMGTOOLERR_SUCCESS;
@@ -502,7 +512,7 @@ static imgtoolerr_t write_bitmap_block(imgtool::image &img, int block, const bit
uint8_t buffer[BSIZE];
/* Setup buffer */
- place_integer_be(buffer, 0, 4, bm->chksum);
+ put_u32be(&buffer[0], bm->chksum);
copy_integer_array_be((uint32_t *) &buffer[4], bm->map, MSIZE);
/* write block */
@@ -513,9 +523,8 @@ static imgtoolerr_t write_bitmap_block(imgtool::image &img, int block, const bit
}
-#ifdef UNUSED_FUNCTION
/* Read a bitmap extended block */
-static imgtoolerr_t read_bitmap_ext_block(imgtool::image *img, int block, bitmap_ext_block *bm)
+[[maybe_unused]] static imgtoolerr_t read_bitmap_ext_block(imgtool::image &img, int block, bitmap_ext_block *bm)
{
imgtoolerr_t ret;
uint8_t buffer[BSIZE];
@@ -526,11 +535,10 @@ static imgtoolerr_t read_bitmap_ext_block(imgtool::image *img, int block, bitmap
/* fill in data */
copy_integer_array_be(bm->map, (uint32_t *) &buffer, MSIZE);
- bm->next = pick_integer_be(buffer, BSIZE-4, 4);
+ bm->next = get_u32be(&buffer[BSIZE-4]);
return IMGTOOLERR_SUCCESS;
}
-#endif
/* Read the root block */
@@ -546,17 +554,17 @@ static imgtoolerr_t read_root_block(imgtool::image &img, root_block *root)
/* copy data to root_block */
memset(root, 0, sizeof(root_block));
- root->ht_size = pick_integer_be(buffer, 12, 4);
- root->chksum = pick_integer_be(buffer, 20, 4);
+ root->ht_size = get_u32be(&buffer[12]);
+ root->chksum = get_u32be(&buffer[20]);
copy_integer_array_be(root->ht, (uint32_t *) &buffer[24], TSIZE);
- root->bm_flag = pick_integer_be(buffer, BSIZE-200, 4);
+ root->bm_flag = get_u32be(&buffer[BSIZE-200]);
copy_integer_array_be(root->bm_pages, (uint32_t *) &buffer[BSIZE-196], 25);
copy_date_be(&root->r, (uint32_t *) &buffer[BSIZE-92]);
- root->name_len = pick_integer_be(buffer, BSIZE-80, 1);
+ root->name_len = buffer[BSIZE-80];
memcpy(root->diskname, &buffer[BSIZE-79], 30);
copy_date_be(&root->v, (uint32_t *) &buffer[BSIZE-40]);
copy_date_be(&root->c, (uint32_t *) &buffer[BSIZE-28]);
- root->extension = pick_integer_be(buffer, BSIZE-8, 4);
+ root->extension = get_u32be(&buffer[BSIZE-8]);
return IMGTOOLERR_SUCCESS;
}
@@ -570,25 +578,25 @@ static imgtoolerr_t write_root_block(imgtool::image &img, const root_block *root
/* Setup buffer */
memset(buffer, 0, BSIZE);
- place_integer_be(buffer, 0, 4, T_HEADER);
- place_integer_be(buffer, 12, 4, root->ht_size);
- place_integer_be(buffer, 20, 4, root->chksum);
+ put_u32be(&buffer[0], T_HEADER);
+ put_u32be(&buffer[12], root->ht_size);
+ put_u32be(&buffer[20], root->chksum);
copy_integer_array_be((uint32_t *) &buffer[24], root->ht, TSIZE);
- place_integer_be(buffer, BSIZE-200, 4, root->bm_flag);
+ put_u32be(&buffer[BSIZE-200], root->bm_flag);
copy_integer_array_be((uint32_t *) &buffer[BSIZE-196], root->bm_pages, 25);
- place_integer_be(buffer, BSIZE-92, 4, root->r.days);
- place_integer_be(buffer, BSIZE-88, 4, root->r.mins);
- place_integer_be(buffer, BSIZE-84, 4, root->r.ticks);
- place_integer_be(buffer, BSIZE-80, 1, root->name_len);
+ put_u32be(&buffer[BSIZE-92], root->r.days);
+ put_u32be(&buffer[BSIZE-88], root->r.mins);
+ put_u32be(&buffer[BSIZE-84], root->r.ticks);
+ buffer[BSIZE-80] = root->name_len;
memcpy(&buffer[BSIZE-79], root->diskname, root->name_len);
- place_integer_be(buffer, BSIZE-40, 4, root->v.days);
- place_integer_be(buffer, BSIZE-36, 4, root->v.mins);
- place_integer_be(buffer, BSIZE-32, 4, root->v.ticks);
- place_integer_be(buffer, BSIZE-28, 4, root->c.days);
- place_integer_be(buffer, BSIZE-24, 4, root->c.mins);
- place_integer_be(buffer, BSIZE-20, 4, root->c.ticks);
- place_integer_be(buffer, BSIZE-8, 4, root->extension);
- place_integer_be(buffer, BSIZE-4, 4, ST_ROOT);
+ put_u32be(&buffer[BSIZE-40], root->v.days);
+ put_u32be(&buffer[BSIZE-36], root->v.mins);
+ put_u32be(&buffer[BSIZE-32], root->v.ticks);
+ put_u32be(&buffer[BSIZE-28], root->c.days);
+ put_u32be(&buffer[BSIZE-24], root->c.mins);
+ put_u32be(&buffer[BSIZE-20], root->c.ticks);
+ put_u32be(&buffer[BSIZE-8], root->extension);
+ put_u32be(&buffer[BSIZE-4], ST_ROOT);
/* write root block to image */
ret = write_block(img, get_total_blocks(img)/2, buffer);
@@ -609,25 +617,25 @@ static imgtoolerr_t read_file_block(imgtool::image &img, int block, file_block *
if (ret) return ret;
/* fill in data */
- fb->header_key = pick_integer_be(buffer, 4, 4);
- fb->high_seq = pick_integer_be(buffer, 8, 4);
- fb->first_data = pick_integer_be(buffer, 16, 4);
- fb->chksum = pick_integer_be(buffer, 20, 4);
+ fb->header_key = get_u32be(&buffer[4]);
+ fb->high_seq = get_u32be(&buffer[8]);
+ fb->first_data = get_u32be(&buffer[16]);
+ fb->chksum = get_u32be(&buffer[20]);
copy_integer_array_be(fb->data_blocks, (uint32_t *) &buffer[24], TSIZE);
- fb->uid = pick_integer_be(buffer, BSIZE-196, 2);
- fb->gid = pick_integer_be(buffer, BSIZE-194, 2);
- fb->protect = pick_integer_be(buffer, BSIZE-192, 4);
- fb->byte_size = pick_integer_be(buffer, BSIZE-188, 4);
- fb->comm_len = pick_integer_be(buffer, BSIZE-184, 1);
+ fb->uid = get_u16be(&buffer[BSIZE-196]);
+ fb->gid = get_u16be(&buffer[BSIZE-194]);
+ fb->protect = get_u32be(&buffer[BSIZE-192]);
+ fb->byte_size = get_u32be(&buffer[BSIZE-188]);
+ fb->comm_len = buffer[BSIZE-184];
memcpy(fb->comment, &buffer[BSIZE-183], 79);
copy_date_be(&fb->date, (uint32_t *) &buffer[BSIZE-92]);
- fb->name_len = pick_integer_be(buffer, BSIZE-80, 1);
- memcpy(fb->filename, (uint32_t *) &buffer[BSIZE-79], 30);
- fb->real_entry = pick_integer_be(buffer, BSIZE-44, 4);
- fb->next_link = pick_integer_be(buffer, BSIZE-40, 4);
- fb->hash_chain = pick_integer_be(buffer, BSIZE-16, 4);
- fb->parent = pick_integer_be(buffer, BSIZE-12, 4);
- fb->extension = pick_integer_be(buffer, BSIZE-8, 4);
+ fb->name_len = buffer[BSIZE-80];
+ memcpy(fb->filename, &buffer[BSIZE-79], 30);
+ fb->real_entry = get_u32be(&buffer[BSIZE-44]);
+ fb->next_link = get_u32be(&buffer[BSIZE-40]);
+ fb->hash_chain = get_u32be(&buffer[BSIZE-16]);
+ fb->parent = get_u32be(&buffer[BSIZE-12]);
+ fb->extension = get_u32be(&buffer[BSIZE-8]);
return IMGTOOLERR_SUCCESS;
}
@@ -643,12 +651,12 @@ static imgtoolerr_t read_file_ext_block(imgtool::image &img, int block, file_ext
if (ret) return ret;
/* fill in data */
- fe->header_key = pick_integer_be(buffer, 4, 4);
- fe->high_seq = pick_integer_be(buffer, 8, 4);
- fe->chksum = pick_integer_be(buffer, 20, 4);
+ fe->header_key = get_u32be(&buffer[4]);
+ fe->high_seq = get_u32be(&buffer[8]);
+ fe->chksum = get_u32be(&buffer[20]);
copy_integer_array_be(fe->data_blocks, (uint32_t *) &buffer[24], TSIZE);
- fe->parent = pick_integer_be(buffer, BSIZE-12, 4);
- fe->extension = pick_integer_be(buffer, BSIZE-8, 4);
+ fe->parent = get_u32be(&buffer[BSIZE-12]);
+ fe->extension = get_u32be(&buffer[BSIZE-8]);
return IMGTOOLERR_SUCCESS;
}
@@ -664,11 +672,11 @@ static imgtoolerr_t read_data_block(imgtool::image &img, int block, data_block *
if (ret) return ret;
/* fill in data */
- d->header_key = pick_integer_be(buffer, 4, 4);
- d->seq_num = pick_integer_be(buffer, 8, 4);
- d->data_size = pick_integer_be(buffer, 12, 4);
- d->next_data = pick_integer_be(buffer, 16, 4);
- d->chksum = pick_integer_be(buffer, 20, 4);
+ d->header_key = get_u32be(&buffer[4]);
+ d->seq_num = get_u32be(&buffer[8]);
+ d->data_size = get_u32be(&buffer[12]);
+ d->next_data = get_u32be(&buffer[16]);
+ d->chksum = get_u32be(&buffer[20]);
memcpy(d->data, &buffer[24], BSIZE-24);
return IMGTOOLERR_SUCCESS;
@@ -686,21 +694,21 @@ static imgtoolerr_t read_dir_block(imgtool::image &img, int block, dir_block *db
if (ret) return ret;
/* fill in data */
- db->header_key = pick_integer_be(buffer, 4, 4);
- db->chksum = pick_integer_be(buffer, 20, 4);
+ db->header_key = get_u32be(&buffer[4]);
+ db->chksum = get_u32be(&buffer[20]);
copy_integer_array_be(db->ht, (uint32_t *) &buffer[24], TSIZE);
- db->uid = pick_integer_be(buffer, BSIZE-196, 2);
- db->gid = pick_integer_be(buffer, BSIZE-194, 2);
- db->protect = pick_integer_be(buffer, BSIZE-192, 4);
- db->comm_len = pick_integer_be(buffer, BSIZE-184, 1);
+ db->uid = get_u16be(&buffer[BSIZE-196]);
+ db->gid = get_u16be(&buffer[BSIZE-194]);
+ db->protect = get_u32be(&buffer[BSIZE-192]);
+ db->comm_len = buffer[BSIZE-184];
memcpy(db->comment, &buffer[BSIZE-183], 79);
copy_date_be(&db->date, (uint32_t *) &buffer[BSIZE-92]);
- db->name_len = pick_integer_be(buffer, BSIZE-80, 1);
+ db->name_len = buffer[BSIZE-80];
memcpy(db->dirname, (uint32_t *) &buffer[BSIZE-79], 30);
- db->next_link = pick_integer_be(buffer, BSIZE-40, 4);
- db->hash_chain = pick_integer_be(buffer, BSIZE-16, 4);
- db->parent = pick_integer_be(buffer, BSIZE-12, 4);
- db->extension = pick_integer_be(buffer, BSIZE-8, 4);
+ db->next_link = get_u32be(&buffer[BSIZE-40]);
+ db->hash_chain = get_u32be(&buffer[BSIZE-16]);
+ db->parent = get_u32be(&buffer[BSIZE-12]);
+ db->extension = get_u32be(&buffer[BSIZE-8]);
return IMGTOOLERR_SUCCESS;
}
@@ -714,25 +722,25 @@ static imgtoolerr_t write_dir_block(imgtool::image &img, int block, const dir_bl
memset(buffer, 0, BSIZE);
/* Copy data */
- place_integer_be(buffer, 0, 4, T_HEADER);
- place_integer_be(buffer, 4, 4, db->header_key);
- place_integer_be(buffer, 20, 4, db->chksum);
+ put_u32be(&buffer[0], T_HEADER);
+ put_u32be(&buffer[4], db->header_key);
+ put_u32be(&buffer[20], db->chksum);
copy_integer_array_be((uint32_t *) &buffer[24], db->ht, TSIZE);
- place_integer_be(buffer, BSIZE-196, 2, db->uid);
- place_integer_be(buffer, BSIZE-194, 2, db->gid);
- place_integer_be(buffer, BSIZE-192, 4, db->protect);
- place_integer_be(buffer, BSIZE-184, 1, db->comm_len);
- memcpy((uint32_t *) &buffer[BSIZE-183], db->comment, db->comm_len);
- place_integer_be(buffer, BSIZE-92, 4, db->date.days);
- place_integer_be(buffer, BSIZE-88, 4, db->date.mins);
- place_integer_be(buffer, BSIZE-84, 4, db->date.ticks);
- place_integer_be(buffer, BSIZE-80, 1, db->name_len);
- memcpy((uint32_t *) &buffer[BSIZE-79], db->dirname, db->name_len);
- place_integer_be(buffer, BSIZE-40, 4, db->next_link);
- place_integer_be(buffer, BSIZE-16, 4, db->hash_chain);
- place_integer_be(buffer, BSIZE-12, 4, db->parent);
- place_integer_be(buffer, BSIZE-8, 4, db->extension);
- place_integer_be(buffer, BSIZE-4, 4, ST_USERDIR);
+ put_u16be(&buffer[BSIZE-196], db->uid);
+ put_u16be(&buffer[BSIZE-194], db->gid);
+ put_u32be(&buffer[BSIZE-192], db->protect);
+ buffer[BSIZE-184] = db->comm_len;
+ memcpy(&buffer[BSIZE-183], db->comment, db->comm_len);
+ put_u32be(&buffer[BSIZE-92], db->date.days);
+ put_u32be(&buffer[BSIZE-88], db->date.mins);
+ put_u32be(&buffer[BSIZE-84], db->date.ticks);
+ buffer[BSIZE-80] = db->name_len;
+ memcpy(&buffer[BSIZE-79], db->dirname, db->name_len);
+ put_u32be(&buffer[BSIZE-40], db->next_link);
+ put_u32be(&buffer[BSIZE-16], db->hash_chain);
+ put_u32be(&buffer[BSIZE-12], db->parent);
+ put_u32be(&buffer[BSIZE-8], db->extension);
+ put_u32be(&buffer[BSIZE-4], ST_USERDIR);
/* Write block to disk */
return write_block(img, block, buffer);
@@ -749,19 +757,19 @@ static imgtoolerr_t read_hardlink_block(imgtool::image &img, int block, hardlink
if (ret) return ret;
/* fill in data */
- hl->header_key = pick_integer_be(buffer, 4, 4);
- hl->chksum = pick_integer_be(buffer, 20, 4);
- hl->protect = pick_integer_be(buffer, BSIZE-192, 4);
- hl->comm_len = pick_integer_be(buffer, BSIZE-184, 1);
+ hl->header_key = get_u32be(&buffer[4]);
+ hl->chksum = get_u32be(&buffer[20]);
+ hl->protect = get_u32be(&buffer[BSIZE-192]);
+ hl->comm_len = buffer[BSIZE-184];
memcpy(hl->comment, &buffer[BSIZE-183], 79);
copy_date_be(&hl->date, (uint32_t *) &buffer[BSIZE-92]);
- hl->name_len = pick_integer_be(buffer, BSIZE-80, 1);
- memcpy(hl->hlname, (uint32_t *) &buffer[BSIZE-79], 30);
- hl->real_entry = pick_integer_be(buffer, BSIZE-44, 4);
- hl->next_link = pick_integer_be(buffer, BSIZE-40, 4);
- hl->hash_chain = pick_integer_be(buffer, BSIZE-16, 4);
- hl->parent = pick_integer_be(buffer, BSIZE-12, 4);
- hl->sec_type = pick_integer_be(buffer, BSIZE-4, 4);
+ hl->name_len = buffer[BSIZE-80];
+ memcpy(hl->hlname, &buffer[BSIZE-79], 30);
+ hl->real_entry = get_u32be(&buffer[BSIZE-44]);
+ hl->next_link = get_u32be(&buffer[BSIZE-40]);
+ hl->hash_chain = get_u32be(&buffer[BSIZE-16]);
+ hl->parent = get_u32be(&buffer[BSIZE-12]);
+ hl->sec_type = get_u32be(&buffer[BSIZE-4]);
return IMGTOOLERR_SUCCESS;
}
@@ -777,17 +785,17 @@ static imgtoolerr_t read_softlink_block(imgtool::image &img, int block, softlink
if (ret) return ret;
/* fill in data */
- sl->header_key = pick_integer_be(buffer, 4, 4);
- sl->chksum = pick_integer_be(buffer, 20, 4);
+ sl->header_key = get_u32be(&buffer[4]);
+ sl->chksum = get_u32be(&buffer[20]);
memcpy(sl->symbolic_name, &buffer[24], BSIZE-224);
- sl->protect = pick_integer_be(buffer, BSIZE-192, 4);
- sl->comm_len = pick_integer_be(buffer, BSIZE-184, 1);
+ sl->protect = get_u32be(&buffer[BSIZE-192]);
+ sl->comm_len = buffer[BSIZE-184];
memcpy(sl->comment, &buffer[BSIZE-183], 79);
copy_date_be(&sl->date, (uint32_t *) &buffer[BSIZE-92]);
- sl->name_len = pick_integer_be(buffer, BSIZE-80, 1);
- memcpy(sl->slname, (uint32_t *) &buffer[BSIZE-79], 30);
- sl->hash_chain = pick_integer_be(buffer, BSIZE-16, 4);
- sl->parent = pick_integer_be(buffer, BSIZE-12, 4);
+ sl->name_len = buffer[BSIZE-80];
+ memcpy(sl->slname, &buffer[BSIZE-79], 30);
+ sl->hash_chain = get_u32be(&buffer[BSIZE-16]);
+ sl->parent = get_u32be(&buffer[BSIZE-12]);
return IMGTOOLERR_SUCCESS;
}
@@ -837,16 +845,14 @@ static int is_intl(imgtool::image &img)
t == DT_FFS_INTL_DIRC) ? true : false);
}
-#ifdef UNUSED_FUNCTION
/* Returns true if the disk uses the directory cache mode */
-static int is_dirc(imgtool::image *img)
+[[maybe_unused]] static int is_dirc(imgtool::image &img)
{
disk_type t = get_disk_type(img);
return ((t == DT_OFS_INTL_DIRC ||
t == DT_FFS_INTL_DIRC) ? true : false);
}
-#endif
static imgtoolerr_t get_hash_table(imgtool::image &img, int block, uint32_t *ht)
{
@@ -907,12 +913,10 @@ static imgtoolerr_t set_hash_table(imgtool::image &img, int block, const uint32_
return IMGTOOLERR_SUCCESS;
}
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t get_root_hash_table(imgtool::image *img, uint32_t *ht)
+[[maybe_unused]] static imgtoolerr_t get_root_hash_table(imgtool::image &img, uint32_t *ht)
{
return get_hash_table(img, get_total_blocks(img)/2, ht);
}
-#endif
static imgtoolerr_t get_blockname(imgtool::image &img, int block, char *dest)
{
@@ -941,7 +945,7 @@ static imgtoolerr_t get_hash_chain(imgtool::image &img, int block, uint32_t *cha
if (ret) return ret;
/* Get chain value */
- *chain = pick_integer_be(buffer, BSIZE-16, 4);
+ *chain = get_u32be(&buffer[BSIZE-16]);
return IMGTOOLERR_SUCCESS;
}
@@ -957,7 +961,7 @@ static imgtoolerr_t set_hash_chain(imgtool::image &img, int block, uint32_t chai
if (ret) return ret;
/* Copy new hash chain value into it */
- place_integer_be(buffer, BSIZE-16, 4, chain);
+ put_u32be(&buffer[BSIZE-16], chain);
/* Write it back again */
ret = write_block(img, block, buffer);
@@ -974,7 +978,7 @@ static imgtoolerr_t walk_hash_chain(imgtool::image &img, const char *path, int s
char name[31];
/* choose compare function depending on intl mode */
- int (*cmp)(const char *, const char *) = is_intl(img) ? &intl_stricmp : &core_stricmp;
+ int (*cmp)(std::string_view, std::string_view) = is_intl(img) ? &intl_stricmp : &core_stricmp;
/* initialize filenames */
memset(name, 0, sizeof(name));
@@ -1174,11 +1178,11 @@ static imgtoolerr_t fix_chksum(imgtool::image &img, int block, int bitmap)
/* update checksum */
if (bitmap)
{
- place_integer_be(buffer, 0, 4, chksum);
+ put_u32be(&buffer[0], chksum);
}
else
{
- place_integer_be(buffer, 20, 4, chksum);
+ put_u32be(&buffer[20], chksum);
}
/* write back new block data */
@@ -1273,9 +1277,9 @@ static imgtoolerr_t update_block_modified_date(imgtool::image &img, int block)
amiga_setup_time(now, &date);
/* Write new time into block */
- place_integer_be(buffer, BSIZE-92, 4, date.days);
- place_integer_be(buffer, BSIZE-88, 4, date.mins);
- place_integer_be(buffer, BSIZE-84, 4, date.ticks);
+ put_u32be(&buffer[BSIZE-92], date.days);
+ put_u32be(&buffer[BSIZE-88], date.mins);
+ put_u32be(&buffer[BSIZE-84], date.ticks);
/* Write block back to disk */
ret = write_block(img, block, buffer);
@@ -1367,8 +1371,7 @@ static int get_first_bit(uint32_t *array, int size)
}
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t walk_bitmap_ext_blocks(imgtool::image *img, int start, int *block)
+[[maybe_unused]] static imgtoolerr_t walk_bitmap_ext_blocks(imgtool::image &img, int start, int *block)
{
imgtoolerr_t ret;
bitmap_ext_block bm_ext;
@@ -1400,7 +1403,6 @@ static imgtoolerr_t walk_bitmap_ext_blocks(imgtool::image *img, int start, int *
/* else continue walking the list */
return walk_bitmap_ext_blocks(img, bm_ext.next, block);
}
-#endif
/* Searches for a block marked as free
@@ -1710,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);
}
@@ -1979,6 +1981,7 @@ static imgtoolerr_t amiga_image_nextenum(imgtool::directory &enumeration, imgtoo
case ST_LINKDIR:
ent.directory = 1;
+ [[fallthrough]];
case ST_LINKFILE:
{
@@ -2337,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;
}
@@ -2384,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 a1a3bdc203d..8c465032f28 100644
--- a/src/tools/imgtool/modules/bml3.cpp
+++ b/src/tools/imgtool/modules/bml3.cpp
@@ -18,12 +18,18 @@
- (used with MP-1802 floppy disk controller card)
*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
#include "imgtool.h"
+#include "filter.h"
#include "iflopimg.h"
+#include "corestr.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
#define MAX_SECTOR_SIZE 256
struct bml3_diskinfo
@@ -129,7 +135,7 @@ static floperr_t get_bml3_dirent(imgtool::image &f, int index_loc, struct bml3_d
ent->ftype = buf[11];
ent->asciiflag = buf[12];
ent->first_granule = buf[13];
- ent->lastsectorbytes = (buf[14] << 8) | buf[15];
+ ent->lastsectorbytes = get_u16be(&buf[14]);
break;
default:
return FLOPPY_ERROR_INVALIDIMAGE;
@@ -162,8 +168,7 @@ static floperr_t put_bml3_dirent(imgtool::image &f, int index_loc, const struct
buf[11] = ent->ftype;
buf[12] = ent->asciiflag;
buf[13] = ent->first_granule;
- buf[14] = ent->lastsectorbytes >> 8;
- buf[15] = ent->lastsectorbytes & 0xff;
+ put_u16be(&buf[14], ent->lastsectorbytes);
break;
default:
return FLOPPY_ERROR_INVALIDIMAGE;
@@ -512,7 +517,10 @@ static imgtoolerr_t bml3_diskimage_open(imgtool::image &image, imgtool::stream::
ferr = callbacks->get_sector_length(floppy, 0, 20, 1, &sector_length);
if (ferr)
return imgtool_floppy_error(ferr);
- int sectors_per_track = callbacks->get_sectors_per_track(floppy, 0, 20);
+
+ int sectors_per_track = -1;
+ if (callbacks->get_sectors_per_track)
+ sectors_per_track = callbacks->get_sectors_per_track(floppy, 0, 20);
if (heads_per_disk == 2 && sector_length == 128 && sectors_per_track == 16) {
// single-sided, single-density
@@ -604,8 +612,8 @@ eof:
get_dirent_fname(fname, &rsent);
- snprintf(ent.filename, ARRAY_LENGTH(ent.filename), "%s", fname);
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "%d %c", (int) rsent.ftype, (char) (rsent.asciiflag + 'B'));
+ snprintf(ent.filename, std::size(ent.filename), "%s", fname);
+ snprintf(ent.attr, std::size(ent.attr), "%d %c", (int) rsent.ftype, (char) (rsent.asciiflag + 'B'));
}
return IMGTOOLERR_SUCCESS;
}
@@ -832,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());
@@ -848,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;
}
@@ -903,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/concept.cpp b/src/tools/imgtool/modules/concept.cpp
index 6bc0fe1bf22..da9689d455a 100644
--- a/src/tools/imgtool/modules/concept.cpp
+++ b/src/tools/imgtool/modules/concept.cpp
@@ -8,12 +8,15 @@
Raphael Nabet, 2003
*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
#include "imgtool.h"
+#include "opresolv.h"
+
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
struct UINT16xE
{
uint8_t bytes[2];
@@ -201,7 +204,6 @@ static int read_physical_record(imgtool::stream &file_handle, int secnum, void *
return 0;
}
-#ifdef UNUSED_FUNCTION
/*
write_physical_record
@@ -213,7 +215,7 @@ static int read_physical_record(imgtool::stream &file_handle, int secnum, void *
Return non-zero on error
*/
-static int write_physical_record(imgtool::stream *file_handle, int secnum, const void *src)
+[[maybe_unused]] static int write_physical_record(imgtool::stream *file_handle, int secnum, const void *src)
{
int reply;
@@ -228,7 +230,6 @@ static int write_physical_record(imgtool::stream *file_handle, int secnum, const
return 0;
}
-#endif
/*
Search for a file name on a concept_image
@@ -357,8 +358,8 @@ static imgtoolerr_t concept_image_nextenum(imgtool::directory &enumeration, imgt
int len = iter->image->dev_dir.file_dir[iter->index].filename[0];
const char *type;
- if (len > ARRAY_LENGTH(ent.filename))
- len = ARRAY_LENGTH(ent.filename);
+ if (len > std::size(ent.filename))
+ len = std::size(ent.filename);
memcpy(ent.filename, iter->image->dev_dir.file_dir[iter->index].filename + 1, len);
ent.filename[len] = 0;
@@ -382,7 +383,7 @@ static imgtoolerr_t concept_image_nextenum(imgtool::directory &enumeration, imgt
type = "???";
break;
}
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "%s", type);
+ snprintf(ent.attr, std::size(ent.attr), "%s", type);
/* len in physrecs */
ent.filesize = get_UINT16xE(iter->image->dev_dir.vol_hdr.disk_flipped, iter->image->dev_dir.file_dir[iter->index].next_block)
diff --git a/src/tools/imgtool/modules/cybiko.cpp b/src/tools/imgtool/modules/cybiko.cpp
index 1b9f43ee298..bfe9bfdddb2 100644
--- a/src/tools/imgtool/modules/cybiko.cpp
+++ b/src/tools/imgtool/modules/cybiko.cpp
@@ -10,6 +10,9 @@
#include "imgtool.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
#include <zlib.h>
struct cybiko_file_system
@@ -52,8 +55,8 @@ enum
};
#define BLOCK_USED(x) (x[0] & 0x80)
-#define BLOCK_FILE_ID(x) buffer_read_16_be( x + 2)
-#define BLOCK_PART_ID(x) buffer_read_16_be( x + 4)
+#define BLOCK_FILE_ID(x) get_u16be( x + 2)
+#define BLOCK_PART_ID(x) get_u16be( x + 4)
#define BLOCK_FILENAME(x) (char*)(x + 7)
#define FILE_HEADER_SIZE 0x48
@@ -79,30 +82,6 @@ uint32_t cybiko_time_setup(const imgtool::datetime &t)
return cybiko_time_point.time_since_epoch().count();
}
-static uint32_t buffer_read_32_be( uint8_t *buffer)
-{
- return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3] << 0);
-}
-
-static uint16_t buffer_read_16_be( uint8_t *buffer)
-{
- return (buffer[0] << 8) | (buffer[1] << 0);
-}
-
-static void buffer_write_32_be( uint8_t *buffer, uint32_t data)
-{
- buffer[0] = (data >> 24) & 0xFF;
- buffer[1] = (data >> 16) & 0xFF;
- buffer[2] = (data >> 8) & 0xFF;
- buffer[3] = (data >> 0) & 0xFF;
-}
-
-static void buffer_write_16_be( uint8_t *buffer, uint16_t data)
-{
- buffer[0] = (data >> 8) & 0xFF;
- buffer[1] = (data >> 0) & 0xFF;
-}
-
// page = crc1 (4) + wcnt (2) + crc2 (2) + data (x) + unk (2)
static uint32_t page_buffer_calc_checksum_1( uint8_t *buffer, uint32_t size, int block_type)
@@ -113,9 +92,9 @@ static uint32_t page_buffer_calc_checksum_1( uint8_t *buffer, uint32_t size, int
static uint16_t page_buffer_calc_checksum_2( uint8_t *buffer)
{
uint16_t val = 0xAF17;
- val ^= buffer_read_16_be( buffer + 0);
- val ^= buffer_read_16_be( buffer + 2);
- val ^= buffer_read_16_be( buffer + 4);
+ val ^= get_u16be( buffer + 0);
+ val ^= get_u16be( buffer + 2);
+ val ^= get_u16be( buffer + 4);
return swapendian_int16(val);
}
@@ -124,11 +103,11 @@ static int page_buffer_verify( uint8_t *buffer, uint32_t size, int block_type)
uint32_t checksum_page, checksum_calc;
// checksum 1
checksum_calc = page_buffer_calc_checksum_1( buffer, size, block_type);
- checksum_page = buffer_read_32_be( buffer + 0);
+ checksum_page = get_u32be( buffer + 0);
if (checksum_calc != checksum_page) return false;
// checksum 2
checksum_calc = page_buffer_calc_checksum_2( buffer);
- checksum_page = buffer_read_16_be( buffer + 6);
+ checksum_page = get_u16be( buffer + 6);
if (checksum_calc != checksum_page) return false;
// ok
return true;
@@ -198,10 +177,10 @@ static int cfs_block_write( cybiko_file_system *cfs, uint8_t *buffer, int block_
uint8_t buffer_page[MAX_PAGE_SIZE];
uint32_t page;
memcpy( buffer_page + 8, buffer, cfs->page_size - 10);
- buffer_write_32_be( buffer_page + 0, page_buffer_calc_checksum_1( buffer_page, cfs->page_size, block_type));
- buffer_write_16_be( buffer_page + 4, cfs->write_count++);
- buffer_write_16_be( buffer_page + 6, page_buffer_calc_checksum_2( buffer_page));
- buffer_write_16_be( buffer_page + cfs->page_size - 2, 0xFFFF);
+ put_u32be( buffer_page + 0, page_buffer_calc_checksum_1( buffer_page, cfs->page_size, block_type));
+ put_u16be( buffer_page + 4, cfs->write_count++);
+ put_u16be( buffer_page + 6, page_buffer_calc_checksum_2( buffer_page));
+ put_u16be( buffer_page + cfs->page_size - 2, 0xFFFF);
if (!cfs_block_to_page( cfs, block_type, block, &page)) return false;
if (!cfs_page_write( cfs, buffer_page, page)) return false;
return true;
@@ -236,7 +215,7 @@ static int cfs_file_info( cybiko_file_system *cfs, uint16_t file_id, cfs_file *f
if (BLOCK_PART_ID(buffer) == 0)
{
strcpy( file->name, BLOCK_FILENAME(buffer));
- file->date = buffer_read_32_be( buffer + 6 + FILE_HEADER_SIZE - 4);
+ file->date = get_u32be( buffer + 6 + FILE_HEADER_SIZE - 4);
}
file->size += buffer[1];
file->blocks++;
@@ -499,13 +478,13 @@ static imgtoolerr_t cybiko_image_write_file(imgtool::partition &partition, const
buffer[0] = 0x80;
buffer[1] = cfs->page_size - 0x10 - ((part_id == 0) ? FILE_HEADER_SIZE : 0);
if (bytes_left < buffer[1]) buffer[1] = bytes_left;
- buffer_write_16_be( buffer + 2, file_id);
- buffer_write_16_be( buffer + 4, part_id);
+ put_u16be( buffer + 2, file_id);
+ put_u16be( buffer + 4, part_id);
if (part_id == 0)
{
buffer[6] = 0;
strcpy(BLOCK_FILENAME(buffer), filename);
- buffer_write_32_be(buffer + 6 + FILE_HEADER_SIZE - 4, cybiko_time_setup(imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL)));
+ put_u32be(buffer + 6 + FILE_HEADER_SIZE - 4, cybiko_time_setup(imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL)));
sourcef.read(buffer + 6 + FILE_HEADER_SIZE, buffer[1]);
}
else
diff --git a/src/tools/imgtool/modules/cybikoxt.cpp b/src/tools/imgtool/modules/cybikoxt.cpp
index 8c2980de449..556f37fde76 100644
--- a/src/tools/imgtool/modules/cybikoxt.cpp
+++ b/src/tools/imgtool/modules/cybikoxt.cpp
@@ -10,6 +10,8 @@
#include "imgtool.h"
+#include "multibyte.h"
+
#include <zlib.h>
struct cybiko_file_system
@@ -44,8 +46,8 @@ enum
#define INVALID_FILE_ID 0xFFFF
#define BLOCK_USED(x) (x[0] & 0x80)
-#define BLOCK_FILE_ID(x) buffer_read_16_be( x + 2)
-#define BLOCK_PART_ID(x) buffer_read_16_be( x + 4)
+#define BLOCK_FILE_ID(x) get_u16be( x + 2)
+#define BLOCK_PART_ID(x) get_u16be( x + 4)
#define BLOCK_FILENAME(x) (char*)(x + 7)
#define FILE_HEADER_SIZE 0x48
@@ -58,30 +60,6 @@ static cybiko_file_system *get_cfs(imgtool::image &image)
extern imgtool::datetime cybiko_time_crack(uint32_t cfs_time);
extern uint32_t cybiko_time_setup(const imgtool::datetime &t);
-static uint32_t buffer_read_32_be( uint8_t *buffer)
-{
- return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3] << 0);
-}
-
-static uint16_t buffer_read_16_be( uint8_t *buffer)
-{
- return (buffer[0] << 8) | (buffer[1] << 0);
-}
-
-static void buffer_write_32_be( uint8_t *buffer, uint32_t data)
-{
- buffer[0] = (data >> 24) & 0xFF;
- buffer[1] = (data >> 16) & 0xFF;
- buffer[2] = (data >> 8) & 0xFF;
- buffer[3] = (data >> 0) & 0xFF;
-}
-
-static void buffer_write_16_be( uint8_t *buffer, uint16_t data)
-{
- buffer[0] = (data >> 8) & 0xFF;
- buffer[1] = (data >> 0) & 0xFF;
-}
-
// page = crc (2) + data (x)
static uint16_t page_buffer_calc_checksum( uint8_t *data, uint32_t size)
@@ -103,7 +81,7 @@ static int page_buffer_verify( uint8_t *buffer, uint32_t size, int block_type)
{
uint32_t checksum_page, checksum_calc;
checksum_calc = page_buffer_calc_checksum( buffer + 2, size - 2);
- checksum_page = buffer_read_16_be( buffer + 0);
+ checksum_page = get_u16be( buffer + 0);
if (checksum_calc != checksum_page) return false;
}
// ok
@@ -183,7 +161,7 @@ static int cfs_block_write( cybiko_file_system *cfs, uint8_t *buffer, int block_
{
checksum = page_buffer_calc_checksum( buffer_page + 2, cfs->page_size - 2);
}
- buffer_write_16_be( buffer_page + 0, checksum);
+ put_u16be( buffer_page + 0, checksum);
if (!cfs_block_to_page( cfs, block_type, block, &page)) return false;
if (!cfs_page_write( cfs, buffer_page, page)) return false;
return true;
@@ -218,7 +196,7 @@ static int cfs_file_info( cybiko_file_system *cfs, uint16_t file_id, cfs_file *f
if (BLOCK_PART_ID(buffer) == 0)
{
strcpy( file->name, BLOCK_FILENAME(buffer));
- file->date = buffer_read_32_be( buffer + 6 + FILE_HEADER_SIZE - 4);
+ file->date = get_u32be( buffer + 6 + FILE_HEADER_SIZE - 4);
}
file->size += buffer[1];
file->blocks++;
@@ -460,13 +438,13 @@ static imgtoolerr_t cybiko_image_write_file(imgtool::partition &partition, const
buffer[0] = 0x80;
buffer[1] = (cfs->page_size - 2) - 6 - ((part_id == 0) ? FILE_HEADER_SIZE : 0);
if (bytes_left < buffer[1]) buffer[1] = bytes_left;
- buffer_write_16_be( buffer + 2, file_id);
- buffer_write_16_be( buffer + 4, part_id);
+ put_u16be( buffer + 2, file_id);
+ put_u16be( buffer + 4, part_id);
if (part_id == 0)
{
buffer[6] = 0x20;
strcpy(BLOCK_FILENAME(buffer), filename);
- buffer_write_32_be( buffer + 6 + FILE_HEADER_SIZE - 4, cybiko_time_setup(imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL)));
+ put_u32be( buffer + 6 + FILE_HEADER_SIZE - 4, cybiko_time_setup(imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL)));
sourcef.read(buffer + 6 + FILE_HEADER_SIZE, buffer[1]);
}
else
diff --git a/src/tools/imgtool/modules/dgndos.cpp b/src/tools/imgtool/modules/dgndos.cpp
new file mode 100644
index 00000000000..692c010d057
--- /dev/null
+++ b/src/tools/imgtool/modules/dgndos.cpp
@@ -0,0 +1,1256 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/****************************************************************************
+
+ dgndos.cpp
+
+ Dragon DOS disk images
+
+ I am not happy with the sector allocation algorithm
+
+****************************************************************************/
+
+#include "imgtool.h"
+#include "filter.h"
+#include "iflopimg.h"
+
+#include "formats/coco_dsk.h"
+#include "corestr.h"
+#include "opresolv.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#ifdef _MSC_VER
+#pragma pack(push,1)
+#define A_PACKED
+#else
+#define A_PACKED __attribute__((packed))
+#endif
+
+typedef struct A_PACKED dngdos_sector_allocation_format {
+ uint16_t lsn;
+ uint8_t count;
+} dngdos_sector_allocation_format;
+
+typedef struct A_PACKED dngdos_file_header_block {
+ char filename[11];
+ dngdos_sector_allocation_format block[4];
+} dngdos_file_header_block;
+
+typedef struct A_PACKED dngdos_file_continuation_block {
+ dngdos_sector_allocation_format block[7];
+ uint16_t unused;
+} dngdos_file_continuation_block;
+
+struct A_PACKED dgndos_dirent
+{
+ unsigned char flag_byte;
+ union block {
+ dngdos_file_header_block header;
+ dngdos_file_continuation_block continuation;
+ } block;
+ uint8_t dngdos_last_or_next;
+};
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif
+
+struct dgndos_direnum
+{
+ int index;
+ bool eof;
+};
+
+/*********************************************************************
+ Imgtool module code
+*********************************************************************/
+
+#define DGNDOS_OPTIONS_PROTECT 'P'
+#define MAX_DIRENTS 160
+#define HEADER_EXTENTS_COUNT 4
+#define CONT_EXTENTS_COUNT 7
+
+#define DGNDOS_DELETED_BIT 0x80 // deleted entry
+#define DGNDOS_CONTINUED_BIT 0x20 // byte at offset 0x18 give next entry number
+#define DGNDOS_END_BIT 0x08 // end of directory
+#define DGNDOS_PROTECT_BIT 0x02 // ignored
+#define DGNDOS_CONTINUATION_BIT 0x01 // this is a continuation block
+
+static imgtoolerr_t get_dgndos_dirent(uint8_t *track, int index_loc, dgndos_dirent &ent)
+{
+ if (index_loc >= MAX_DIRENTS)
+ return IMGTOOLERR_FILENOTFOUND;
+
+ int sector = 3 + (index_loc / 10);
+ int offset = (index_loc * 25) % 250;
+
+ memcpy( (void *)&ent, track + (256 * (sector-1)) + offset, sizeof(ent));
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t put_dgndos_dirent(uint8_t *track, int index_loc, const dgndos_dirent &ent)
+{
+ if (index_loc >= MAX_DIRENTS)
+ return IMGTOOLERR_FILENOTFOUND;
+
+ int sector = 3 + (index_loc / 10);
+ int offset = (index_loc * 25) % 250;
+
+ memcpy( track + (256 * (sector-1)) + offset, (void *)&ent, sizeof(ent));
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static std::string get_dirent_fname(const dgndos_dirent &ent)
+{
+ return extract_padded_filename(ent.block.header.filename, 8, 3, '\0');
+}
+
+static bool dgndos_real_file( dgndos_dirent &ent )
+{
+ if( ent.flag_byte & DGNDOS_DELETED_BIT) return false;
+ if( ent.flag_byte & DGNDOS_CONTINUATION_BIT) return false;
+
+ return true;
+}
+
+static imgtoolerr_t lookup_dgndos_file(uint8_t *entire_track, const char *fname, dgndos_dirent &ent, int *position = nullptr)
+{
+ int i = 0;
+ imgtoolerr_t err;
+ std::string fnamebuf;
+
+ do
+ {
+ do
+ {
+ err = get_dgndos_dirent( entire_track, i++, ent );
+ if( err ) return err;
+
+ if( ent.flag_byte & DGNDOS_END_BIT ) return IMGTOOLERR_FILENOTFOUND;
+ }
+ while( ! dgndos_real_file(ent) );
+
+ fnamebuf = get_dirent_fname(ent);
+ }
+ while(core_stricmp(fnamebuf, fname));
+
+ if (position)
+ *position = i - 1;
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_get_geometry(uint8_t *entire_track, int *bitmap_count, int *heads, int *tracks_on_disk, int *sectors_per_track)
+{
+ unsigned int tod, spt, sides;
+
+ tod = entire_track[0xfc];
+ spt = entire_track[0xfd];
+
+ if( (~tod & 0xff) != entire_track[0xfe])
+ {
+// fprintf( stderr, "tracks_on_disk check failed: %u == %u\n", (~tod & 0xff), entire_track[0xfe] );
+ return IMGTOOLERR_CORRUPTIMAGE;
+ }
+
+ if( (~spt & 0xff) != entire_track[0xff])
+ {
+// fprintf( stderr, "sectors_per_track check failed: %u == %u\n", (~spt & 0xff), entire_track[0xff] );
+ return IMGTOOLERR_CORRUPTIMAGE;
+ }
+
+ if(spt == 36)
+ {
+ sides = 1;
+ }
+ else if(spt == 18 )
+ {
+ sides = 0;
+ }
+ else
+ {
+// fprintf( stderr, "sides check failed\n" );
+ return IMGTOOLERR_CORRUPTIMAGE;
+ }
+
+ if( heads ) *heads = sides;
+ if( tracks_on_disk) *tracks_on_disk = tod;
+ if( sectors_per_track ) *sectors_per_track = spt;
+ if( bitmap_count ) *bitmap_count = (tod * sides * 18) + (tod * 18);
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_convert_lsn(uint8_t *entire_track, int lsn, int *head, int *track, int *sector )
+{
+ int tracks_on_disk;
+ int sectors_per_track;
+ int sides;
+
+ imgtoolerr_t err = dgndos_get_geometry(entire_track, nullptr, &sides, &tracks_on_disk, &sectors_per_track);
+ if(err) return err;
+
+ if( sides == 0 )
+ {
+ *head = 0;
+ *track = lsn / 18;
+ *sector = (lsn % 18) + 1;
+ }
+ else
+ {
+ *head = (lsn / 18) % 2;
+ *track = lsn / 36;
+ *sector = (lsn % 18) + 1;
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+#define ALLOCATE_BIT 1
+#define QUERY_BIT 0
+#define DEALLOCATE_BIT -1
+
+static int dgndos_set_reset_bitmap( uint8_t *entire_track, int lsn, int set )
+{
+ int startbyte = lsn / 8;
+ int startbit = lsn % 8;
+
+ if( lsn > 1439 ) startbyte += 76;
+
+ if(set > QUERY_BIT) // ALLOCATE_BIT
+ {
+ // 0 = used, 1 = free
+ entire_track[startbyte] &= ~(1 << startbit);
+ }
+ else if( set < QUERY_BIT ) // DEALLOCATE_BIT
+ {
+ // 0 = used, 1 = free
+ entire_track[startbyte] |= (1 << startbit);
+ }
+
+ // 0 = used, 1 = free
+ return (entire_track[startbyte] & (1 << startbit)) != 0;
+}
+
+static int dgndos_is_sector_avaiable(uint8_t *entire_track, int lsn)
+{
+ return dgndos_set_reset_bitmap( entire_track, lsn, QUERY_BIT );
+}
+
+static int dgndos_fat_allocate_sector(uint8_t *entire_track, int lsn)
+{
+ return dgndos_set_reset_bitmap( entire_track, lsn, ALLOCATE_BIT );
+}
+
+static int dgndos_fat_deallocate_sector(uint8_t *entire_track, int lsn)
+{
+ return dgndos_set_reset_bitmap( entire_track, lsn, DEALLOCATE_BIT );
+}
+
+static int dgndos_fat_deallocate_span(uint8_t *entire_track, int lsn, int count)
+{
+ int value = 0;
+
+ for( int i=lsn; i<lsn+count; i++)
+ {
+ value = dgndos_fat_deallocate_sector(entire_track, i);
+ }
+
+ return value;
+}
+
+static imgtoolerr_t dgndos_get_avaiable_dirent_position(uint8_t *entire_track, int *position )
+{
+ int i;
+ imgtoolerr_t err;
+ dgndos_dirent ent;
+
+ for( i=0; i<MAX_DIRENTS; i++ )
+ {
+ err = get_dgndos_dirent(entire_track, i, ent);
+ if( err ) return err;
+
+ if( ent.flag_byte & DGNDOS_DELETED_BIT) break;
+
+ if( ent.flag_byte & DGNDOS_END_BIT) break;
+ }
+
+ if( i == MAX_DIRENTS )
+ {
+ return IMGTOOLERR_NOSPACE;
+ }
+
+ if( position ) *position = i;
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_get_avaiable_dirent(uint8_t *entire_track, dgndos_dirent &ent, int *position )
+{
+ int i;
+ imgtoolerr_t err;
+
+ for( i=0; i<MAX_DIRENTS; i++ )
+ {
+ err = get_dgndos_dirent(entire_track, i, ent);
+ if( err ) return err;
+
+ if( ent.flag_byte & DGNDOS_DELETED_BIT) break;
+
+ if( ent.flag_byte & DGNDOS_END_BIT) break;
+ }
+
+ if( i == MAX_DIRENTS )
+ {
+ return IMGTOOLERR_NOSPACE;
+ }
+
+ if( position ) *position = i;
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_get_avaiable_sector( uint8_t *entire_track, int *lsn )
+{
+ int bitmap_count, i;
+ int pos_diff = 18;
+ int neg_diff = 36;
+ int start = 360;
+
+ imgtoolerr_t err = dgndos_get_geometry(entire_track, &bitmap_count, nullptr, nullptr, nullptr);
+ if(err) return err;
+
+ do
+ {
+ i = start;
+ while ( i >= 0 )
+ {
+ if( dgndos_is_sector_avaiable(entire_track, i) )
+ {
+ *lsn = i;
+ return IMGTOOLERR_SUCCESS;
+ }
+
+ i -= neg_diff;
+ }
+
+ i = start;
+ while( i < bitmap_count )
+ {
+ if( dgndos_is_sector_avaiable(entire_track, i) )
+ {
+ *lsn = i;
+ return IMGTOOLERR_SUCCESS;
+ }
+
+ i += pos_diff;
+ }
+
+ start--;
+ }
+ while( start >= 335 );
+
+ return IMGTOOLERR_NOSPACE;
+}
+
+static imgtoolerr_t dgndos_count_dirents(uint8_t *entire_track, dgndos_dirent dgnent, int *result)
+{
+ imgtoolerr_t err = IMGTOOLERR_SUCCESS;
+ *result = 1;
+
+ while( (dgnent.flag_byte & DGNDOS_CONTINUED_BIT) && *result < MAX_DIRENTS )
+ {
+ (*result)++;
+ err = get_dgndos_dirent(entire_track, dgnent.dngdos_last_or_next, dgnent);
+ }
+
+ return err;
+}
+
+static imgtoolerr_t dgndos_get_file_size(uint8_t *entire_track, dgndos_dirent dgnent, size_t &filesize)
+{
+ imgtoolerr_t err;
+ int directory_entry_count = 0;
+ int extent = 0;
+ int block_size;
+ int done;
+ int count;
+ int i;
+
+ filesize = 0;
+
+ do
+ {
+ if(directory_entry_count>MAX_DIRENTS) return IMGTOOLERR_CORRUPTDIR;
+
+ count = dgnent.flag_byte & DGNDOS_CONTINUATION_BIT ? dgnent.block.continuation.block[extent].count : dgnent.block.header.block[extent].count;
+
+ if( count == 0 ) break;
+
+ i = 0;
+
+ // count extents except last sector
+ while (i < count - 1)
+ {
+ filesize += 256;
+ i++;
+ }
+
+ block_size = 256;
+ done = false;
+
+ if( extent < (dgnent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT) - 1 )
+ {
+ if( (dgnent.flag_byte & DGNDOS_CONTINUATION_BIT ? dgnent.block.continuation.block[extent+1].count : dgnent.block.header.block[extent+1].count) == 0 )
+ {
+ // not last extent, and yes continuation
+ if( dgnent.dngdos_last_or_next == 0 )
+ block_size = 256;
+ else
+ block_size = dgnent.dngdos_last_or_next;
+
+ done = true;
+ }
+ }
+ else if( extent == (dgnent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT) - 1)
+ {
+ if( !(dgnent.flag_byte & DGNDOS_CONTINUED_BIT) )
+ {
+ // is last extent, and no continuation
+ if( dgnent.dngdos_last_or_next == 0 )
+ block_size = 256;
+ else
+ block_size = dgnent.dngdos_last_or_next;
+
+ done = true;
+ }
+ }
+
+ filesize += block_size;
+
+ extent++;
+
+ if( extent == (dgnent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT) )
+ {
+ if( dgnent.flag_byte & DGNDOS_CONTINUED_BIT)
+ {
+ err = get_dgndos_dirent(entire_track, dgnent.dngdos_last_or_next, *(&dgnent) );
+ if(err) return err;
+
+ extent = 0;
+ directory_entry_count++;
+ }
+ }
+ }
+ while( !done );
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static floperr_t dgndos_get_directory_track( imgtool::image &image, int track, uint8_t *buffer )
+{
+ floperr_t ferr;
+
+ for(int i=1; i<=18; i++ )
+ {
+ ferr = floppy_read_sector(imgtool_floppy(image), 0, track, i, 0, &(buffer[(i-1)*256]), 256);
+ if(ferr) break;
+ }
+
+ return ferr;
+}
+
+static floperr_t dgndos_put_directory_track( imgtool::image &image, int track, uint8_t *buffer )
+{
+ floperr_t ferr;
+
+ for(int i=1; i<=18; i++ )
+ {
+ ferr = floppy_write_sector(imgtool_floppy(image), 0, track, i, 0, &(buffer[(i-1)*256]), 256, 0);
+ if(ferr) break;
+ }
+
+ return ferr;
+}
+
+static imgtoolerr_t dgndos_diskimage_nextenum(imgtool::directory &enumeration, imgtool_dirent &ent)
+{
+ floperr_t ferr;
+ imgtoolerr_t err;
+ size_t filesize;
+ dgndos_direnum *dgnenum;
+ dgndos_dirent dgnent;
+ int dir_ent_count;
+
+ imgtool::image &image(enumeration.image());
+
+ uint8_t entire_track20[18*256];
+
+ ferr = dgndos_get_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ dgnenum = (dgndos_direnum *) enumeration.extra_bytes();
+
+ /* Did we hit the end of file before? */
+ if (dgnenum->eof) return IMGTOOLERR_SUCCESS;
+
+ do
+ {
+ if (dgnenum->index >= MAX_DIRENTS)
+ {
+ dgnenum->eof = 1;
+ ent.eof = 1;
+ return IMGTOOLERR_SUCCESS;
+ }
+
+ err = get_dgndos_dirent(entire_track20, dgnenum->index++, dgnent);
+ if (err) return err;
+
+ if( dgndos_real_file( dgnent ) ) break;
+ }
+ while( ! (dgnent.flag_byte & DGNDOS_END_BIT) );
+
+ // now are we at the eof point?
+ if (dgnent.flag_byte & DGNDOS_END_BIT)
+ {
+ dgnenum->eof = 1;
+ ent.eof = 1;
+ }
+ else
+ {
+ err = dgndos_get_file_size(entire_track20, dgnent, filesize);
+ if (err) return err;
+
+ if (filesize == ((size_t) -1))
+ {
+ /* corrupt! */
+ ent.filesize = 0;
+ ent.corrupt = 1;
+ }
+ else
+ {
+ ent.filesize = filesize;
+ ent.corrupt = 0;
+ }
+ ent.eof = 0;
+
+ std::string fname = get_dirent_fname(dgnent);
+
+ err = dgndos_count_dirents(entire_track20, dgnent, &dir_ent_count);
+ if (err) return err;
+
+ snprintf(ent.filename, std::size(ent.filename), "%s", fname.c_str());
+ snprintf(ent.attr, std::size(ent.attr), "%c (%03d)",
+ (char) (dgnent.flag_byte & DGNDOS_PROTECT_BIT ? 'P' : '.'),
+ dir_ent_count);
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_diskimage_freespace(imgtool::partition &partition, uint64_t *size)
+{
+ floperr_t ferr;
+ imgtool::image &image(partition.image());
+ int bitmap_count(0);
+
+ uint8_t entire_track20[18*256];
+
+ ferr = dgndos_get_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ *size = 0;
+
+ dgndos_get_geometry(entire_track20, &bitmap_count, nullptr, nullptr, nullptr);
+
+ for( int i=0; i<bitmap_count; i++ )
+ {
+ if (dgndos_is_sector_avaiable(entire_track20, i))
+ {
+ *size += 256;
+ }
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_diskimage_readfile(imgtool::partition &partition, const char *fname, const char *fork, imgtool::stream &destf)
+{
+ floperr_t ferr;
+ imgtoolerr_t err;
+ dgndos_dirent ent;
+ imgtool::image &image(partition.image());
+ int directory_entry_count = 0;
+ int head, track, sector;
+ int position;
+ int extent = 0;
+ int block_size;
+ int done;
+ int lsn;
+ int count;
+ int i;
+
+ uint8_t entire_track20[18*256];
+
+ ferr = dgndos_get_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ err = lookup_dgndos_file(entire_track20, fname, ent, &position);
+ if (err) return err;
+
+ do
+ {
+ if(directory_entry_count>MAX_DIRENTS) return IMGTOOLERR_CORRUPTDIR;
+
+ lsn = big_endianize_int16( ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[extent].lsn : ent.block.header.block[extent].lsn );
+ count = ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[extent].count : ent.block.header.block[extent].count;
+
+ if( count == 0 ) break;
+
+ i = 0;
+
+ // get extents except last sector
+ while (i < count - 1)
+ {
+ err = dgndos_convert_lsn(entire_track20, lsn + i, &head, &track, &sector );
+ if(err) return err;
+
+ err = imgtool_floppy_read_sector_to_stream(image, head, track, sector, 0, 256, destf);
+ if (err) return err;
+
+ i++;
+ }
+
+ block_size = 256;
+ done = false;
+
+ if( extent < (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT) - 1 )
+ {
+ if( (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[extent+1].count : ent.block.header.block[extent+1].count) == 0 )
+ {
+ // not last extent, and yes continuation
+ if( ent.dngdos_last_or_next == 0 )
+ block_size = 256;
+ else
+ block_size = ent.dngdos_last_or_next;
+
+ done = true;
+ }
+ }
+ else if( extent == (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT) - 1)
+ {
+ if( !(ent.flag_byte & DGNDOS_CONTINUED_BIT) )
+ {
+ // is last extent, and no continuation
+ if( ent.dngdos_last_or_next == 0 )
+ block_size = 256;
+ else
+ block_size = ent.dngdos_last_or_next;
+
+ done = true;
+ }
+ }
+
+ err = dgndos_convert_lsn(entire_track20, lsn + i, &head, &track, &sector );
+ if(err) return err;
+
+ err = imgtool_floppy_read_sector_to_stream(image, head, track, sector, 0, block_size, destf);
+ if (err) return err;
+
+ extent++;
+
+ if( extent == (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT) )
+ {
+ if( ent.flag_byte & DGNDOS_CONTINUED_BIT)
+ {
+ position = ent.dngdos_last_or_next;
+ err = get_dgndos_dirent(entire_track20, ent.dngdos_last_or_next, ent );
+ if(err) return err;
+
+ extent = 0;
+ directory_entry_count++;
+ }
+ }
+ }
+ while( !done );
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_diskimage_deletefile(imgtool::partition &partition, const char *fname)
+{
+ imgtoolerr_t err;
+ floperr_t ferr;
+ imgtool::image &image(partition.image());
+ int pos;
+ struct dgndos_dirent ent;
+ int directory_entry_count = 0;
+
+ uint8_t entire_track20[18*256];
+ uint8_t entire_track16[18*256];
+ bool write_20_to_16;
+
+ ferr = dgndos_get_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ ferr = dgndos_get_directory_track( image, 16, entire_track16 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ write_20_to_16 = memcmp(entire_track20, entire_track16, 256*18 );
+
+ err = lookup_dgndos_file(entire_track20, fname, ent, &pos);
+ if (err) return err;
+
+ ent.flag_byte |= DGNDOS_DELETED_BIT;
+ ent.flag_byte &= ~DGNDOS_PROTECT_BIT;
+
+ for( int i=0; i<HEADER_EXTENTS_COUNT; i++)
+ {
+ if( ent.block.header.block[i].count != 0)
+ {
+ dgndos_fat_deallocate_span(entire_track20, big_endianize_int16(ent.block.header.block[i].lsn), ent.block.header.block[i].count);
+
+ ent.block.header.block[i].lsn = 0;
+ ent.block.header.block[i].count = 0;
+ }
+ else break;
+ }
+
+ int continue_flag = ent.flag_byte & DGNDOS_CONTINUED_BIT;
+ int continue_dirent_index = ent.dngdos_last_or_next;
+
+ ent.dngdos_last_or_next = 0;
+ err = put_dgndos_dirent(entire_track20, pos, ent);
+ if (err) return err;
+
+ while( continue_flag )
+ {
+ if( directory_entry_count > MAX_DIRENTS ) return IMGTOOLERR_CORRUPTDIR;
+
+ int dirent_index = continue_dirent_index;
+ err = get_dgndos_dirent(entire_track20, dirent_index, ent);
+ if (err) return err;
+
+ for( int i=0; i<CONT_EXTENTS_COUNT; i++)
+ {
+ if(ent.block.continuation.block[i].count !=0)
+ {
+ dgndos_fat_deallocate_span(entire_track20, big_endianize_int16(ent.block.continuation.block[i].lsn), ent.block.continuation.block[i].count);
+
+ ent.block.continuation.block[i].lsn = 0;
+ ent.block.continuation.block[i].count = 0;
+ }
+ else break;
+ }
+
+ ent.flag_byte |= DGNDOS_DELETED_BIT;
+ continue_flag = ent.flag_byte & DGNDOS_CONTINUED_BIT;
+ continue_dirent_index = ent.dngdos_last_or_next;
+
+ ent.dngdos_last_or_next = 0;
+ err = put_dgndos_dirent(entire_track20, dirent_index, ent);
+ if (err) return err;
+
+ directory_entry_count++;
+ }
+
+ ferr = dgndos_put_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ if( write_20_to_16 )
+ {
+ ferr = dgndos_put_directory_track( image, 16, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_prepare_dirent(uint8_t *track, dgndos_dirent &ent, const char *fname)
+{
+ const char *fname_end;
+ const char *fname_ext;
+ int fname_ext_len;
+
+ memset(&ent, '\0', sizeof(ent));
+
+ fname_end = strchr(fname, '.');
+ if (fname_end)
+ fname_ext = fname_end + 1;
+ else
+ fname_end = fname_ext = fname + strlen(fname);
+
+ fname_ext_len = strlen(fname_ext);
+
+ // we had better be an 8.3 filename
+ if (((fname_end - fname) > 8) || (fname_ext_len > 3))
+ return IMGTOOLERR_BADFILENAME;
+
+ memcpy(&ent.block.header.filename[0], fname, fname_end - fname);
+ memcpy(&ent.block.header.filename[8], fname_ext, fname_ext_len);
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_diskimage_writefile(imgtool::partition &partition, const char *fname, const char *fork, imgtool::stream &sourcef, util::option_resolution *writeoptions)
+{
+ floperr_t ferr;
+ imgtoolerr_t err;
+ imgtool::image &image(partition.image());
+ dgndos_dirent ent;
+ int position;
+ uint64_t written = 0;
+ int fat_block, first_lsn, sectors_avaiable, current_sector_index;
+ int last_sector_size = 0;
+ int bitmap_count;
+
+ if( sourcef.size() == 0 ) return IMGTOOLERR_BUFFERTOOSMALL;
+
+ uint8_t entire_track20[18*256];
+ uint8_t entire_track16[18*256];
+ bool write_20_to_16;
+
+ ferr = dgndos_get_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ ferr = dgndos_get_directory_track( image, 16, entire_track16 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ write_20_to_16 = memcmp(entire_track20, entire_track16, 18*256 );
+
+ err = dgndos_get_geometry(entire_track20, &bitmap_count, nullptr, nullptr, nullptr);
+ if(err) return err;
+
+ // find directory entry with same file name
+ err = lookup_dgndos_file(entire_track20, fname, ent, &position);
+
+ if( err == IMGTOOLERR_FILENOTFOUND )
+ {
+ int new_lsn;
+
+ // get new directory entry
+ err = dgndos_get_avaiable_dirent(entire_track20, ent, &position);
+ if (err) return err;
+
+ err = dgndos_prepare_dirent(entire_track20, ent, fname);
+ if(err) return err;
+
+ err = dgndos_get_avaiable_sector( entire_track20, &new_lsn );
+ if (err)
+ {
+ return err;
+ }
+
+ dgndos_fat_allocate_sector(entire_track20, new_lsn);
+
+ ent.block.header.block[0].lsn = big_endianize_int16(new_lsn);
+ ent.block.header.block[0].count = 1;
+
+ err = put_dgndos_dirent(entire_track20, position, ent);
+ if(err) return err;
+ }
+ else if(err != IMGTOOLERR_SUCCESS )
+ {
+ return err;
+ }
+
+ if( writeoptions->lookup_int(DGNDOS_OPTIONS_PROTECT))
+ {
+ ent.flag_byte |= DGNDOS_PROTECT_BIT;
+ }
+ else
+ {
+ ent.flag_byte &= ~DGNDOS_PROTECT_BIT;
+ }
+
+ fat_block = 0;
+
+ /* get next available fat entry */
+ first_lsn = big_endianize_int16(ent.block.header.block[fat_block].lsn);
+ sectors_avaiable = ent.block.header.block[fat_block].count;
+ current_sector_index = 0;
+
+ do
+ {
+ while ((current_sector_index < sectors_avaiable) && (written < sourcef.size()))
+ {
+ int head, track, sector, write_count;
+
+ err = dgndos_convert_lsn(entire_track20, first_lsn + current_sector_index, &head, &track, &sector );
+ if (err) return err;
+
+ if( sourcef.size() - written > 256 )
+ {
+ write_count = 256;
+ }
+ else if( sourcef.size() - written == 256 )
+ {
+ write_count = 256;
+ last_sector_size = 0;
+ }
+ else
+ {
+ write_count = sourcef.size() - written;
+ last_sector_size = write_count;
+ }
+
+ err = imgtool_floppy_write_sector_from_stream(image, head, track, sector, 0, write_count, sourcef);
+ if (err) return err;
+
+ current_sector_index++;
+ written += write_count;
+ }
+
+ if( written == sourcef.size()) // are we are done writing file
+ {
+ int de_count = 0;
+ int de_dont_delete = position;
+ int lsn, count;
+ int save_next_de;
+
+ save_next_de = ent.dngdos_last_or_next;
+ ent.dngdos_last_or_next = last_sector_size;
+
+ // yes, truncate this allocation block if necessary
+ if( ent.flag_byte & DGNDOS_CONTINUATION_BIT)
+ {
+ for( int i = current_sector_index; i < ent.block.continuation.block[fat_block].count; i++)
+ {
+ dgndos_fat_deallocate_sector(entire_track20, first_lsn + i);
+ }
+
+ ent.block.continuation.block[fat_block].count = current_sector_index;
+ }
+ else
+ {
+ for( int i = current_sector_index; i < ent.block.header.block[fat_block].count; i++)
+ {
+ dgndos_fat_deallocate_sector(entire_track20, first_lsn + i);
+ }
+
+ ent.block.header.block[fat_block].count = current_sector_index;
+ }
+
+ do // check remaining allocation blocks and zero them
+ {
+ fat_block++;
+
+ if( (fat_block < (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT)) )
+ {
+ lsn = big_endianize_int16( ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].lsn : ent.block.header.block[fat_block].lsn );
+ count = ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].count : ent.block.header.block[fat_block].count;
+
+ if( count > 0 )
+ {
+ dgndos_fat_deallocate_span(entire_track20, lsn, count);
+
+ (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].lsn : ent.block.header.block[fat_block].lsn) = 0;
+ (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].count : ent.block.header.block[fat_block].count) = 0;
+ }
+ }
+ else
+ {
+ uint8_t save_flag = ent.flag_byte;
+
+ ent.flag_byte &= ~DGNDOS_CONTINUED_BIT;
+
+ if( ent.flag_byte & DGNDOS_CONTINUATION_BIT )
+ {
+ if( de_dont_delete != position )
+ {
+ ent.flag_byte |= DGNDOS_DELETED_BIT;
+ }
+ }
+
+ err = put_dgndos_dirent(entire_track20, position, ent);
+ if (err) return err;
+
+ if( save_flag & DGNDOS_CONTINUED_BIT )
+ {
+ position = save_next_de;
+
+ err = get_dgndos_dirent(entire_track20, position, ent);
+ if (err) return err;
+
+ save_next_de = ent.dngdos_last_or_next;
+ fat_block = -1;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ de_count++;
+ }
+ while( de_count < MAX_DIRENTS );
+
+ if( de_count == MAX_DIRENTS ) return IMGTOOLERR_CORRUPTDIR;
+ }
+ else // more to write
+ {
+ // check if I can extend the allocation count
+ if( (current_sector_index < 254) && (first_lsn + current_sector_index < bitmap_count) && (dgndos_is_sector_avaiable( entire_track20, first_lsn + current_sector_index )) )
+ {
+ sectors_avaiable++;
+
+ (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].count : ent.block.header.block[fat_block].count) = sectors_avaiable;
+
+ dgndos_fat_allocate_sector( entire_track20, first_lsn + current_sector_index );
+ }
+ else // this allocation list is full - check next allocation list
+ {
+ fat_block++;
+
+ if( fat_block == (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? CONT_EXTENTS_COUNT : HEADER_EXTENTS_COUNT))
+ {
+ if( ent.flag_byte & DGNDOS_CONTINUED_BIT)
+ {
+ // go to next directory entry.
+ err = put_dgndos_dirent(entire_track20, position, ent);
+ if (err) return err;
+
+ position = ent.dngdos_last_or_next;
+ err = get_dgndos_dirent(entire_track20, position, ent);
+ if (err)
+ {
+ return err;
+ }
+
+ fat_block = 0;
+ }
+ else
+ {
+ // need a or another continuation directory entry
+ int save_position = position, new_lsn;
+
+ err = put_dgndos_dirent(entire_track20, position, ent);
+ if (err) return err;
+
+ err = dgndos_get_avaiable_dirent_position( entire_track20, &position );
+ if (err)
+ {
+ return err;
+ }
+
+ ent.flag_byte |= DGNDOS_CONTINUED_BIT;
+ ent.dngdos_last_or_next = position;
+ err = put_dgndos_dirent(entire_track20, save_position, ent);
+ if (err) return err;
+
+ err = get_dgndos_dirent(entire_track20, position, ent);
+ if (err)
+ {
+ return err;
+ }
+
+ memset( (void *)&ent, 0, sizeof(dgndos_dirent) );
+ ent.flag_byte |= DGNDOS_CONTINUATION_BIT;
+ fat_block = 0;
+
+ err = dgndos_get_avaiable_sector( entire_track20, &new_lsn );
+ if (err)
+ {
+ return err;
+ }
+ }
+ }
+
+ sectors_avaiable = ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].count : ent.block.header.block[fat_block].count;
+
+ // check if this block is empty
+ if( sectors_avaiable == 0)
+ {
+ int new_lsn;
+
+ err = dgndos_get_avaiable_sector( entire_track20, &new_lsn );
+ if (err) return err;
+
+ (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].lsn : ent.block.header.block[fat_block].lsn) = big_endianize_int16(new_lsn);
+ (ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].count : ent.block.header.block[fat_block].count) = 1;
+
+ dgndos_fat_allocate_sector(entire_track20, new_lsn);
+ }
+
+ first_lsn = ent.flag_byte & DGNDOS_CONTINUATION_BIT ? big_endianize_int16(ent.block.continuation.block[fat_block].lsn) : big_endianize_int16(ent.block.header.block[fat_block].lsn);
+ sectors_avaiable = ent.flag_byte & DGNDOS_CONTINUATION_BIT ? ent.block.continuation.block[fat_block].count : ent.block.header.block[fat_block].count;
+ current_sector_index = 0;
+ }
+ }
+ }
+ while( written < sourcef.size() );
+
+ ferr = dgndos_put_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ if( write_20_to_16 )
+ {
+ ferr = dgndos_put_directory_track( image, 16, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+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;
+ imgtool::image &image(partition.image());
+ struct dgndos_dirent ent;
+ int pos;
+
+ uint8_t entire_track20[18*256];
+
+ ferr = dgndos_get_directory_track( image, 20, entire_track20 );
+ if (ferr) return imgtool_floppy_error(ferr);
+
+ if (fname)
+ {
+ err = lookup_dgndos_file(entire_track20, fname, ent, &pos);
+ if (err)
+ return err;
+
+ if (strcmp(ent.block.header.filename+8,"DAT") == 0)
+ {
+ /* ASCII file */
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = filter_eoln_getinfo;
+ 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 = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = filter_dragonbas_getinfo;
+ }
+ }
+ else
+ {
+ 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 = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[2].filter = filter_dragonbas_getinfo;
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+static imgtoolerr_t dgndos_diskimage_create(imgtool::image &image, imgtool::stream::ptr &&stream, util::option_resolution *opts)
+{
+ imgtoolerr_t err;
+ uint32_t heads, tracks, sectors, first_sector_id, sector_bytes, total_sector_count;
+ uint8_t sector[512];
+ struct dgndos_dirent *ents;
+
+ heads = opts->lookup_int('H');
+ tracks = opts->lookup_int('T');
+ sectors = opts->lookup_int('S');
+ first_sector_id = opts->lookup_int('F');
+ sector_bytes = opts->lookup_int('L');
+
+ if(sector_bytes!=256) return IMGTOOLERR_UNIMPLEMENTED;
+
+ // create FAT sectors
+ memset( sector, 0, 512 );
+
+ total_sector_count = (heads * tracks * sectors);
+
+ for( int i=0; i<total_sector_count; i++ )
+ {
+ dgndos_fat_deallocate_sector(sector, i);
+ }
+
+ sector[0xfc] = tracks;
+ sector[0xfd] = heads == 1 ? (sectors) : (sectors * 2);
+ sector[0xfe] = ~sector[0xfc];
+ sector[0xff] = ~sector[0xfd];
+
+ // allocate sectors
+ for( int i=0; i<18; i++ )
+ {
+ dgndos_fat_allocate_sector(sector, (20 * 18 * heads) + i);
+ dgndos_fat_allocate_sector(sector, (16 * 18 * heads) + i);
+ }
+
+ // write fat sectors
+ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(image), 0, 20, first_sector_id, 0, &sector[0], sector_bytes, 0);
+ if (err) return err;
+ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(image), 0, 20, first_sector_id+1, 0, &sector[256], sector_bytes, 0);
+ if (err) return err;
+
+ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(image), 0, 16, first_sector_id, 0, &sector[0], sector_bytes, 0);
+ if (err) return err;
+ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(image), 0, 16, first_sector_id+1, 0, &sector[256], sector_bytes, 0);
+ if (err) return err;
+
+ // create empty directory entries
+ memset( sector, 0, 512 );
+ ents = (struct dgndos_dirent *)sector;
+
+ for( int i=0; i<10; i++ )
+ {
+ ents[i].flag_byte = 0x89;
+ }
+
+ // write directory entires to disk
+ for( int i=3; i<19; i++)
+ {
+ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(image), 0, 20, i, 0, &sector[0], sector_bytes, 0);
+ if (err) return err;
+ err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(image), 0, 16, i, 0, &sector[0], sector_bytes, 0);
+ if (err) return err;
+ }
+
+ return IMGTOOLERR_SUCCESS;
+}
+
+/*********************************************************************
+ Imgtool module declaration
+*********************************************************************/
+
+OPTION_GUIDE_START( dragon_dgndos_writefile_optionguide )
+ OPTION_ENUM_START( DGNDOS_OPTIONS_PROTECT, "prot", "Protect file" )
+ OPTION_ENUM( 0, "no", "No" )
+ OPTION_ENUM( 1, "yes", "Yes" )
+ OPTION_ENUM_END
+OPTION_GUIDE_END
+
+void dgndos_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ 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 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;
+ case IMGTOOLINFO_STR_EOLN: strcpy(info->s = imgtool_temp_str(), "\r"); break;
+ case IMGTOOLINFO_STR_WRITEFILE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), "P[0]-1"); 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_FLOPPY_CREATE: info->create = dgndos_diskimage_create; break;
+ case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = dgndos_diskimage_nextenum; break;
+ case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = dgndos_diskimage_freespace; break;
+ case IMGTOOLINFO_PTR_READ_FILE: info->read_file = dgndos_diskimage_readfile; break;
+ case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = dgndos_diskimage_writefile; break;
+ case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = dgndos_diskimage_deletefile; break;
+ case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = dgndos_diskimage_suggesttransfer; break;
+ case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE: info->writefile_optguide = &dragon_dgndos_writefile_optionguide; break;
+ case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_coco; break;
+ }
+}
diff --git a/src/tools/imgtool/modules/fat.cpp b/src/tools/imgtool/modules/fat.cpp
index 029050d1e9c..d6611932c0d 100644
--- a/src/tools/imgtool/modules/fat.cpp
+++ b/src/tools/imgtool/modules/fat.cpp
@@ -134,13 +134,17 @@
****************************************************************************/
-#include <time.h>
-#include <ctype.h>
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "unicode.h"
#include "fat.h"
+#include "corestr.h"
+#include "multibyte.h"
+#include "unicode.h"
+
+#include <algorithm>
+#include <cctype>
+#include <cstdio>
+#include <ctime>
+
#define FAT_DIRENT_SIZE 32
#define FAT_SECLEN 512
@@ -176,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;
@@ -364,14 +380,12 @@ static imgtoolerr_t fat_write_sector(imgtool::partition &partition, uint32_t sec
}
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t fat_clear_sector(imgtool::partition &partition, uint32_t sector_index, uint8_t data)
+[[maybe_unused]] static imgtoolerr_t fat_clear_sector(imgtool::partition &partition, uint32_t sector_index, uint8_t data)
{
char buf[FAT_SECLEN];
memset(buf, data, sizeof(buf));
return fat_write_sector(partition, sector_index, 0, buf, sizeof(buf));
}
-#endif
static imgtoolerr_t fat_partition_open(imgtool::partition &partition, uint64_t first_block, uint64_t block_count)
@@ -410,19 +424,19 @@ static imgtoolerr_t fat_partition_open(imgtool::partition &partition, uint64_t f
}
info->fat_bits = fat_bits;
- sector_size = pick_integer_le(header, 11, 2);
- info->sectors_per_cluster = pick_integer_le(header, 13, 1);
- info->reserved_sectors = pick_integer_le(header, 14, 2);
- info->fat_count = pick_integer_le(header, 16, 1);
- info->root_entries = pick_integer_le(header, 17, 2);
- total_sectors_l = pick_integer_le(header, 19, 2);
- info->sectors_per_fat = pick_integer_le(header, 22, 2);
- total_sectors_h = pick_integer_le(header, 32, 4);
+ sector_size = get_u16le(&header[11]);
+ info->sectors_per_cluster = header[13];
+ info->reserved_sectors = get_u16le(&header[14]);
+ info->fat_count = header[16];
+ info->root_entries = get_u16le(&header[17]);
+ total_sectors_l = get_u16le(&header[19]);
+ info->sectors_per_fat = get_u16le(&header[22]);
+ total_sectors_h = get_u32le(&header[32]);
if (info->sectors_per_cluster == 0)
return IMGTOOLERR_CORRUPTIMAGE;
- info->total_sectors = total_sectors_l + (((uint64_t) total_sectors_h) << 16);
+ info->total_sectors = total_sectors_l + (uint64_t(total_sectors_h) << 16);
available_sectors = info->total_sectors - info->reserved_sectors
- (info->sectors_per_fat * info->fat_count)
- (info->root_entries * FAT_DIRENT_SIZE + FAT_SECLEN - 1) / FAT_SECLEN;
@@ -520,24 +534,24 @@ static imgtoolerr_t fat_partition_create(imgtool::image &image, uint64_t first_b
/* prepare the header */
memset(header, 0, sizeof(header));
memcpy(&header[3], "IMGTOOL ", 8);
- place_integer_le(header, 11, 2, FAT_SECLEN);
- place_integer_le(header, 13, 1, sectors_per_cluster);
- place_integer_le(header, 14, 1, reserved_sectors);
- place_integer_le(header, 16, 1, fat_count);
- place_integer_le(header, 17, 2, root_dir_count);
- place_integer_le(header, 19, 2, (uint16_t) (block_count >> 0));
- place_integer_le(header, 21, 1, media_descriptor);
- place_integer_le(header, 22, 2, sectors_per_fat);
- place_integer_le(header, 24, 2, sectors_per_track);
- place_integer_le(header, 26, 2, heads);
- place_integer_le(header, 28, 4, hidden_sectors);
- place_integer_le(header, 32, 4, (uint32_t) (block_count >> 16));
- place_integer_le(header, 36, 1, 0xFF);
- place_integer_le(header, 38, 1, 0x28);
- place_integer_le(header, 39, 1, std::rand());
- place_integer_le(header, 40, 1, std::rand());
- place_integer_le(header, 41, 1, std::rand());
- place_integer_le(header, 42, 1, std::rand());
+ put_u16le(&header[11], FAT_SECLEN);
+ header[13] = sectors_per_cluster;
+ header[14] = reserved_sectors;
+ header[16] = fat_count;
+ put_u16le(&header[17], root_dir_count);
+ put_u16le(&header[19], uint16_t(block_count >> 0));
+ header[21] = media_descriptor;
+ put_u16le(&header[22], sectors_per_fat);
+ put_u16le(&header[24], sectors_per_track);
+ put_u16le(&header[26], heads);
+ put_u32le(&header[28], hidden_sectors);
+ put_u32le(&header[32], uint32_t(block_count >> 16));
+ header[36] = 0xFF;
+ header[38] = 0x28;
+ header[39] = std::rand();
+ header[40] = std::rand();
+ header[41] = std::rand();
+ header[42] = std::rand();
memcpy(&header[43], " ", 11);
memcpy(&header[54], fat_bits_string, 8);
@@ -553,14 +567,14 @@ static imgtoolerr_t fat_partition_create(imgtool::image &image, uint64_t first_b
if (boot_sector_offset <= 129)
{
header[0] = 0xEB; /* JMP rel8 */
- header[1] = (uint8_t) (boot_sector_offset - 2); /* (offset) */
+ header[1] = uint8_t(boot_sector_offset - 2); /* (offset) */
header[2] = 0x90; /* NOP */
}
else
{
header[0] = 0xE9; /* JMP rel16 */
- header[1] = (uint8_t) ((boot_sector_offset - 2) >> 0); /* (offset) */
- header[2] = (uint8_t) ((boot_sector_offset - 2) >> 8); /* (offset) */
+ header[1] = uint8_t((boot_sector_offset - 2) >> 0); /* (offset) */
+ header[2] = uint8_t((boot_sector_offset - 2) >> 8); /* (offset) */
}
err = image.write_block(first_block, header);
@@ -578,9 +592,9 @@ static imgtoolerr_t fat_partition_create(imgtool::image &image, uint64_t first_b
// FIXME: this causes a corrupt PC floppy image since it doubles the FAT partition header - works without it though
#if 0
/* set first two FAT entries */
- first_fat_entries = ((uint64_t) media_descriptor) | 0xFFFFFF00;
- first_fat_entries &= (((uint64_t) 1) << fat_bits) - 1;
- first_fat_entries |= ((((uint64_t) 1) << fat_bits) - 1) << fat_bits;
+ first_fat_entries = uint64_t(media_descriptor) | 0xFFFFFF00;
+ first_fat_entries &= (uint64_t(1) << fat_bits) - 1;
+ first_fat_entries |= ((uint64_t(1) << fat_bits) - 1) << fat_bits;
first_fat_entries = little_endianize_int64(first_fat_entries);
for (i = 0; i < fat_count; i++)
@@ -706,8 +720,8 @@ static uint32_t fat_get_fat_entry(imgtool::partition &partition, const uint8_t *
entry &= bit_mask;
if (i == 0)
- last_entry = (uint32_t) entry;
- else if (last_entry != (uint32_t) entry)
+ last_entry = uint32_t(entry);
+ else if (last_entry != uint32_t(entry))
return 1; /* if the FATs disagree; mark this as reserved */
}
@@ -739,8 +753,8 @@ static void fat_set_fat_entry(imgtool::partition &partition, uint8_t *fat_table,
* disk_info->sectors_per_fat) + (bit_index / 8), sizeof(entry));
entry = little_endianize_int64(entry);
- entry &= (~((uint64_t) 0xFFFFFFFF >> (32 - disk_info->fat_bits)) << (bit_index % 8)) | ((1 << (bit_index % 8)) - 1);
- entry |= ((uint64_t) value) << (bit_index % 8);
+ entry &= (~(uint64_t(0xFFFFFFFF) >> (32 - disk_info->fat_bits)) << (bit_index % 8)) | ((1 << (bit_index % 8)) - 1);
+ entry |= uint64_t(value) << (bit_index % 8);
entry = little_endianize_int64(entry);
memcpy(fat_table + (i * FAT_SECLEN
@@ -1080,8 +1094,8 @@ static imgtoolerr_t fat_set_file_size(imgtool::partition &partition, fat_file *f
}
/* record the new file size */
- place_integer_le(dirent, 26, 2, file->first_cluster);
- place_integer_le(dirent, 28, 4, new_size);
+ put_u16le(&dirent[26], file->first_cluster);
+ put_u32le(&dirent[28], new_size);
/* delete the file, if appropriate */
if (delete_file)
@@ -1228,7 +1242,7 @@ static void fat_canonicalize_sfn(char *sfn, const uint8_t *sfn_bytes)
memcpy(sfn, sfn_bytes, 8);
rtrim(sfn);
if (sfn[0] == 0x05)
- sfn[0] = (char) 0xE5;
+ sfn[0] = char(0xE5);
if ((sfn_bytes[8] != ' ') || (sfn_bytes[9] != ' ') || (sfn_bytes[10] != ' '))
{
strcat(sfn, ".");
@@ -1272,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;
@@ -1289,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
@@ -1326,11 +1341,11 @@ static imgtoolerr_t fat_read_dirent(imgtool::partition &partition, fat_file *fil
lfn_checksum = entry[13];
}
lfn_lastentry = entry[0] & 0x3F;
- prepend_lfn_bytes(lfn_buf, ARRAY_LENGTH(lfn_buf),
+ prepend_lfn_bytes(lfn_buf, std::size(lfn_buf),
&lfn_len, entry, 28, 2);
- prepend_lfn_bytes(lfn_buf, ARRAY_LENGTH(lfn_buf),
+ prepend_lfn_bytes(lfn_buf, std::size(lfn_buf),
&lfn_len, entry, 14, 6);
- prepend_lfn_bytes(lfn_buf, ARRAY_LENGTH(lfn_buf),
+ prepend_lfn_bytes(lfn_buf, std::size(lfn_buf),
&lfn_len, entry, 1, 5);
}
else if (freeent && (freeent->position == ~0))
@@ -1350,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')
@@ -1368,25 +1383,25 @@ 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], ARRAY_LENGTH(lfn_buf) - i);
- j += utf8_from_uchar(&ent.long_filename[j], ARRAY_LENGTH(ent.long_filename) - j, ch);
+ 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);
}
}
/* other attributes */
- ent.filesize = pick_integer_le(entry, 28, 4);
+ ent.filesize = get_u32le(&entry[28]);
ent.directory = (entry[11] & 0x10) ? 1 : 0;
- ent.first_cluster = pick_integer_le(entry, 26, 2);
+ ent.first_cluster = get_u16le(&entry[26]);
ent.dirent_sector_index = entry_sector_index;
ent.dirent_sector_offset = entry_sector_offset;
- ent.creation_time = fat_crack_time(pick_integer_le(entry, 14, 4));
- ent.lastmodified_time = fat_crack_time(pick_integer_le(entry, 22, 4));
+ ent.creation_time = fat_crack_time(get_u32le(&entry[14]));
+ ent.lastmodified_time = fat_crack_time(get_u32le(&entry[22]));
return IMGTOOLERR_SUCCESS;
}
@@ -1440,9 +1455,9 @@ static imgtoolerr_t fat_construct_dirent(const char *filename, creation_policy_t
/* set up file dates in the new dirent */
now = fat_setup_time(time(NULL));
- place_integer_le(created_entry, 14, 4, now);
- place_integer_le(created_entry, 18, 2, now);
- place_integer_le(created_entry, 22, 4, now);
+ put_u32le(&created_entry[14], now);
+ put_u16le(&created_entry[18], now);
+ put_u32le(&created_entry[22], now);
while(*filename)
{
@@ -1451,13 +1466,13 @@ static imgtoolerr_t fat_construct_dirent(const char *filename, creation_policy_t
/* append to short filename, if possible */
if ((ch < 32) || (ch > 128))
short_char = '\0';
- else if (isalnum((char) ch))
- short_char = toupper((char) ch);
- else if (strchr(".!#$%^()-@^_`{}~", (char) ch))
- short_char = (char) ch;
+ else if (isalnum(char(ch)))
+ short_char = toupper(char(ch));
+ else if (strchr(".!#$%^()-@^_`{}~", char(ch)))
+ short_char = char(ch);
else
short_char = '\0'; /* illegal SFN char */
- canonical_short_char = fat_canonicalize_sfn_char((char) ch);
+ canonical_short_char = fat_canonicalize_sfn_char(char(ch));
if (!short_char || (short_char != canonical_short_char))
{
if (toupper(short_char) == toupper(canonical_short_char))
@@ -1605,7 +1620,7 @@ static void fat_bump_dirent(imgtool::partition &partition, uint8_t *entry, size_
sfn_entry = &entry[entry_len - FAT_DIRENT_SIZE];
digit_place = 1;
- for (pos = 7; (pos >= 0) && isdigit((char) sfn_entry[pos]); pos--)
+ for (pos = 7; (pos >= 0) && isdigit(char(sfn_entry[pos])); pos--)
{
val += (sfn_entry[pos] - '0') * digit_place;
digit_place *= 10;
@@ -1834,7 +1849,7 @@ static imgtoolerr_t fat_partition_nextenum(imgtool::directory &enumeration, imgt
return err;
/* copy stuff from the FAT dirent to the Imgtool dirent */
- snprintf(ent.filename, ARRAY_LENGTH(ent.filename), "%s", fatent.long_filename[0]
+ snprintf(ent.filename, std::size(ent.filename), "%s", fatent.long_filename[0]
? fatent.long_filename : fatent.short_filename);
ent.filesize = fatent.filesize;
ent.directory = fatent.directory;
@@ -1945,7 +1960,7 @@ static imgtoolerr_t fat_partition_writefile(imgtool::partition &partition, const
if (file.directory)
return IMGTOOLERR_FILENOTFOUND;
- bytes_left = (uint32_t) sourcef.size();
+ bytes_left = uint32_t(sourcef.size());
err = fat_set_file_size(partition, &file, bytes_left);
if (err)
@@ -2051,11 +2066,11 @@ static imgtoolerr_t fat_partition_createdir(imgtool::partition &partition, const
/* set up the two directory entries in all directories */
memset(initial_data, 0, sizeof(initial_data));
memcpy(&initial_data[0], ". ", 11);
- place_integer_le(initial_data, 11, 1, 0x10);
- place_integer_le(initial_data, 26, 2, file.first_cluster);
+ initial_data[11] = 0x10;
+ put_u16le(&initial_data[26], file.first_cluster);
memcpy(&initial_data[32], ". ", 11);
- place_integer_le(initial_data, 43, 1, 0x10);
- place_integer_le(initial_data, 58, 2, file.parent_first_cluster);
+ initial_data[43] = 0x10;
+ put_u16le(&initial_data[58], file.parent_first_cluster);
err = fat_write_file(partition, &file, initial_data, sizeof(initial_data), NULL);
if (err)
diff --git a/src/tools/imgtool/modules/fat.h b/src/tools/imgtool/modules/fat.h
index 77c56f5f9f1..8e7c60d89af 100644
--- a/src/tools/imgtool/modules/fat.h
+++ b/src/tools/imgtool/modules/fat.h
@@ -1,3 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Raphael Nabet
+
+#include "imgtool.h"
+
void fat_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info);
diff --git a/src/tools/imgtool/modules/hp48.cpp b/src/tools/imgtool/modules/hp48.cpp
index 4d237f3c470..4a008adaeb5 100644
--- a/src/tools/imgtool/modules/hp48.cpp
+++ b/src/tools/imgtool/modules/hp48.cpp
@@ -86,6 +86,8 @@
#include "imgtool.h"
+#include "opresolv.h"
+
/*****************************************************************************
diff --git a/src/tools/imgtool/modules/hp85_tape.cpp b/src/tools/imgtool/modules/hp85_tape.cpp
index dada87e290a..319f1e3f10c 100644
--- a/src/tools/imgtool/modules/hp85_tape.cpp
+++ b/src/tools/imgtool/modules/hp85_tape.cpp
@@ -7,12 +7,19 @@
HP-85 tape format
*********************************************************************/
-
#include "imgtool.h"
-#include "formats/imageutl.h"
+
#include "formats/hti_tape.h"
+
+#include "ioprocs.h"
+#include "multibyte.h"
+#include "opresolv.h"
+#include "strformat.h"
+
+#include <cstdio>
#include <iostream>
+
// Constants
static constexpr unsigned CHARS_PER_FNAME = 6; // Characters in a filename
static constexpr unsigned CHARS_PER_EXT = 4; // Characters in (simulated) file extension
@@ -109,9 +116,9 @@ private:
// Content
std::vector<sif_file_ptr_t> content;
// First file on track 1
- file_no_t file_track_1;
+ file_no_t file_track_1{};
// No. of first record on track 1
- uint16_t record_track_1;
+ uint16_t record_track_1 = 0;
bool dec_rec_header(const tape_word_t *hdr , file_no_t& file_no , uint16_t& rec_no , bool& has_body , unsigned& body_len);
bool load_whole_tape();
@@ -145,7 +152,7 @@ typedef struct {
tape_image_85::tape_image_85(void)
: dirty(false)
{
- image.set_bits_per_word(16);
+ image.set_image_format(hti_format_t::HTI_DELTA_MOD_16_BITS);
}
void tape_image_85::format_img(void)
@@ -158,48 +165,13 @@ void tape_image_85::format_img(void)
finalize_allocation();
}
-namespace {
- int my_seekproc(void *file, int64_t offset, int whence)
- {
- reinterpret_cast<imgtool::stream *>(file)->seek(offset, whence);
- return 0;
- }
-
- size_t my_readproc(void *file, void *buffer, size_t length)
- {
- return reinterpret_cast<imgtool::stream *>(file)->read(buffer, length);
- }
-
- size_t my_writeproc(void *file, const void *buffer, size_t length)
- {
- reinterpret_cast<imgtool::stream *>(file)->write(buffer, length);
- return length;
- }
-
- uint64_t my_filesizeproc(void *file)
- {
- return reinterpret_cast<imgtool::stream *>(file)->size();
- }
-
- const struct io_procs my_stream_procs = {
- nullptr,
- my_seekproc,
- my_readproc,
- my_writeproc,
- my_filesizeproc
- };
-}
-
imgtoolerr_t tape_image_85::load_from_file(imgtool::stream *stream)
{
- io_generic io;
- io.file = (void *)stream;
- io.procs = &my_stream_procs;
- io.filler = 0;
-
- if (!image.load_tape(&io)) {
+ auto io = imgtool::stream_read(*stream, 0);
+ if (!io || !image.load_tape(*io)) {
return IMGTOOLERR_READERROR;
}
+ io.reset();
// Prevent track boundary crossing when reading directory
file_track_1 = 0;
@@ -422,12 +394,7 @@ imgtoolerr_t tape_image_85::save_to_file(imgtool::stream *stream)
file_0.clear();
save_sif_file(track , pos , dir.size() + 1 , file_0);
- io_generic io;
- io.file = (void *)stream;
- io.procs = &my_stream_procs;
- io.filler = 0;
-
- image.save_tape(&io);
+ image.save_tape(*imgtool::stream_read_write(*stream, 0));
return IMGTOOLERR_SUCCESS;
}
@@ -667,7 +634,7 @@ bool tape_image_85::decode_dir(const sif_file_t& file_0)
// Get FL1TK1
file_track_1 = file_0[ 0xfd ];
- record_track_1 = pick_integer_le(file_0.data() , 0xfe , 2);
+ record_track_1 = get_u16le(&file_0[ 0xfe ]);
file_no_t file_no = 1;
@@ -698,10 +665,10 @@ bool tape_image_85::decode_dir(const sif_file_t& file_0)
new_entry.file_no = file_no++;
// Physical records
- new_entry.n_recs = pick_integer_le(p , 8 , 2);
+ new_entry.n_recs = get_u16le(&p[ 8 ]);
// Bytes per logical record
- new_entry.record_len = pick_integer_le(p , 10 , 2);
+ new_entry.record_len = get_u16le(&p[ 10 ]);
if (new_entry.record_len < 4 || new_entry.record_len >= 32768) {
return false;
}
@@ -722,8 +689,8 @@ void tape_image_85::encode_dir(sif_file_t& file_0) const
file_0[ 0x1fc ] = 1;
// Set FL1TK1
file_0[ 0xfd ] = file_0[ 0x1fd ] = file_track_1;
- place_integer_le(file_0.data() , 0xfe , 2 , record_track_1);
- place_integer_le(file_0.data() , 0x1fe , 2 , record_track_1);
+ put_u16le(&file_0[ 0xfe ] , record_track_1);
+ put_u16le(&file_0[ 0x1fe ] , record_track_1);
unsigned i = 0;
file_no_t file_no = 1;
@@ -736,8 +703,8 @@ void tape_image_85::encode_dir(sif_file_t& file_0) const
memcpy(&p_entry[ 0 ] , &entry->filename[ 0 ] , CHARS_PER_FNAME);
p_entry[ 6 ] = file_no;
p_entry[ 7 ] = entry->filetype;
- place_integer_le(p_entry , 8 , 2 , entry->n_recs);
- place_integer_le(p_entry , 10 , 2 , entry->record_len);
+ put_u16le(&p_entry[ 8 ] , entry->n_recs);
+ put_u16le(&p_entry[ 10 ] , entry->record_len);
}
if (file_no <= MAX_FILE_NO) {
@@ -866,7 +833,7 @@ namespace {
tape_image_85& get_tape_image(tape_state_t& ts)
{
if (ts.img == nullptr) {
- ts.img = global_alloc(tape_image_85);
+ ts.img = new tape_image_85;
}
return *(ts.img);
@@ -916,7 +883,7 @@ namespace {
delete state.stream;
// Free tape_image
- global_free(&tape_image);
+ delete &tape_image;
}
imgtoolerr_t hp85_tape_begin_enum (imgtool::directory &enumeration, const char *path)
diff --git a/src/tools/imgtool/modules/hp9845_tape.cpp b/src/tools/imgtool/modules/hp9845_tape.cpp
index d3416deaefd..26cb2f4eb1c 100644
--- a/src/tools/imgtool/modules/hp9845_tape.cpp
+++ b/src/tools/imgtool/modules/hp9845_tape.cpp
@@ -108,12 +108,20 @@
these special characters.
*********************************************************************/
-#include <bitset>
-
#include "imgtool.h"
-#include "formats/imageutl.h"
+#include "filter.h"
+
#include "formats/hti_tape.h"
+#include "corefile.h"
+#include "ioprocs.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <bitset>
+#include <cstdio>
+
+
// Constants
#define SECTOR_LEN 256 // Bytes in a sector
#define WORDS_PER_SECTOR (SECTOR_LEN / 2) // 16-bit words in a sector payload
@@ -291,49 +299,16 @@ void tape_image_t::format_img(void)
dirty = true;
}
-static int my_seekproc(void *file, int64_t offset, int whence)
-{
- reinterpret_cast<imgtool::stream *>(file)->seek(offset, whence);
- return 0;
-}
-
-static size_t my_readproc(void *file, void *buffer, size_t length)
-{
- return reinterpret_cast<imgtool::stream *>(file)->read(buffer, length);
-}
-
-static size_t my_writeproc(void *file, const void *buffer, size_t length)
-{
- reinterpret_cast<imgtool::stream *>(file)->write(buffer, length);
- return length;
-}
-
-static uint64_t my_filesizeproc(void *file)
-{
- return reinterpret_cast<imgtool::stream *>(file)->size();
-}
-
-static const struct io_procs my_stream_procs = {
- nullptr,
- my_seekproc,
- my_readproc,
- my_writeproc,
- my_filesizeproc
-};
-
imgtoolerr_t tape_image_t::load_from_file(imgtool::stream *stream)
{
hti_format_t inp_image;
- inp_image.set_bits_per_word(16);
+ inp_image.set_image_format(hti_format_t::HTI_DELTA_MOD_16_BITS);
- io_generic io;
- io.file = (void *)stream;
- io.procs = &my_stream_procs;
- io.filler = 0;
-
- if (!inp_image.load_tape(&io)) {
+ auto io = imgtool::stream_read(*stream, 0);
+ if (!io || !inp_image.load_tape(*io)) {
return IMGTOOLERR_READERROR;
}
+ io.reset();
unsigned exp_sector = 0;
unsigned last_sector_on_track = SECTORS_PER_TRACK;
@@ -523,12 +498,7 @@ imgtoolerr_t tape_image_t::save_to_file(imgtool::stream *stream)
}
}
- io_generic io;
- io.file = (void *)stream;
- io.procs = &my_stream_procs;
- io.filler = 0;
-
- out_image.save_tape(&io);
+ out_image.save_tape(*imgtool::stream_read_write(*stream, 0));
return IMGTOOLERR_SUCCESS;
}
@@ -985,7 +955,7 @@ static tape_state_t& get_tape_state(imgtool::image &img)
static tape_image_t& get_tape_image(tape_state_t& ts)
{
if (ts.img == nullptr) {
- ts.img = global_alloc(tape_image_t);
+ ts.img = new tape_image_t;
}
return *(ts.img);
@@ -1034,7 +1004,7 @@ static void hp9845_tape_close(imgtool::image &image)
delete state.stream;
// Free tape_image
- global_free(&tape_image);
+ delete &tape_image;
}
static imgtoolerr_t hp9845_tape_begin_enum (imgtool::directory &enumeration, const char *path)
@@ -1374,7 +1344,7 @@ static imgtoolerr_t hp9845data_read_file(imgtool::partition &partition, const ch
if (!get_record_part(*inp_data , tmp , 2)) {
return IMGTOOLERR_READERROR;
}
- rec_type = (uint16_t)pick_integer_be(tmp , 0 , 2);
+ rec_type = get_u16be(&tmp[ 0 ]);
switch (rec_type) {
case REC_TYPE_EOR:
// End of record: just skip it
@@ -1397,7 +1367,7 @@ static imgtoolerr_t hp9845data_read_file(imgtool::partition &partition, const ch
if (!get_record_part(*inp_data , tmp , 2)) {
return IMGTOOLERR_READERROR;
}
- tmp_len = (unsigned)pick_integer_be(tmp , 0 , 2);
+ tmp_len = get_u16be(&tmp [ 0 ]);
if (rec_type == REC_TYPE_FULLSTR || rec_type == REC_TYPE_1STSTR) {
accum_len = tmp_len;
@@ -1445,7 +1415,7 @@ static bool split_string_n_dump(const char *s , imgtool::stream &dest)
unsigned free_len = len_to_eor(dest);
if (free_len <= 4) {
// Not enough free space at end of current record: fill with EORs
- place_integer_be(tmp , 0 , 2 , REC_TYPE_EOR);
+ put_u16be(&tmp[ 0 ] , REC_TYPE_EOR);
while (free_len) {
if (dest.write(tmp , 2) != 2) {
return false;
@@ -1458,8 +1428,8 @@ static bool split_string_n_dump(const char *s , imgtool::stream &dest)
// Free space to EOR enough for what's left of string
break;
}
- place_integer_be(tmp , 0 , 2 , rec_type);
- place_integer_be(tmp , 2 , 2 , s_len);
+ put_u16be(&tmp[ 0 ] , rec_type);
+ put_u16be(&tmp[ 2 ] , s_len);
if (dest.write(tmp , 4) != 4 ||
dest.write(s, s_part_len) != s_part_len) {
return false;
@@ -1471,8 +1441,8 @@ static bool split_string_n_dump(const char *s , imgtool::stream &dest)
}
}
- place_integer_be(tmp , 0 , 2 , at_least_one ? REC_TYPE_ENDSTR : REC_TYPE_FULLSTR);
- place_integer_be(tmp , 2 , 2 , s_len);
+ put_u16be(&tmp[ 0 ] , at_least_one ? REC_TYPE_ENDSTR : REC_TYPE_FULLSTR);
+ put_u16be(&tmp[ 2 ] , s_len);
if (dest.write(tmp , 4) != 4 ||
dest.write(s , s_len) != s_len) {
return false;
@@ -1528,7 +1498,7 @@ static imgtoolerr_t hp9845data_write_file(imgtool::partition &partition, const c
// Fill free space of last record with EOFs
unsigned free_len = len_to_eor(*out_data);
uint8_t tmp[ 2 ];
- place_integer_be(tmp , 0 , 2 , REC_TYPE_EOF);
+ put_u16be(&tmp[ 0 ] , REC_TYPE_EOF);
while (free_len) {
if (out_data->write(tmp , 2 ) != 2) {
@@ -1544,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/mac.cpp b/src/tools/imgtool/modules/mac.cpp
deleted file mode 100644
index 90c68323f76..00000000000
--- a/src/tools/imgtool/modules/mac.cpp
+++ /dev/null
@@ -1,6439 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- mac.c
-
- Handlers for Classic MacOS images (MFS and HFS formats).
-
- Raphael Nabet, 2003
-
- TODO:
- * add support for HFS write
-
-*****************************************************************************
-
- terminology:
- disk block: 512-byte logical block. With sectors of 512 bytes, one logical
- block is equivalent to one sector; when the sector size is not 512
- bytes, sectors are split or grouped to make 512-byte disk blocks.
- allocation block: The File Manager always allocates logical disk blocks to
- a file in groups called allocation blocks; an allocation block is
- simply a group of consecutive logical blocks. The size of a volume's
- allocation blocks depends on the capacity of the volume; there can be
- at most 4094 (MFS) or 65535 (HFS) allocation blocks on a volume.
- MFS (Macintosh File System): File system used by the early Macintosh. This
- File system does not support folders (you may create folders on a MFS
- disk, but such folders are not implemented on File System level but in
- the Desktop file, and they are just a hint of how programs should list
- files, i.e. you can't have two files with the same name on a volume
- even if they are in two different folders), and it is not adequate for
- large volumes.
- HFS (Hierarchical File System): File system introduced with the HD20
- harddisk, the Macintosh Plus ROMs, and system 3.2 (IIRC). Contrary to
- MFS, it supports hierarchical folders. Also, it is suitable for larger
- volumes.
- HFS+ (HFS Plus): New file system introduced with MacOS 8.1. It has a lot
- in common with HFS, but it supports more allocation blocks (up to 4
- billions IIRC), and many extra features, including longer file names
- (up to 255 UTF-16 Unicode chars).
- tag data: with the GCR encoding, each disk block is associated with a 12
- (3.5" floppies) or 20 (HD20) byte tag record. This tag record contains
- information on the block allocation status (whether it is allocated
- in a file or free, which file is it belongs to, what offset the block
- has in the file). This enables to recover all files whose data blocks
- are still on the disk surface even if the disk catalog has been trashed
- completely (though most file properties, like the name, type and
- logical EOF, are not saved in the tag record and cannot be recovered).
-
- Organization of an MFS volume:
-
- Logical Contents Allocation block
- block
-
- 0 - 1: System startup information
- 2 - m: Master directory block (MDB)
- + allocation block link pointers
- m+1 - n: Directory file
- n+1 - p-2: Other files and free space 0 - ((p-2)-(n+1))/k
- p-1: Alternate MDB
- p: Not used
- usually, k = 2, m = 3, n = 16, p = 799 (SSDD 3.5" floppy)
- with DSDD 3.5" floppy, I assume that p = 1599, but I don't know the other
- values
-
-
- Master Directory Block:
-
- Offset Length Description
- ------ ------ -----------
- 0 2 Volume Signature
- 2 4 Creation Date
- 6 4 Last Modification Date
- 10 2 Volume Attributes
- 12 2 Number of Files In Root Directory
- 14 2 First Block of Volume Bitmap
- ...
-
- Links:
- http://developer.apple.com/documentation/mac/Files/Files-99.html
- http://developer.apple.com/documentation/mac/Files/Files-100.html
- http://developer.apple.com/documentation/mac/Files/Files-101.html
- http://developer.apple.com/documentation/mac/Files/Files-102.html
- http://developer.apple.com/documentation/mac/Files/Files-103.html
- http://developer.apple.com/documentation/mac/Files/Files-104.html
- http://developer.apple.com/documentation/mac/Files/Files-105.html
- http://developer.apple.com/documentation/mac/Files/Files-106.html
- http://developer.apple.com/documentation/mac/Devices/Devices-121.html#MARKER-2-169
- http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
-
-*****************************************************************************/
-
-#include <ctype.h>
-#include <string.h>
-#include <time.h>
-#include <limits.h>
-#include <stddef.h>
-
-#include "formats/imageutl.h"
-#include "imgtool.h"
-#include "macutil.h"
-#include "iflopimg.h"
-#include "formats/ap_dsk35.h"
-
-/* if 1, check consistency of B-Tree (most of the checks will eventually be
- suppressed when the image is opened as read-only and only enabled when
- the image is opened as read/write) */
-#define BTREE_CHECKS 1
-/* if 1, check consistency of tag data when we are at risk of corrupting the
- disk (file write and allocation) */
-#define TAG_CHECKS 1
-/* if 1, check consistency of tag data when reading files (not recommended
- IMHO) */
-#define TAG_EXTRA_CHECKS 0
-
-#if 0
-#pragma mark MISCELLANEOUS UTILITIES
-#endif
-
-struct UINT16BE
-{
- uint8_t bytes[2];
-};
-
-struct UINT24BE
-{
- uint8_t bytes[3];
-};
-
-struct UINT32BE
-{
- uint8_t bytes[4];
-};
-
-static inline uint16_t get_UINT16BE(UINT16BE word)
-{
- return (word.bytes[0] << 8) | word.bytes[1];
-}
-
-static inline void set_UINT16BE(UINT16BE *word, uint16_t data)
-{
- word->bytes[0] = (data >> 8) & 0xff;
- word->bytes[1] = data & 0xff;
-}
-
-#if 0
-static inline uint32_t get_UINT24BE(UINT24BE word)
-{
- return (word.bytes[0] << 16) | (word.bytes[1] << 8) | word.bytes[2];
-}
-
-static inline void set_UINT24BE(UINT24BE *word, uint32_t data)
-{
- word->bytes[0] = (data >> 16) & 0xff;
- word->bytes[1] = (data >> 8) & 0xff;
- word->bytes[2] = data & 0xff;
-}
-#endif
-
-static inline uint32_t get_UINT32BE(UINT32BE word)
-{
- return (word.bytes[0] << 24) | (word.bytes[1] << 16) | (word.bytes[2] << 8) | word.bytes[3];
-}
-
-static inline void set_UINT32BE(UINT32BE *word, uint32_t data)
-{
- word->bytes[0] = (data >> 24) & 0xff;
- word->bytes[1] = (data >> 16) & 0xff;
- word->bytes[2] = (data >> 8) & 0xff;
- word->bytes[3] = data & 0xff;
-}
-
-/*
- Macintosh string: first byte is length
-*/
-typedef uint8_t mac_str27[28];
-typedef uint8_t mac_str31[32];
-typedef uint8_t mac_str63[64];
-typedef uint8_t mac_str255[256];
-
-/*
- Macintosh type/creator code: 4 char value
-*/
-typedef UINT32BE mac_type;
-
-/*
- point record, with the y and x coordinates
-*/
-struct mac_point
-{
- UINT16BE v; /* actually signed */
- UINT16BE h; /* actually signed */
-};
-
-/*
- rect record, with the corner coordinates
-*/
-struct mac_rect
-{
- UINT16BE top; /* actually signed */
- UINT16BE left; /* actually signed */
- UINT16BE bottom;/* actually signed */
- UINT16BE right; /* actually signed */
-};
-
-/*
- FInfo (Finder file info) record
-*/
-struct mac_FInfo
-{
- mac_type type; /* file type */
- mac_type creator; /* file creator */
- UINT16BE flags; /* Finder flags */
- mac_point location; /* file's location in window */
- /* If set to {0, 0}, and the inited flag is
- clear, the Finder will place the item
- automatically */
- UINT16BE fldr; /* MFS: window that contains file */
- /* -3: trash */
- /* -2: desktop */
- /* -1: new folder template?????? */
- /* 0: disk window ("root") */
- /* > 0: specific folder, index of FOBJ resource??? */
- /* The FOBJ resource contains some folder info;
- the name of the resource is the folder name. */
- /* HFS & HFS+:
- System 7: The window in which the file???s icon appears
- System 8: reserved (set to 0) */
-};
-
-/*
- FXInfo (Finder extended file info) record -- not found in MFS
-*/
-struct mac_FXInfo
-{
- UINT16BE iconID; /* System 7: An ID number for the file???s icon; the
- numbers that identify icons are assigned by the
- Finder */
- /* System 8: Reserved (set to 0) */
- UINT16BE reserved[3]; /* Reserved (set to 0) */
- uint8_t script; /* System 7: if high-bit is set, the script code
- for displaying the file name; ignored otherwise */
- /* System 8: Extended flags MSB(?) */
- uint8_t XFlags; /* Extended flags */
- UINT16BE comment; /* System 7: Comment ID if high-bit is clear */
- /* System 8: Reserved (set to 0) */
- UINT32BE putAway; /* Put away folder ID (i.e. if the user moves the
- file onto the desktop, the directory ID of the
- folder from which the user moves the file is
- saved here) */
-};
-
-/*
- DInfo (Finder folder info) record -- not found in MFS
-*/
-struct mac_DInfo
-{
- mac_rect rect; /* Folder's window bounds */
- UINT16BE flags; /* Finder flags, e.g. kIsInvisible, kNameLocked, etc */
- mac_point location; /* Location of the folder in parent window */
- /* If set to {0, 0}, and the initied flag is
- clear, the Finder will place the item
- automatically */
- UINT16BE view; /* System 7: The manner in which folders are
- displayed */
- /* System 8: reserved (set to 0) */
-};
-
-/*
- DXInfo (Finder extended folder info) record -- not found in MFS
-*/
-struct mac_DXInfo
-{
- mac_point scroll; /* Scroll position */
- UINT32BE openChain; /* System 7: chain of directory IDs for open folders */
- /* System 8: reserved (set to 0) */
- uint8_t script; /* System 7: if high-bit is set, the script code
- for displaying the folder name; ignored otherwise */
- /* System 8: Extended flags MSB(?) */
- uint8_t XFlags; /* Extended flags */
- UINT16BE comment; /* System 7: Comment ID if high-bit is clear */
- /* System 8: Reserved (set to 0) */
- UINT32BE putAway; /* Put away folder ID (i.e. if the user moves the
- folder onto the desktop, the directory ID of
- the folder from which the user moves it is
- saved here) */
-};
-
-/*
- defines for FInfo & DInfo flags fields
-*/
-enum
-{
- fif_isOnDesk = 0x0001, /* System 6: set if item is located on desktop (files and folders) */
- /* System 7: Unused (set to 0) */
- fif_color = 0x000E, /* color coding (files and folders) */
- fif_colorReserved = 0x0010, /* System 6: reserved??? */
- /* System 7: Unused (set to 0) */
- fif_requiresSwitchLaunch= 0x0020, /* System 6: ??? */
- /* System 7: Unused (set to 0) */
- fif_isShared = 0x0040, /* Applications files: if set, the */
- /* application can be executed by */
- /* multiple users simultaneously. */
- /* Otherwise, set to 0. */
- fif_hasNoINITs = 0x0080, /* Extensions/Control Panels: if set(?), */
- /* this file contains no INIT */
- /* resource */
- /* Otherwise, set to 0. */
- fif_hasBeenInited = 0x0100, /* System 6: The Finder has recorded information from
- the file???s bundle resource into the desktop
- database and given the file or folder a
- position on the desktop. */
- /* System 7? 8?: Clear if the file contains desktop database */
- /* resources ('BNDL', 'FREF', 'open', 'kind'...) */
- /* that have not been added yet. Set only by the Finder */
- /* Reserved for folders - make sure this bit is cleared for folders */
-
- /* bit 0x0200 was at a point (AOCE for system 7.x?) the letter bit for
- AOCE, but was reserved before and it is reserved again in recent MacOS
- releases. */
-
- fif_hasCustomIcon = 0x0400, /* (files and folders) */
- fif_isStationery = 0x0800, /* System 7: (files only) */
- fif_nameLocked = 0x1000, /* (files and folders) */
- fif_hasBundle = 0x2000, /* Files only */
- fif_isInvisible = 0x4000, /* (files and folders) */
- fif_isAlias = 0x8000 /* System 7: (files only) */
-};
-
-/*
- mac_to_c_strncpy()
-
- Encode a macintosh string as a C string. The NUL character is escaped,
- using the "%00" sequence. To avoid any ambiguity, '%' is escaped with
- '%25'.
-
- dst (O): C string
- n (I): length of buffer pointed to by dst
- src (I): macintosh string (first byte is length)
-*/
-static void mac_to_c_strncpy(char *dst, int n, uint8_t *src)
-{
- size_t len = src[0];
- int i, j;
-
- i = j = 0;
- while ((i < len) && (j < n-1))
- {
- switch (src[i+1])
- {
- case '\0':
- if (j >= n-3)
- goto exit;
- dst[j] = '%';
- dst[j+1] = '0';
- dst[j+2] = '0';
- j += 3;
- break;
-
- case '%':
- if (j >= n-3)
- goto exit;
- dst[j] = '%';
- dst[j+1] = '2';
- dst[j+2] = '5';
- j += 3;
- break;
-
- default:
- dst[j] = src[i+1];
- j++;
- break;
- }
- i++;
- }
-
-exit:
- if (n > 0)
- dst[j] = '\0';
-}
-
-/*
- c_to_mac_strncpy()
-
- Decode a C string to a macintosh string. The NUL character is escaped,
- using the "%00" sequence. To avoid any ambiguity, '%' is escaped with
- '%25'.
-
- dst (O): macintosh string (first byte is length)
- src (I): C string
- n (I): length of string pointed to by src
-*/
-static void c_to_mac_strncpy(mac_str255 dst, const char *src, int n)
-{
- size_t len;
- int i;
- char buf[3];
-
-
- len = 0;
- i = 0;
- while ((i < n) && (len < 255))
- {
- switch (src[i])
- {
- case '%':
- if (i >= n-2)
- goto exit;
- buf[0] = src[i+1];
- buf[1] = src[i+2];
- buf[2] = '\0';
- dst[len+1] = strtoul(buf, NULL, 16);
- i += 3;
- break;
-
- default:
- dst[len+1] = src[i];
- i++;
- break;
- }
- len++;
- }
-
-exit:
- dst[0] = len;
-}
-
-/*
- mac_strcmp()
-
- Compare two macintosh strings
-
- s1 (I): the string to compare
- s2 (I): the comparison string
-
- Return a zero if s1 and s2 are equal, a negative value if s1 is less than
- s2, and a positive value if s1 is greater than s2.
-*/
-#ifdef UNUSED_FUNCTION
-static int mac_strcmp(const uint8_t *s1, const uint8_t *s2)
-{
- size_t common_len;
-
- common_len = (s1[0] <= s2[0]) ? s1[0] : s2[0];
-
- return memcmp(s1+1, s2+1, common_len) || ((int)s1[0] - s2[0]);
-}
-#endif
-
-/*
- mac_stricmp()
-
- Compare two macintosh strings in a manner compatible with the macintosh HFS
- file system.
-
- This functions emulates the way HFS (and MFS???) sorts string: this is
- equivalent to the RelString macintosh toolbox call with the caseSensitive
- parameter as false and the diacSensitive parameter as true.
-
- s1 (I): the string to compare
- s2 (I): the comparison string
-
- Return a zero if s1 and s2 are equal, a negative value if s1 is less than
- s2, and a positive value if s1 is greater than s2.
-
-Known issues:
- Using this function makes sense with the MacRoman encoding, as it means the
- computer will regard "DeskTop File", "Desktop File", "Desktop file", etc,
- as the same file. (UNIX users will probably regard this as an heresy, but
- you must consider that, unlike UNIX, the Macintosh was not designed for
- droids, but error-prone human beings that may forget about case.)
-
- (Also, letters with diatrical signs follow the corresponding letters
- without diacritical signs in the HFS catalog file. This does not matter,
- though, since the Finder will not display files in the HFS catalog order,
- but it will instead sort files according to whatever order is currently
- selected in the View menu.)
-
- However, with other text encodings, the behavior will be completely absurd.
- For instance, with the Greek encoding, it will think that the degree symbol
- is the same letter (with different case) as the upper-case Psi, so that if
- a program asks for a file called "90??" on a greek HFS volume, and there is
- a file called "90??" on this volume, file "90??" will be opened.
- Results will probably be even weirder with 2-byte scripts like Japanese or
- Chinese. Of course, we are not going to fix this issue, since doing so
- would break the compatibility with the original Macintosh OS.
-*/
-
-static int mac_stricmp(const uint8_t *s1, const uint8_t *s2)
-{
- static const unsigned char mac_char_sort_table[256] =
- {
- /* \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- /* \x08 \x09 \x0a \x0b \x0c \x0d \x0e \x0f */
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- /* \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 */
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- /* \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f */
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- /* \x20 \x21 \x22 \x23 \x24 \x25 \x26 \x27 */
- 0x20, 0x21, 0x22, 0x27, 0x28, 0x29, 0x2a, 0x2b,
- /* \x28 \x29 \x2a \x2b \x2c \x2d \x2e \x2f */
- 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
- /* \x30 \x31 \x32 \x33 \x34 \x35 \x36 \x37 */
- 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
- /* \x38 \x39 \x3a \x3b \x3c \x3d \x3e \x3f */
- 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
- /* \x40 \x41 \x42 \x43 \x44 \x45 \x46 \x47 */
- 0x46, 0x47, 0x51, 0x52, 0x54, 0x55, 0x5a, 0x5b,
- /* \x48 \x49 \x4a \x4b \x4c \x4d \x4e \x4f */
- 0x5c, 0x5d, 0x62, 0x63, 0x64, 0x65, 0x66, 0x68,
- /* \x50 \x51 \x52 \x53 \x54 \x55 \x56 \x57 */
- 0x71, 0x72, 0x73, 0x74, 0x76, 0x77, 0x7c, 0x7d,
- /* \x58 \x59 \x5a \x5b \x5c \x5d \x5e \x5f */
- 0x7e, 0x7f, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
- /* \x60 \x61 \x62 \x63 \x64 \x65 \x66 \x67 */
- 0x4d, 0x47, 0x51, 0x52, 0x54, 0x55, 0x5a, 0x5b,
- /* \x68 \x69 \x6a \x6b \x6c \x6d \x6e \x6f */
- 0x5c, 0x5d, 0x62, 0x63, 0x64, 0x65, 0x66, 0x68,
- /* \x70 \x71 \x72 \x73 \x74 \x75 \x76 \x77 */
- 0x71, 0x72, 0x73, 0x74, 0x76, 0x77, 0x7c, 0x7d,
- /* \x78 \x79 \x7a \x7b \x7c \x7d \x7e \x7f */
- 0x7e, 0x7f, 0x81, 0x87, 0x88, 0x89, 0x8a, 0x8b,
- /* \x80 \x81 \x82 \x83 \x84 \x85 \x86 \x87 */
- 0x49, 0x4b, 0x53, 0x56, 0x67, 0x69, 0x78, 0x4e,
- /* \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f */
- 0x48, 0x4f, 0x49, 0x4a, 0x4b, 0x53, 0x56, 0x57,
- /* \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 */
- 0x58, 0x59, 0x5e, 0x5f, 0x60, 0x61, 0x67, 0x6d,
- /* \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f */
- 0x6e, 0x6f, 0x69, 0x6a, 0x79, 0x7a, 0x7b, 0x78,
- /* \xa0 \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 */
- 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x75,
- /* \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf */
- 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x4c, 0x6b,
- /* \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 */
- 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
- /* \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf */
- 0xa1, 0xa2, 0xa3, 0x50, 0x70, 0xa4, 0x4c, 0x6b,
- /* \xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 */
- 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0x25,
- /* \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf */
- 0x26, 0xac, 0x20, 0x48, 0x4a, 0x6a, 0x6c, 0x6c,
- /* \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 */
- 0xad, 0xae, 0x23, 0x24, 0x2c, 0x2d, 0xaf, 0xb0,
- /* \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf */
- 0x80, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
- /* \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 */
- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
- /* \xe8 \xe9 \xea \xeb \xec \xed \xee \xef */
- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
- /* \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 */
- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
- /* \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff */
- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7
- };
-
- size_t common_len;
- int i;
- int c1, c2;
-
- common_len = (s1[0] <= s2[0]) ? s1[0] : s2[0];
-
- for (i=0; i<common_len; i++)
- {
- c1 = mac_char_sort_table[s1[i+1]];
- c2 = mac_char_sort_table[s2[i+1]];
- if (c1 != c2)
- return c1 - c2;
- }
-
- return ((int)s1[0] - s2[0]);
-}
-
-/*
- mac_strcpy()
-
- Copy a macintosh string
-
- dst (O): dest macintosh string
- src (I): source macintosh string (first byte is length)
-
- Return a zero if s1 and s2 are equal, a negative value if s1 is less than
- s2, and a positive value if s1 is greater than s2.
-*/
-static inline void mac_strcpy(uint8_t *dest, const uint8_t *src)
-{
- memcpy(dest, src, src[0]+1);
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- mac_strncpy()
-
- Copy a macintosh string
-
- dst (O): dest macintosh string
- n (I): max string length for dest (range 0-255, buffer length + 1)
- src (I): source macintosh string (first byte is length)
-*/
-static void mac_strncpy(uint8_t *dest, int n, const uint8_t *src)
-{
- size_t len;
-
- len = src[0];
- if (len > n)
- len = n;
- dest[0] = len;
- memcpy(dest+1, src+1, len);
-}
-#endif
-
-/*
- disk image reference
-*/
-struct mac_l1_imgref
-{
- imgtool::image *image;
- uint32_t heads;
-};
-
-
-
-static imgtoolerr_t mac_find_block(mac_l1_imgref *image, int block,
- uint32_t *track, uint32_t *head, uint32_t *sector)
-{
- *track = 0;
- while(block >= (apple35_sectors_per_track(imgtool_floppy(*image->image), *track) * image->heads))
- {
- block -= (apple35_sectors_per_track(imgtool_floppy(*image->image), (*track)++) * image->heads);
- if (*track >= 80)
- return IMGTOOLERR_SEEKERROR;
- }
-
- *head = block / apple35_sectors_per_track(imgtool_floppy(*image->image), *track);
- *sector = block % apple35_sectors_per_track(imgtool_floppy(*image->image), *track);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*
- image_read_block()
-
- Read one 512-byte block of data from a macintosh disk image
-
- image (I/O): level-1 image reference
- block (I): address of block to read
- dest (O): buffer where block data should be stored
-
- Return imgtool error code
-*/
-static imgtoolerr_t image_read_block(mac_l1_imgref *image, uint32_t block, void *dest)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- uint32_t track, head, sector;
-
- err = mac_find_block(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_read_sector(imgtool_floppy(*image->image), head, track, sector, 0, dest, 512);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- image_write_block()
-
- Read one 512-byte block of data from a macintosh disk image
-
- image (I/O): level-1 image reference
- block (I): address of block to write
- src (I): buffer with the block data
-
- Return imgtool error code
-*/
-static imgtoolerr_t image_write_block(mac_l1_imgref *image, uint32_t block, const void *src)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- uint32_t track, head, sector;
-
- err = mac_find_block(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_write_sector(imgtool_floppy(*image->image), head, track, sector, 0, src, 512, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- image_get_tag_len()
-
- Get length of tag data (12 for GCR floppies, 20 for HD20, 0 otherwise)
-
- image (I/O): level-1 image reference
-
- Return tag length
-*/
-static inline int image_get_tag_len(mac_l1_imgref *image)
-{
- return 0;
-}
-
-
-
-/*
- image_read_tag()
-
- Read a 12- or 20-byte tag record associated with a disk block
-
- image (I/O): level-1 image reference
- block (I): address of block to read
- dest (O): buffer where tag data should be stored
-
- Return imgtool error code
-*/
-static imgtoolerr_t image_read_tag(mac_l1_imgref *image, uint32_t block, void *dest)
-{
- return IMGTOOLERR_UNEXPECTED;
-}
-
-/*
- image_write_tag()
-
- Write a 12- or 20-byte tag record associated with a disk block
-
- image (I/O): level-1 image reference
- block (I): address of block to write
- src (I): buffer with the tag data
-
- Return imgtool error code
-*/
-static imgtoolerr_t image_write_tag(mac_l1_imgref *image, uint32_t block, const void *src)
-{
- return IMGTOOLERR_UNEXPECTED;
-}
-
-#if 0
-#pragma mark -
-#pragma mark MFS/HFS WRAPPERS
-#endif
-
-enum mac_format
-{
- L2I_MFS,
- L2I_HFS
-};
-
-enum mac_forkID { data_fork = 0x00, rsrc_fork = 0xff };
-
-/*
- MFS image ref
-*/
-struct mfs_l2_imgref
-{
- uint16_t dir_num_files;
- uint16_t dir_start;
- uint16_t dir_blk_len;
-
- uint16_t ABStart;
-
- mac_str27 volname;
-
- unsigned char ABlink_dirty[13]; /* dirty flag for each disk block in the ABlink array */
- uint8_t ABlink[6141];
-};
-
-/*
- HFS extent descriptor
-*/
-struct hfs_extent
-{
- UINT16BE stABN; /* first allocation block */
- UINT16BE numABlks; /* number of allocation blocks */
-};
-
-/*
- HFS likes to group extents by 3 (it is 8 with HFS+), so we create a
- specific type.
-*/
-typedef hfs_extent hfs_extent_3[3];
-
-/*
- MFS open file ref
-*/
-struct mfs_fileref
-{
- uint16_t stBlk; /* first allocation block of file */
-};
-
-/*
- HFS open file ref
-*/
-struct hfs_fileref
-{
- hfs_extent_3 extents; /* first 3 file extents */
-
- uint32_t parID; /* CNID of parent directory (undefined for extent & catalog files) */
- mac_str31 filename; /* file name (undefined for extent & catalog files) */
-};
-
-struct mac_l2_imgref;
-
-/*
- MFS/HFS open file ref
-*/
-struct mac_fileref
-{
- struct mac_l2_imgref *l2_img; /* image pointer */
-
- uint32_t fileID; /* file ID (a.k.a. CNID in HFS/HFS+) */
-
- mac_forkID forkType; /* 0x00 for data, 0xff for resource */
-
- uint32_t eof; /* logical end-of-file */
- uint32_t pLen; /* physical end-of-file */
-
- uint32_t crPs; /* current position in file */
-
- uint8_t reload_buf;
- uint8_t block_buffer[512]; /* buffer with current file block */
-
- union
- {
- mfs_fileref mfs;
- hfs_fileref hfs;
- };
-};
-
-/*
- open BT ref
-*/
-struct mac_BTref
-{
- struct mac_fileref fileref; /* open B-tree file ref */
-
- uint16_t nodeSize; /* size of a node, in bytes */
- uint32_t rootNode; /* node number of root node */
- uint32_t firstLeafNode; /* node number of first leaf node */
- uint32_t attributes; /* persistent attributes about the tree */
- uint16_t treeDepth; /* maximum height (usually leaf nodes) */
- uint16_t maxKeyLength; /* maximum key length */
-
- /* function to compare keys during tree searches */
- int (*key_compare_func)(const void *key1, const void *key2);
-
- void *node_buf; /* current node buffer */
-};
-
-/*
- Constants for BTHeaderRec attributes field
-*/
-enum
-{
- btha_badCloseMask = 0x00000001, /* reserved */
- btha_bigKeysMask = 0x00000002, /* key length field is 16 bits */
- btha_variableIndexKeysMask = 0x00000004 /* keys in index nodes are variable length */
-};
-
-/*
- HFS image ref
-*/
-struct hfs_l2_imgref
-{
- uint16_t VBM_start;
-
- uint16_t ABStart;
-
- mac_str27 volname;
-
- mac_BTref extents_BT;
- mac_BTref cat_BT;
-
- uint8_t VBM[8192];
-};
-
-/*
- MFS/HFS image ref
-*/
-struct mac_l2_imgref
-{
- mac_l1_imgref l1_img;
-
- uint16_t numABs;
- uint16_t blocksperAB;
-
- uint16_t freeABs;
-
- uint32_t nxtCNID; /* nxtFNum in MFS, nxtCNID in HFS */
-
- mac_format format;
- union
- {
- mfs_l2_imgref mfs;
- hfs_l2_imgref hfs;
- } u;
-};
-
-/*
- MFS Master Directory Block
-*/
-struct mfs_mdb
-{
- uint8_t sigWord[2]; /* volume signature - always $D2D7 */
- UINT32BE crDate; /* date and time of volume creation */
- UINT32BE lsMod/*lsBkUp???*/;/* date and time of last modification (backup???) */
- UINT16BE atrb; /* volume attributes (0x0000) */
- /* bit 15 is set if volume is locked by software */
- UINT16BE nmFls; /* number of files in directory */
- UINT16BE dirSt; /* first block of directory */
-
- UINT16BE blLn; /* length of directory in blocks (0x000C) */
- UINT16BE nmAlBlks; /* number of allocation blocks in volume (0x0187) */
- UINT32BE alBlkSiz; /* size (in bytes) of allocation blocks (0x00000400) */
- UINT32BE clpSiz; /* default clump size - number of bytes to allocate
- when a file grows (0x00002000) */
- UINT16BE alBlSt; /* first allocation block in volume (0x0010) */
-
- UINT32BE nxtFNum; /* next unused file number */
- UINT16BE freeABs; /* number of unused allocation blocks */
-
- mac_str27 VN; /* volume name */
-
- uint8_t ABlink[512-64];/* Link array for file ABs. Array of nmAlBlks
- 12-bit-long entries, indexed by AB address. If an
- AB belongs to no file, the entry is 0; if an AB is
- the last in any file, the entry is 1; if an AB
- belongs to a file and is not the last one, the
- entry is the AB address of the next file AB plus 1.
- Note that the array extends on as many consecutive
- disk blocks as needed (usually the MDB block plus
- the next one). Incidentally, this array is not
- saved in the secondary MDB: presumably, the idea
- was that the disk utility could rely on the tag
- data to rebuild the link array if it should ever
- be corrupted. */
-};
-
-/*
- HFS Master Directory Block
-*/
-struct hfs_mdb
-{
-/* First fields are similar to MFS, though several fields have a different meaning */
- uint8_t sigWord[2]; /* volume signature - always $D2D7 */
- UINT32BE crDate; /* date and time of volume creation */
- UINT32BE lsMod; /* date and time of last modification */
- UINT16BE atrb; /* volume attributes (0x0000) */
- /* bit 15 is set if volume is locked by software */
- UINT16BE nmFls; /* number of files in root folder */
- UINT16BE VBMSt; /* first block of volume bitmap */
- UINT16BE allocPtr; /* start of next allocation search */
-
- UINT16BE nmAlBlks; /* number of allocation blocks in volume */
- UINT32BE alBlkSiz; /* size (in bytes) of allocation blocks */
- UINT32BE clpSiz; /* default clump size - number of bytes to allocate
- when a file grows */
- UINT16BE alBlSt; /* first allocation block in volume (0x0010) */
- UINT32BE nxtCNID; /* next unused catalog node ID */
- UINT16BE freeABs; /* number of unused allocation blocks */
- mac_str27 VN; /* volume name */
-
-/* next fields are HFS-specific */
-
- UINT32BE volBkUp; /* date and time of last backup */
- UINT16BE vSeqNum; /* volume backup sequence number */
- UINT32BE wrCnt; /* volume write count */
- UINT32BE xtClpSiz; /* clump size for extents overflow file */
- UINT32BE ctClpSiz; /* clump size for catalog file */
- UINT16BE nmRtDirs; /* number of directories in root folder */
- UINT32BE filCnt; /* number of files in volume */
- UINT32BE dirCnt; /* number of directories in volume */
- uint8_t fndrInfo[32]; /* information used by the Finder */
-
- union
- {
- struct
- {
- UINT16BE VCSize; /* size (in blocks) of volume cache */
- UINT16BE VBMCSize; /* size (in blocks) of volume bitmap cache */
- UINT16BE ctlCSize; /* size (in blocks) of common volume cache */
- };
- struct
- {
- UINT16BE embedSigWord; /* embedded volume signature */
- hfs_extent embedExtent; /* embedded volume location and size */
- } v2;
- } u;
-
- UINT32BE xtFlSize; /* size (in bytes) of extents overflow file */
- hfs_extent_3 xtExtRec; /* extent record for extents overflow file */
- UINT32BE ctFlSize; /* size (in bytes) of catalog file */
- hfs_extent_3 ctExtRec; /* extent record for catalog file */
-};
-
-/* to save a little stack space, we use the same buffer for MDB and next blocks */
-union img_open_buf
-{
- struct mfs_mdb mfs_mdb;
- struct hfs_mdb hfs_mdb;
- uint8_t raw[512];
-};
-
-/*
- Information extracted from catalog/directory
-*/
-struct mac_dirent
-{
- uint16_t dataRecType; /* type of data record */
-
- mac_FInfo flFinderInfo; /* information used by the Finder */
- mac_FXInfo flXFinderInfo; /* information used by the Finder */
-
- uint8_t flags; /* bit 0=1 if file locked */
-
- uint32_t fileID; /* file ID in directory/catalog */
-
- uint32_t dataLogicalSize; /* logical EOF of data fork */
- uint32_t dataPhysicalSize; /* physical EOF of data fork */
- uint32_t rsrcLogicalSize; /* logical EOF of resource fork */
- uint32_t rsrcPhysicalSize; /* physical EOF of resource fork */
-
- uint32_t createDate; /* date and time of creation */
- uint32_t modifyDate; /* date and time of last modification */
-};
-
-/*
- Tag record for GCR floppies (12 bytes)
-
- And, no, I don't know the format of the 20-byte tag record of the HD20
-*/
-struct floppy_tag_record
-{
- UINT32BE fileID; /* a.k.a. CNID */
- /* a value of 1 seems to be the default for non-AB blocks, but this is not consistent */
- uint8_t ftype; /* bit 1 = 1 if resource fork */
- /* bit 0 = 1 if block is allocated to user file (i.e. it is not
- in HFS extent & catalog, and not in non-AB blocks such
- as MDB and MFS directory)??? */
- /* bit 7 seems to be used, but I don't know what it means */
- /* a value of $FF seems to be the default for non-AB blocks, but this is not consistent */
- uint8_t fattr; /* bit 0 = 1 if locked(?) */
- /* a value of $FF seems to be the default for non-AB blocks, but this is not consistent */
- UINT16BE fblock; /* relative file block number (enough for any volume up to 32 MBytes in size) */
- UINT32BE wrCnt; /* MFS: date and time of last write */
- /* HFS: seems related to the wrCnt field in the mdb, i.e.
- each time a volume is written to, the current value of
- wrCnt is written in the tag field, then it is incremented */
- /* (DV17 says "disk block number", but it cannot be true) */
-};
-
-#ifdef UNUSED_FUNCTION
-static void hfs_image_close(struct mac_l2_imgref *l2_img);
-#endif
-static imgtoolerr_t mfs_file_get_nth_block_address(struct mac_fileref *fileref, uint32_t block_num, uint32_t *block_address);
-static imgtoolerr_t hfs_file_get_nth_block_address(struct mac_fileref *fileref, uint32_t block_num, uint32_t *block_address);
-static imgtoolerr_t mfs_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, mac_str255 filename, mac_dirent *cat_info, int create_it);
-static imgtoolerr_t hfs_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, uint32_t *parID, mac_str255 filename, mac_dirent *cat_info);
-static imgtoolerr_t mfs_file_open(struct mac_l2_imgref *l2_img, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref);
-static imgtoolerr_t hfs_file_open(struct mac_l2_imgref *l2_img, uint32_t parID, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref);
-static imgtoolerr_t mfs_file_setABeof(struct mac_fileref *fileref, uint32_t newABeof);
-static imgtoolerr_t mfs_dir_update(struct mac_fileref *fileref);
-
-static struct mac_l2_imgref *get_imgref(imgtool::image &img)
-{
- return (struct mac_l2_imgref *) imgtool_floppy_extrabytes(img);
-}
-
-
-#ifdef UNUSED_FUNCTION
-/*
- mac_image_close
-
- Close a macintosh image.
-
- l2_img (I/O): level-2 image reference
-*/
-static void mac_image_close(struct mac_l2_imgref *l2_img)
-{
- switch (l2_img->format)
- {
- case L2I_MFS:
- break;
-
- case L2I_HFS:
- hfs_image_close(l2_img);
- break;
- }
-}
-#endif
-
-/*
- mac_lookup_path
-
- Resolve a file path, and translate it to a parID + filename pair that enables
- to do an efficient file search on a HFS volume (and an inefficient one on
- MFS, but it is not an issue as MFS volumes typically have a few dozens
- files, vs. possibly thousands with HFS volumes).
-
- l2_img (I/O): level-2 image reference
- fpath (I): file path (C string)
- parID (O): set to the CNID of the parent directory if the volume is in HFS
- format (reserved for MFS volumes)
- filename (O): set to the actual name of the file, with capitalization matching
- the one on the volume rather than the one in the fpath parameter (Mac
- string)
- cat_info (O): catalog info for this file extracted from the catalog file
- (may be NULL)
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, uint32_t *parID, mac_str255 filename, mac_dirent *cat_info, int create_it)
-{
- imgtoolerr_t err = IMGTOOLERR_UNEXPECTED;
-
- switch (l2_img->format)
- {
- case L2I_MFS:
- *parID = 0;
- err = mfs_lookup_path(l2_img, fpath, filename, cat_info, create_it);
- break;
-
- case L2I_HFS:
- err = hfs_lookup_path(l2_img, fpath, parID, filename, cat_info);
- break;
- }
- return err;
-}
-
-/*
- mac_file_open
-
- Open a file located on a macintosh image
-
- l2_img (I/O): level-2 image reference
- parID (I): CNID of the parent directory if the volume is in HFS format
- (reserved for MFS volumes)
- filename (I): name of the file (Mac string)
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_open(struct mac_l2_imgref *l2_img, uint32_t parID, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref)
-{
- switch (l2_img->format)
- {
- case L2I_MFS:
- return mfs_file_open(l2_img, filename, fork, fileref);
-
- case L2I_HFS:
- return hfs_file_open(l2_img, parID, filename, fork, fileref);
- }
-
- return IMGTOOLERR_UNEXPECTED;
-}
-
-/*
- mac_file_read
-
- Read data from an open mac file, starting at current position in file
-
- fileref (I/O): mac file reference
- len (I): number of bytes to read
- dest (O): destination buffer
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_read(struct mac_fileref *fileref, uint32_t len, void *dest)
-{
- uint32_t block = 0;
- floppy_tag_record tag;
- int run_len;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
- if ((fileref->crPs + len) > fileref->eof)
- /* EOF */
- return IMGTOOLERR_UNEXPECTED;
-
- while (len > 0)
- {
- if (fileref->reload_buf)
- {
- switch (fileref->l2_img->format)
- {
- case L2I_MFS:
- err = mfs_file_get_nth_block_address(fileref, fileref->crPs/512, &block);
- break;
-
- case L2I_HFS:
- err = hfs_file_get_nth_block_address(fileref, fileref->crPs/512, &block);
- break;
- }
- if (err)
- return err;
- err = image_read_block(&fileref->l2_img->l1_img, block, fileref->block_buffer);
- if (err)
- return err;
- fileref->reload_buf = false;
-
- if (TAG_EXTRA_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, block, &tag);
- if (err)
- return err;
-
- if ((get_UINT32BE(tag.fileID) != fileref->fileID)
- || (((tag.ftype & 2) != 0) != (fileref->forkType == rsrc_fork))
- || (get_UINT16BE(tag.fblock) != ((fileref->crPs/512) & 0xffff)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- }
- }
- }
- run_len = 512 - (fileref->crPs % 512);
- if (run_len > len)
- run_len = len;
-
- memcpy(dest, fileref->block_buffer+(fileref->crPs % 512), run_len);
- len -= run_len;
- dest = (uint8_t *)dest + run_len;
- fileref->crPs += run_len;
- if ((fileref->crPs % 512) == 0)
- fileref->reload_buf = true;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mac_file_write
-
- Write data to an open mac file, starting at current position in file
-
- fileref (I/O): mac file reference
- len (I): number of bytes to read
- dest (O): destination buffer
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_write(struct mac_fileref *fileref, uint32_t len, const void *src)
-{
- uint32_t block = 0;
- floppy_tag_record tag;
- int run_len;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
- if ((fileref->crPs + len) > fileref->eof)
- /* EOF */
- return IMGTOOLERR_UNEXPECTED;
-
- while (len > 0)
- {
- switch (fileref->l2_img->format)
- {
- case L2I_MFS:
- err = mfs_file_get_nth_block_address(fileref, fileref->crPs/512, &block);
- break;
-
- case L2I_HFS:
- err = hfs_file_get_nth_block_address(fileref, fileref->crPs/512, &block);
- break;
- }
- if (err)
- return err;
-
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, block, &tag);
- if (err)
- return err;
-
- if ((get_UINT32BE(tag.fileID) != fileref->fileID)
- || (((tag.ftype & 2) != 0) != (fileref->forkType == rsrc_fork))
- || (get_UINT16BE(tag.fblock) != ((fileref->crPs/512) & 0xffff)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- }
- }
-
- if (fileref->reload_buf)
- {
- err = image_read_block(&fileref->l2_img->l1_img, block, fileref->block_buffer);
- if (err)
- return err;
- fileref->reload_buf = false;
- }
- run_len = 512 - (fileref->crPs % 512);
- if (run_len > len)
- run_len = len;
-
- memcpy(fileref->block_buffer+(fileref->crPs % 512), src, run_len);
- err = image_write_block(&fileref->l2_img->l1_img, block, fileref->block_buffer);
- if (err)
- return err;
- /* update tag data */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- if (!TAG_CHECKS)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, block, &tag);
- if (err)
- return err;
- }
-
- switch (fileref->l2_img->format)
- {
- case L2I_MFS:
- set_UINT32BE(&tag.wrCnt, mac_time_now());
- break;
-
- case L2I_HFS:
- /*set_UINT32BE(&tag.wrCnt, ++fileref->l2_img.u.hfs.wrCnt);*/ /* ***TODO*** */
- break;
- }
-
- err = image_write_tag(&fileref->l2_img->l1_img, block, &tag);
- if (err)
- return err;
- }
- len -= run_len;
- src = (const uint8_t *)src + run_len;
- fileref->crPs += run_len;
- if ((fileref->crPs % 512) == 0)
- fileref->reload_buf = true;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- mac_file_tell
-
- Get current position in an open mac file
-
- fileref (I/O): mac file reference
- filePos (O): current position in file
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_tell(struct mac_fileref *fileref, uint32_t *filePos)
-{
- *filePos = fileref->crPs;
-
- return IMGTOOLERR_SUCCESS;
-}
-#endif
-
-/*
- mac_file_seek
-
- Set current position in an open mac file
-
- fileref (I/O): mac file reference
- filePos (I): new position in file
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_seek(struct mac_fileref *fileref, uint32_t filePos)
-{
- if ((fileref->crPs / 512) != (filePos / 512))
- fileref->reload_buf = true;
-
- fileref->crPs = filePos;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mac_file_seteof
-
- Set the position of the EOF in an open mac file
-
- fileref (I/O): mac file reference
- newEof (I): new position of EOF in file
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_seteof(struct mac_fileref *fileref, uint32_t newEof)
-{
- uint32_t newABEof;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
- newABEof = (newEof + fileref->l2_img->blocksperAB * 512 - 1) / (fileref->l2_img->blocksperAB * 512);
-
-#if 0
- if (fileref->pLen % (fileref->l2_img->blocksperAB * 512))
- return IMGTOOLERR_CORRUPTIMAGE;
-#endif
-
- if (newEof < fileref->eof)
- fileref->eof = newEof;
-
- switch (fileref->l2_img->format)
- {
- case L2I_MFS:
- err = mfs_file_setABeof(fileref, newABEof);
- break;
-
- case L2I_HFS:
- err = IMGTOOLERR_UNIMPLEMENTED;
- break;
- }
- if (err)
- return err;
-
- fileref->eof = newEof;
-
- err = mfs_dir_update(fileref);
- if (err)
- return err;
-
- /* update current pos if beyond new EOF */
-#if 0
- if (fileref->crPs > newEof)
- {
- if ((fileref->crPs / 512) != (newEof / 512))
- fileref->reload_buf = true;
-
- fileref->crPs = newEof;
- }
-#endif
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#if 0
-#pragma mark -
-#pragma mark MFS IMPLEMENTATION
-#endif
-
-/*
- directory entry for use in the directory file
-
- Note the structure is variable length. It is always word-aligned, and
- cannot cross block boundaries.
-
- Note that the directory does not seem to be sorted: the order in which
- files appear does not match file names, and it does not always match file
- IDs.
-*/
-struct mfs_dir_entry
-{
- uint8_t flags; /* bit 7=1 if entry used, bit 0=1 if file locked */
- /* 0x00 means end of block: if we are not done
- with reading the directory, the remnants will
- be read from next block */
- uint8_t flVersNum; /* version number (usually 0x00, but I don't
- have the IM volume that describes it) */
- mac_FInfo flFinderInfo; /* information used by the Finder */
-
- UINT32BE fileID; /* file ID */
-
- UINT16BE dataStartBlock; /* first allocation block of data fork */
- UINT32BE dataLogicalSize; /* logical EOF of data fork */
- UINT32BE dataPhysicalSize; /* physical EOF of data fork */
- UINT16BE rsrcStartBlock; /* first allocation block of resource fork */
- UINT32BE rsrcLogicalSize; /* logical EOF of resource fork */
- UINT32BE rsrcPhysicalSize; /* physical EOF of resource fork */
-
- UINT32BE createDate; /* date and time of creation */
- UINT32BE modifyDate; /* date and time of last modification */
-
- uint8_t name[1]; /* first char is length of file name */
- /* next chars are file name - 255 chars at most */
- /* IIRC, Finder 7 only supports 31 chars,
- wheareas earlier versions support 63 chars */
-};
-
-/*
- FOBJ desktop resource: describes a folder, or the location of the volume
- icon.
-
- In typical Apple manner, this resource is not documented. However, I have
- managed to reverse engineer some parts of it.
-*/
-struct mfs_FOBJ
-{
- uint8_t unknown0[2]; /* $00: $0004 for disk, $0008 for folder??? */
- mac_point location; /* $02: location in parent window */
- uint8_t unknown1[4]; /* $06: ??? */
- uint8_t view; /* $0A: manner in which folders are displayed??? */
- uint8_t unknown2; /* $0B: ??? */
- UINT16BE par_fldr; /* $0C: parent folder ID */
- uint8_t unknown3[10]; /* $0E: ??? */
- UINT16BE unknown4; /* $18: ??? */
- UINT32BE createDate; /* $1A: date and time of creation */
- UINT32BE modifyDate; /* $1E: date and time of last modification */
- UINT16BE unknown5; /* $22: put-away folder ID?????? */
- uint8_t unknown6[8]; /* $24: ??? */
- mac_rect bounds; /* $2C: window bounds */
- mac_point scroll; /* $34: current scroll offset??? */
- union
- { /* I think there are two versions of the structure */
- struct
- {
- UINT16BE item_count; /* number of items (folders and files) in
- this folder */
- UINT32BE item_descs[1]; /* this variable-length array has
- item_count entries - meaning of entry is unknown */
- } v1;
- struct
- {
- UINT16BE zerofill; /* always 0? */
- UINT16BE unknown0; /* always 0??? */
- UINT16BE item_count; /* number of items (folders and files) in
- this folder */
- uint8_t unknown1[20]; /* ??? */
- uint8_t name[1]; /* variable-length macintosh string */
- } v2;
- } u;
-};
-
-/*
- MFS open dir ref
-*/
-struct mfs_dirref
-{
- struct mac_l2_imgref *l2_img; /* image pointer */
- uint16_t index; /* current file index in the disk directory */
- uint16_t cur_block; /* current block offset in directory file */
- uint16_t cur_offset; /* current byte offset in current block of directory file */
- uint8_t block_buffer[512]; /* buffer with current directory block */
-};
-
-
-
-static imgtoolerr_t mfs_image_create(imgtool::image &image, imgtool::stream::ptr &&dummy, util::option_resolution *opts)
-{
- imgtoolerr_t err;
- uint8_t buffer[512];
- uint32_t heads, tracks, sector_bytes, i;
- uint32_t total_disk_blocks, total_allocation_blocks, allocation_block_size;
- uint32_t free_allocation_blocks;
-
- heads = opts->lookup_int('H');
- tracks = opts->lookup_int('T');
- sector_bytes = opts->lookup_int('L');
-
- get_imgref(image)->l1_img.image = &image;
- get_imgref(image)->l1_img.heads = heads;
-
- if (sector_bytes != 512)
- return IMGTOOLERR_UNEXPECTED;
-
- /* computation */
- allocation_block_size = 1024;
- total_disk_blocks = 0;
- for (i = 0; i < tracks; i++)
- total_disk_blocks += heads * apple35_sectors_per_track(imgtool_floppy(image), i) * sector_bytes / 512;
- total_allocation_blocks = total_disk_blocks / (allocation_block_size / 512);
- free_allocation_blocks = total_allocation_blocks - 3;
-
- /* write master directory block */
- memset(buffer, 0, sizeof(buffer));
- place_integer_be(buffer, 0, 2, 0xd2d7); /* signature */
- place_integer_be(buffer, 2, 4, mac_time_now()); /* creation date */
- place_integer_be(buffer, 6, 4, mac_time_now()); /* last modified date */
- place_integer_be(buffer, 10, 2, 0); /* volume attributes */
- place_integer_be(buffer, 12, 2, 0); /* number of files in directory */
- place_integer_be(buffer, 14, 2, 4); /* first block of directory */
- place_integer_be(buffer, 16, 2, 12); /* length of directory in blocks */
- place_integer_be(buffer, 18, 2, total_allocation_blocks); /* allocation blocks on volume count */
- place_integer_be(buffer, 20, 4, allocation_block_size); /* allocation block size */
- place_integer_be(buffer, 24, 4, 8192); /* default clumping size */
- place_integer_be(buffer, 28, 2, 16); /* first allocation block on volume */
- place_integer_be(buffer, 30, 4, 2); /* next unused catalog node */
- place_integer_be(buffer, 34, 2, free_allocation_blocks); /* free allocation block count */
- pascal_from_c_string(&buffer[36], 28, "Untitled"); /* volume title */
-
- err = image_write_block(&get_imgref(image)->l1_img, 2, buffer);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*
- mfs_image_open
-
- Open a MFS image. Image must already be open on level 1. This function
- should not be called directly: call mac_image_open() instead.
-
- l2_img (I/O): level-2 image reference to open (l1_img and format fields
- must be initialized)
- img_open_buf (I): buffer with the MDB block
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_image_open(imgtool::image &image, imgtool::stream::ptr &&dummy)
-{
- imgtoolerr_t err;
- struct mac_l2_imgref *l2_img;
- img_open_buf buf_local;
- img_open_buf *buf;
-
- l2_img = get_imgref(image);
- l2_img->l1_img.image = &image;
- l2_img->l1_img.heads = 1;
- l2_img->format = L2I_MFS;
-
- /* read MDB */
- err = image_read_block(&l2_img->l1_img, 2, &buf_local.raw);
- if (err)
- return err;
- buf = &buf_local;
-
- /* check signature word */
- if ((buf->mfs_mdb.sigWord[0] != 0xd2) || (buf->mfs_mdb.sigWord[1] != 0xd7)
- || (buf->mfs_mdb.VN[0] > 27))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- l2_img->u.mfs.dir_num_files = get_UINT16BE(buf->mfs_mdb.nmFls);
- l2_img->u.mfs.dir_start = get_UINT16BE(buf->mfs_mdb.dirSt);
- l2_img->u.mfs.dir_blk_len = get_UINT16BE(buf->mfs_mdb.blLn);
-
- l2_img->numABs = get_UINT16BE(buf->mfs_mdb.nmAlBlks);
- if ((get_UINT32BE(buf->mfs_mdb.alBlkSiz) % 512) || (get_UINT32BE(buf->mfs_mdb.alBlkSiz) == 0))
- return IMGTOOLERR_CORRUPTIMAGE;
- l2_img->blocksperAB = get_UINT32BE(buf->mfs_mdb.alBlkSiz) / 512;
- l2_img->u.mfs.ABStart = get_UINT16BE(buf->mfs_mdb.alBlSt);
-
- l2_img->nxtCNID = get_UINT32BE(buf->mfs_mdb.nxtFNum);
-
- l2_img->freeABs = get_UINT16BE(buf->mfs_mdb.freeABs);
-
- mac_strcpy(l2_img->u.mfs.volname, buf->mfs_mdb.VN);
-
- if (l2_img->numABs > 4094)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* extract link array */
- {
- int byte_len = l2_img->numABs + ((l2_img->numABs + 1) >> 1);
- int cur_byte;
- int cur_block;
- int block_len = sizeof(buf->mfs_mdb.ABlink);
-
- /* clear dirty flags */
- for (cur_block=0; cur_block<13; cur_block++)
- l2_img->u.mfs.ABlink_dirty[cur_block] = 0;
-
- /* append the chunk after MDB to link array */
- cur_byte = 0;
- if (block_len > (byte_len - cur_byte))
- block_len = byte_len - cur_byte;
- memcpy(l2_img->u.mfs.ABlink+cur_byte, buf->mfs_mdb.ABlink, block_len);
- cur_byte += block_len;
- cur_block = 2;
- while (cur_byte < byte_len)
- {
- /* read next block */
- cur_block++;
- err = image_read_block(&l2_img->l1_img, cur_block, buf->raw);
- if (err)
- return err;
- block_len = 512;
-
- /* append this block to link array */
- if (block_len > (byte_len - cur_byte))
- block_len = byte_len - cur_byte;
- memcpy(l2_img->u.mfs.ABlink+cur_byte, buf->raw, block_len);
- cur_byte += block_len;
- }
- /* check that link array and directory don't overlap */
- if (cur_block >= l2_img->u.mfs.dir_start)
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_update_mdb
-
- Update MDB on disk
-
- l2_img (I/O): level-2 image reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_update_mdb(struct mac_l2_imgref *l2_img)
-{
- imgtoolerr_t err;
- union
- {
- struct mfs_mdb mfs_mdb;
- uint8_t raw[512];
- } buf;
-
- assert(l2_img->format == L2I_MFS);
-
- /* read MDB */
- err = image_read_block(&l2_img->l1_img, 2, &buf.mfs_mdb);
- if (err)
- return err;
-
- set_UINT16BE(&buf.mfs_mdb.nmFls, l2_img->u.mfs.dir_num_files);
-#if 0 /* these fields are never changed */
- set_UINT16BE(&buf.mfs_mdb.dirSt, l2_img->u.mfs.dir_start);
- set_UINT16BE(&buf.mfs_mdb.blLn, l2_img->u.mfs.dir_blk_len);
-
- set_UINT16BE(&buf.mfs_mdb.nmAlBlks, l2_img->numABs);
- set_UINT32BE(&buf.mfs_mdb.alBlkSiz, l2_img->blocksperAB*512);
- set_UINT16BE(&buf.mfs_mdb.alBlSt, l2_img->u.mfs.ABStart);
-#endif
-
- set_UINT32BE(&buf.mfs_mdb.nxtFNum, l2_img->nxtCNID);
-
- set_UINT16BE(&buf.mfs_mdb.freeABs, l2_img->freeABs);
-
-#if 0 /* these fields are never changed */
- mac_strcpy(buf.mfs_mdb.VN, l2_img->u.mfs.volname);
-#endif
-
- /* save link array */
- {
- int byte_len = l2_img->numABs + ((l2_img->numABs + 1) >> 1);
- int cur_byte = 0;
- int cur_block = 2;
- int block_len = sizeof(buf.mfs_mdb.ABlink);
-
- /* update the chunk of link array after the MDB */
- if (block_len > (byte_len - cur_byte))
- block_len = byte_len - cur_byte;
- memcpy(buf.mfs_mdb.ABlink, l2_img->u.mfs.ABlink+cur_byte, block_len);
- cur_byte += block_len;
-
- if (block_len < sizeof(buf.mfs_mdb.ABlink))
- memset(buf.mfs_mdb.ABlink+block_len, 0, sizeof(buf.mfs_mdb.ABlink)-block_len);
-
- l2_img->u.mfs.ABlink_dirty[0] = 0;
-
- /* write back modified MDB+link */
- err = image_write_block(&l2_img->l1_img, 2, &buf.mfs_mdb);
- if (err)
- return err;
-
- while (cur_byte < byte_len)
- {
- /* advance to next block */
- cur_block++;
- block_len = 512;
-
- /* extract the current chunk of link array */
- if (block_len > (byte_len - cur_byte))
- block_len = byte_len - cur_byte;
-
- if (l2_img->u.mfs.ABlink_dirty[cur_block-2])
- {
- memcpy(buf.raw, l2_img->u.mfs.ABlink+cur_byte, block_len);
- if (block_len < 512)
- memset(buf.raw+block_len, 0, 512-block_len);
- /* write back link array */
- err = image_write_block(&l2_img->l1_img, cur_block, buf.raw);
- if (err)
- return err;
- l2_img->u.mfs.ABlink_dirty[cur_block-2] = 0;
- }
-
- cur_byte += block_len;
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_dir_open
-
- Open the directory file
-
- l2_img (I/O): level-2 image reference
- dirref (O): open directory file reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_dir_open(struct mac_l2_imgref *l2_img, const char *path, mfs_dirref *dirref)
-{
- imgtoolerr_t err;
-
- assert(l2_img->format == L2I_MFS);
-
- if (path[0])
- return IMGTOOLERR_PATHNOTFOUND;
-
- dirref->l2_img = l2_img;
- dirref->index = 0;
-
- dirref->cur_block = 0;
- dirref->cur_offset = 0;
- err = image_read_block(&l2_img->l1_img, l2_img->u.mfs.dir_start + dirref->cur_block, dirref->block_buffer);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_dir_read
-
- Read one entry of directory file
-
- dirref (I/O): open directory file reference
- dir_entry (O): set to point to the entry read: set to NULL if EOF or error
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_dir_read(mfs_dirref *dirref, mfs_dir_entry **dir_entry)
-{
- mfs_dir_entry *cur_dir_entry;
- size_t cur_dir_entry_len;
- imgtoolerr_t err;
-
-
- if (dir_entry)
- *dir_entry = NULL;
-
- if (dirref->index == dirref->l2_img->u.mfs.dir_num_files)
- /* EOF */
- return IMGTOOLERR_SUCCESS;
-
- /* get cat entry pointer */
- cur_dir_entry = (mfs_dir_entry *) (dirref->block_buffer + dirref->cur_offset);
- while ((dirref->cur_offset == 512) || ! (cur_dir_entry->flags & 0x80))
- {
- dirref->cur_block++;
- dirref->cur_offset = 0;
- if (dirref->cur_block > dirref->l2_img->u.mfs.dir_blk_len)
- /* aargh! */
- return IMGTOOLERR_CORRUPTIMAGE;
- err = image_read_block(&dirref->l2_img->l1_img, dirref->l2_img->u.mfs.dir_start + dirref->cur_block, dirref->block_buffer);
- if (err)
- return err;
- cur_dir_entry = (mfs_dir_entry *) (dirref->block_buffer + dirref->cur_offset);
- }
-
- cur_dir_entry_len = offsetof(mfs_dir_entry, name) + cur_dir_entry->name[0] + 1;
-
- if ((dirref->cur_offset + cur_dir_entry_len) > 512)
- /* aargh! */
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* entry looks valid: set pointer to entry */
- if (dir_entry)
- *dir_entry = cur_dir_entry;
-
- /* update offset in block */
- dirref->cur_offset += cur_dir_entry_len;
- /* align to word boundary */
- dirref->cur_offset = (dirref->cur_offset + 1) & ~1;
-
- /* update file count */
- dirref->index++;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_dir_insert
-
- Add an entry in the directory file
-
- l2_img (I/O): level-2 image reference
- dirref (I/O): open directory file reference
- filename (I): name of the file for which an entry is created (Mac string)
- dir_entry (O): set to point to the created entry: set to NULL if EOF or
- error
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_dir_insert(struct mac_l2_imgref *l2_img, mfs_dirref *dirref, const uint8_t *new_fname, mfs_dir_entry **dir_entry)
-{
- size_t new_dir_entry_len;
- mfs_dir_entry *cur_dir_entry;
- size_t cur_dir_entry_len;
- uint32_t cur_date;
- imgtoolerr_t err;
-
- dirref->l2_img = l2_img;
- dirref->index = 0;
-
- new_dir_entry_len = offsetof(mfs_dir_entry, name) + new_fname[0] + 1;
-
- for (dirref->cur_block = 0; dirref->cur_block < dirref->l2_img->u.mfs.dir_blk_len; dirref->cur_block++)
- {
- /* read current block */
- err = image_read_block(&dirref->l2_img->l1_img, dirref->l2_img->u.mfs.dir_start + dirref->cur_block, dirref->block_buffer);
- if (err)
- return err;
-
- /* get free chunk in this block */
- dirref->cur_offset = 0;
- cur_dir_entry = (mfs_dir_entry *) (dirref->block_buffer + dirref->cur_offset);
- while ((dirref->cur_offset < 512) && (cur_dir_entry->flags & 0x80))
- { /* skip cur_dir_entry */
- cur_dir_entry_len = offsetof(mfs_dir_entry, name) + cur_dir_entry->name[0] + 1;
- /* update offset in block */
- dirref->cur_offset += cur_dir_entry_len;
- /* align to word boundary */
- dirref->cur_offset = (dirref->cur_offset + 1) & ~1;
- /* update entry pointer */
- cur_dir_entry = (mfs_dir_entry *) (dirref->block_buffer + dirref->cur_offset);
- /* update file index (useless, but can't harm) */
- dirref->index++;
- }
-
- if (new_dir_entry_len <= (/*512*/510 - dirref->cur_offset))
- {
- /*memcpy(cur_dir_entry, new_dir_entry, new_dir_entry_len);*/
- cur_dir_entry->flags = 0x80;
- cur_dir_entry->flVersNum = 0x00;
- memset(&cur_dir_entry->flFinderInfo, 0, sizeof(cur_dir_entry->flFinderInfo));
- set_UINT32BE(&cur_dir_entry->fileID, dirref->l2_img->nxtCNID++);
- set_UINT16BE(&cur_dir_entry->dataStartBlock, 1);
- set_UINT32BE(&cur_dir_entry->dataLogicalSize, 0);
- set_UINT32BE(&cur_dir_entry->dataPhysicalSize, 0);
- set_UINT16BE(&cur_dir_entry->rsrcStartBlock, 1);
- set_UINT32BE(&cur_dir_entry->rsrcLogicalSize, 0);
- set_UINT32BE(&cur_dir_entry->rsrcPhysicalSize, 0);
- cur_date = mac_time_now();
- set_UINT32BE(&cur_dir_entry->createDate, cur_date);
- set_UINT32BE(&cur_dir_entry->modifyDate, cur_date);
- mac_strcpy(cur_dir_entry->name, new_fname);
-
- /* update offset in block */
- dirref->cur_offset += new_dir_entry_len;
- /* align to word boundary */
- dirref->cur_offset = (dirref->cur_offset + 1) & ~1;
- if (dirref->cur_offset < 512)
- /* mark remaining space as free record */
- dirref->block_buffer[dirref->cur_offset] = 0;
- /* write back directory */
- err = image_write_block(&dirref->l2_img->l1_img, dirref->l2_img->u.mfs.dir_start + dirref->cur_block, dirref->block_buffer);
- if (err)
- return err;
- /* update file count */
- dirref->l2_img->u.mfs.dir_num_files++;
-
- /* update MDB (nxtCNID & dir_num_files fields) */
- err = mfs_update_mdb(dirref->l2_img);
- if (err)
- return err;
-
- if (dir_entry)
- *dir_entry = cur_dir_entry;
- return IMGTOOLERR_SUCCESS;
- }
- }
-
- return IMGTOOLERR_NOSPACE;
-}
-
-/*
- mfs_dir_update
-
- Update one entry of directory file
-
- fileref (I/O): open file reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_dir_update(struct mac_fileref *fileref)
-{
- uint16_t cur_block;
- uint16_t cur_offset;
- uint8_t block_buffer[512];
- mfs_dir_entry *cur_dir_entry;
- size_t cur_dir_entry_len;
- imgtoolerr_t err;
-
- for (cur_block = 0; cur_block < fileref->l2_img->u.mfs.dir_blk_len; cur_block++)
- {
- /* read current block */
- err = image_read_block(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.dir_start + cur_block, block_buffer);
- if (err)
- return err;
-
- /* get free chunk in this block */
- cur_offset = 0;
- cur_dir_entry = (mfs_dir_entry *) (block_buffer + cur_offset);
- while ((cur_offset < 512) && (cur_dir_entry->flags & 0x80))
- {
- if (get_UINT32BE(cur_dir_entry->fileID) == fileref->fileID)
- { /* found it: update directory entry */
- switch (fileref->forkType)
- {
- case data_fork:
- set_UINT16BE(&cur_dir_entry->dataStartBlock, fileref->mfs.stBlk);
- set_UINT32BE(&cur_dir_entry->dataLogicalSize, fileref->eof);
- set_UINT32BE(&cur_dir_entry->dataPhysicalSize, fileref->pLen);
- break;
-
- case rsrc_fork:
- set_UINT16BE(&cur_dir_entry->rsrcStartBlock, fileref->mfs.stBlk);
- set_UINT32BE(&cur_dir_entry->rsrcLogicalSize, fileref->eof);
- set_UINT32BE(&cur_dir_entry->rsrcPhysicalSize, fileref->pLen);
- break;
- }
- /* write back directory */
- err = image_write_block(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.dir_start + cur_block, block_buffer);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
- }
- /* skip cur_dir_entry */
- cur_dir_entry_len = offsetof(mfs_dir_entry, name) + cur_dir_entry->name[0] + 1;
- /* update offset in block */
- cur_offset += cur_dir_entry_len;
- /* align to word boundary */
- cur_offset = (cur_offset + 1) & ~1;
- /* update entry pointer */
- cur_dir_entry = (mfs_dir_entry *) (block_buffer + cur_offset);
- }
- }
-
- return IMGTOOLERR_UNEXPECTED;
-}
-
-
-/*
- mfs_find_dir_entry
-
- Find a file in an MFS directory
-
- dirref (I/O): open directory file reference
- filename (I): file name (Mac string)
- dir_entry (O): set to point to the entry read: set to NULL if EOF or error
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_find_dir_entry(mfs_dirref *dirref, const mac_str255 filename, mfs_dir_entry **dir_entry)
-{
- mfs_dir_entry *cur_dir_entry;
- imgtoolerr_t err;
-
- if (dir_entry)
- *dir_entry = NULL;
-
- /* scan dir for file */
- while (1)
- {
- err = mfs_dir_read(dirref, &cur_dir_entry);
- if (err)
- return err;
- if (!cur_dir_entry)
- /* EOF */
- break;
- if ((! mac_stricmp(filename, cur_dir_entry->name)) && (cur_dir_entry->flVersNum == 0))
- { /* file found */
-
- if (dir_entry)
- *dir_entry = cur_dir_entry;
-
- return IMGTOOLERR_SUCCESS;
- }
- }
-
- return IMGTOOLERR_FILENOTFOUND;
-}
-
-/*
- mfs_lookup_path
-
- Resolve a file path for MFS volumes. This function should not be called
- directly: call mac_lookup_path instead.
-
- l2_img (I/O): level-2 image reference
- fpath (I): file path (C string)
- filename (O): set to the actual name of the file, with capitalization matching
- the one on the volume rather than the one in the fpath parameter (Mac
- string)
- cat_info (I/O): on output, catalog info for this file extracted from the
- catalog file (may be NULL)
- If create_it is true, created info will first be set according to the
- data from cat_info
- create_it (I): true if entry should be created if not found
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, mac_str255 filename, mac_dirent *cat_info, int create_it)
-{
- mfs_dirref dirref;
- mfs_dir_entry *dir_entry;
- imgtoolerr_t err;
-
- /* rapid check */
- if (strchr(fpath, ':'))
- return IMGTOOLERR_BADFILENAME;
-
- /* extract file name */
- c_to_mac_strncpy(filename, fpath, strlen(fpath));
-
- /* open dir */
- mfs_dir_open(l2_img, "", &dirref);
-
- /* find file */
- err = mfs_find_dir_entry(&dirref, filename, &dir_entry);
- if ((err == IMGTOOLERR_FILENOTFOUND) && create_it)
- err = mfs_dir_insert(l2_img, &dirref, filename, &dir_entry);
- if (err)
- return err;
-
- mac_strcpy(filename, dir_entry->name);
-
- if (create_it && cat_info)
- {
- dir_entry->flFinderInfo = cat_info->flFinderInfo;
- dir_entry->flags = (dir_entry->flags & 0x80) | (cat_info->flags & 0x7f);
- set_UINT32BE(&dir_entry->createDate, cat_info->createDate);
- set_UINT32BE(&dir_entry->modifyDate, cat_info->modifyDate);
-
- /* write current directory block */
- err = image_write_block(&l2_img->l1_img, l2_img->u.mfs.dir_start + dirref.cur_block, dirref.block_buffer);
- if (err)
- return err;
- }
-
- if (cat_info)
- {
- cat_info->flFinderInfo = dir_entry->flFinderInfo;
- memset(&cat_info->flXFinderInfo, 0, sizeof(cat_info->flXFinderInfo));
- cat_info->flags = dir_entry->flags;
- cat_info->fileID = get_UINT32BE(dir_entry->fileID);
- cat_info->dataLogicalSize = get_UINT32BE(dir_entry->dataLogicalSize);
- cat_info->dataPhysicalSize = get_UINT32BE(dir_entry->dataPhysicalSize);
- cat_info->rsrcLogicalSize = get_UINT32BE(dir_entry->rsrcLogicalSize);
- cat_info->rsrcPhysicalSize = get_UINT32BE(dir_entry->rsrcPhysicalSize);
- cat_info->createDate = get_UINT32BE(dir_entry->createDate);
- cat_info->modifyDate = get_UINT32BE(dir_entry->modifyDate);
- cat_info->dataRecType = 0x200; /* hcrt_File */
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_file_open_internal
-
- Open a file fork, given its directory entry. This function should not be
- called directly: call mfs_file_open instead.
-
- l2_img (I/O): level-2 image reference
- dir_entry (I): directory entry for the file to open
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_open_internal(struct mac_l2_imgref *l2_img, const mfs_dir_entry *dir_entry, mac_forkID fork, struct mac_fileref *fileref)
-{
- assert(l2_img->format == L2I_MFS);
-
- fileref->l2_img = l2_img;
-
- fileref->fileID = get_UINT32BE(dir_entry->fileID);
- fileref->forkType = fork;
-
- switch (fork)
- {
- case data_fork:
- fileref->mfs.stBlk = get_UINT16BE(dir_entry->dataStartBlock);
- fileref->eof = get_UINT32BE(dir_entry->dataLogicalSize);
- fileref->pLen = get_UINT32BE(dir_entry->dataPhysicalSize);
- break;
-
- case rsrc_fork:
- fileref->mfs.stBlk = get_UINT16BE(dir_entry->rsrcStartBlock);
- fileref->eof = get_UINT32BE(dir_entry->rsrcLogicalSize);
- fileref->pLen = get_UINT32BE(dir_entry->rsrcPhysicalSize);
- break;
- }
-
- fileref->crPs = 0;
-
- fileref->reload_buf = true;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_file_open
-
- Open a file located on a MFS volume. This function should not be called
- directly: call mac_file_open instead.
-
- l2_img (I/O): level-2 image reference
- filename (I): name of the file (Mac string)
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_open(struct mac_l2_imgref *l2_img, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref)
-{
- mfs_dirref dirref;
- mfs_dir_entry *dir_entry;
- imgtoolerr_t err;
-
- /* open dir */
- mfs_dir_open(l2_img, "", &dirref);
-
- /* find file */
- err = mfs_find_dir_entry(&dirref, filename, &dir_entry);
- if (err)
- return err;
-
- /* open it */
- return mfs_file_open_internal(l2_img, dir_entry, fork, fileref);
-}
-
-/*
- mfs_get_ABlink
-
- Read one entry of the Allocation Bitmap link array, on an MFS volume.
-
- l2_img (I/O): level-2 image reference
- AB_address (I): index in the array, which is an AB address
-
- Returns the 12-bit value read in array.
-*/
-static uint16_t mfs_get_ABlink(struct mac_l2_imgref *l2_img, uint16_t AB_address)
-{
- uint16_t reply;
- int base;
-
- assert(l2_img->format == L2I_MFS);
-
- base = (AB_address >> 1) * 3;
-
- if (! (AB_address & 1))
- reply = (l2_img->u.mfs.ABlink[base] << 4) | ((l2_img->u.mfs.ABlink[base+1] >> 4) & 0x0f);
- else
- reply = ((l2_img->u.mfs.ABlink[base+1] << 8) & 0xf00) | l2_img->u.mfs.ABlink[base+2];
-
- return reply;
-}
-
-/*
- mfs_set_ABlink
-
- Set one entry of the Allocation Bitmap link array, on an MFS volume.
-
- l2_img (I/O): level-2 image reference
- AB_address (I): index in the array, which is an AB address
- data (I): 12-bit value to write in array
-*/
-static void mfs_set_ABlink(struct mac_l2_imgref *l2_img, uint16_t AB_address, uint16_t data)
-{
- int base;
-
- assert(l2_img->format == L2I_MFS);
-
- base = (AB_address >> 1) * 3;
-
- if (! (AB_address & 1))
- {
- l2_img->u.mfs.ABlink[base] = (data >> 4) & 0xff;
- l2_img->u.mfs.ABlink[base+1] = (l2_img->u.mfs.ABlink[base+1] & 0x0f) | ((data << 4) & 0xf0);
-
- l2_img->u.mfs.ABlink_dirty[(base+64)/512] = 1;
- l2_img->u.mfs.ABlink_dirty[(base+1+64)/512] = 1;
- }
- else
- {
- l2_img->u.mfs.ABlink[base+1] = (l2_img->u.mfs.ABlink[base+1] & 0xf0) | ((data >> 8) & 0x0f);
- l2_img->u.mfs.ABlink[base+2] = data & 0xff;
-
- l2_img->u.mfs.ABlink_dirty[(base+1+64)/512] = 1;
- l2_img->u.mfs.ABlink_dirty[(base+2+64)/512] = 1;
- }
-}
-
-/*
- mfs_file_get_nth_block_address
-
- Get the disk block address of a given block in an open file on a MFS image.
- Called by macintosh file code.
-
- fileref (I/O): open mac file reference
- block_num (I): file block index
- block_address (O): disk block address for the file block
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_get_nth_block_address(struct mac_fileref *fileref, uint32_t block_num, uint32_t *block_address)
-{
- uint32_t AB_num;
- uint32_t i;
- uint16_t AB_address;
-
- assert(fileref->l2_img->format == L2I_MFS);
-
- AB_num = block_num / fileref->l2_img->blocksperAB;
-
- AB_address = fileref->mfs.stBlk;
- if ((AB_address == 0) || (AB_address >= fileref->l2_img->numABs+2))
- /* 0 -> ??? */
- return IMGTOOLERR_CORRUPTIMAGE;
- if (AB_address == 1)
- /* EOF */
- return IMGTOOLERR_UNEXPECTED;
- AB_address -= 2;
- for (i=0; i<AB_num; i++)
- {
- AB_address = mfs_get_ABlink(fileref->l2_img, AB_address);
- if ((AB_address == 0) || (AB_address >= fileref->l2_img->numABs+2))
- /* 0 -> empty block: there is no way an empty block could make it
- into the link chain!!! */
- return IMGTOOLERR_CORRUPTIMAGE;
- if (AB_address == 1)
- /* EOF */
- return IMGTOOLERR_UNEXPECTED;
- AB_address -= 2;
- }
-
- *block_address = fileref->l2_img->u.mfs.ABStart + AB_address * fileref->l2_img->blocksperAB
- + block_num % fileref->l2_img->blocksperAB;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_file_allocABs
-
- Allocate a chunk of ABs
-
- fileref (I/O): open mac file reference
- lastAB (I): AB address on disk of last file AB (only if
- fileref->mfs.stBlk != 1)
- allocABs (I): number of ABs to allocate in addition to the current file
- allocation
- fblock (I): first file block to allocate (used for tag data)
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_allocABs(struct mac_fileref *fileref, uint16_t lastAB, uint32_t allocABs, uint32_t fblock)
-{
- int numABs = fileref->l2_img->numABs;
- int free_ABs;
- int i, j;
- floppy_tag_record tag;
- int extentBaseAB, extentABlen;
- int firstBestExtentBaseAB = 0, firstBestExtentABlen;
- int secondBestExtentBaseAB = 0, secondBestExtentABlen;
- imgtoolerr_t err;
-
- /* return if done */
- if (! allocABs)
- return IMGTOOLERR_SUCCESS;
-
- /* compute free space */
- free_ABs = 0;
- for (i=0; i<numABs; i++)
- {
- if (mfs_get_ABlink(fileref->l2_img, i) == 0)
- {
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + i * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if (get_UINT32BE(tag.fileID) != 0)
- {
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- goto corrupt_free_block;
- }
- }
- }
- }
-
- free_ABs++;
- }
-corrupt_free_block:
- ;
- }
-
- /* check we have enough free space */
- if (free_ABs < allocABs)
- return IMGTOOLERR_NOSPACE;
-
- if (fileref->mfs.stBlk != 1)
- { /* try to extend last file extent */
- /* append free ABs after last AB */
- for (i=lastAB+1; (mfs_get_ABlink(fileref->l2_img, i) == 0) && (allocABs > 0) && (i < numABs); i++)
- {
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + i * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if (get_UINT32BE(tag.fileID) != 0)
- {
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- goto corrupt_free_block2;
- }
- }
- }
- }
-
- mfs_set_ABlink(fileref->l2_img, lastAB, i+2);
- lastAB = i;
- allocABs--;
- free_ABs--;
- }
-corrupt_free_block2:
- /* return if done */
- if (! allocABs)
- {
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- fileref->l2_img->freeABs = free_ABs;
- return IMGTOOLERR_SUCCESS; /* done */
- }
- }
-
- while (allocABs)
- {
- /* find smallest data block at least nb_alloc_physrecs in length, and largest data block less than nb_alloc_physrecs in length */
- firstBestExtentABlen = INT_MAX;
- secondBestExtentABlen = 0;
- for (i=0; i<numABs; i++)
- {
- if (mfs_get_ABlink(fileref->l2_img, i) == 0)
- { /* found one free block */
- /* compute its length */
- extentBaseAB = i;
- extentABlen = 0;
- while ((i<numABs) && (mfs_get_ABlink(fileref->l2_img, i) == 0))
- {
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + i * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if (get_UINT32BE(tag.fileID) != 0)
- {
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- goto corrupt_free_block3;
- }
- }
- }
- }
-
- extentABlen++;
- i++;
- }
-corrupt_free_block3:
- /* compare to previous best and second-best blocks */
- if ((extentABlen < firstBestExtentABlen) && (extentABlen >= allocABs))
- {
- firstBestExtentBaseAB = extentBaseAB;
- firstBestExtentABlen = extentABlen;
- if (extentABlen == allocABs)
- /* no need to search further */
- break;
- }
- else if ((extentABlen > secondBestExtentABlen) && (extentABlen < allocABs))
- {
- secondBestExtentBaseAB = extentBaseAB;
- secondBestExtentABlen = extentABlen;
- }
- }
- }
-
- if (firstBestExtentABlen != INT_MAX)
- { /* found one contiguous block which can hold it all */
- extentABlen = allocABs;
- for (i=0; i<allocABs; i++)
- {
- if (fileref->mfs.stBlk != 1)
- mfs_set_ABlink(fileref->l2_img, lastAB, firstBestExtentBaseAB+i+2);
- else
- fileref->mfs.stBlk = firstBestExtentBaseAB+i+2;
- lastAB = firstBestExtentBaseAB+i;
- free_ABs--;
- /* set tag to allocated */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- set_UINT32BE(&tag.fileID, fileref->fileID);
- tag.ftype = 1;
- if ((fileref->forkType) == rsrc_fork)
- tag.ftype |= 2;
- tag.fattr = /*fattr*/ 0; /* ***TODO*** */
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- set_UINT16BE(&tag.fblock, fblock & 0xffff);
- set_UINT32BE(&tag.wrCnt, mac_time_now());
- err = image_write_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + lastAB * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- {
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- fileref->l2_img->freeABs = free_ABs;
- return err;
- }
- fblock++;
- }
- }
- }
- allocABs = 0;
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- fileref->l2_img->freeABs = free_ABs;
- /*return IMGTOOLERR_SUCCESS;*/ /* done */
- }
- else if (secondBestExtentABlen != 0)
- { /* jeez, we need to fragment it. We use the largest smaller block to limit fragmentation. */
- for (i=0; i<secondBestExtentABlen; i++)
- {
- if (fileref->mfs.stBlk != 1)
- mfs_set_ABlink(fileref->l2_img, lastAB, secondBestExtentBaseAB+i+2);
- else
- fileref->mfs.stBlk = secondBestExtentBaseAB+i+2;
- lastAB = secondBestExtentBaseAB+i;
- free_ABs--;
- /* set tag to allocated */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- set_UINT32BE(&tag.fileID, fileref->fileID);
- tag.ftype = 1;
- if ((fileref->forkType) == rsrc_fork)
- tag.ftype |= 2;
- tag.fattr = /*fattr*/ 0; /* ***TODO*** */
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- set_UINT16BE(&tag.fblock, fblock & 0xffff);
- set_UINT32BE(&tag.wrCnt, mac_time_now());
- err = image_write_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + lastAB * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- {
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- fileref->l2_img->freeABs = free_ABs;
- return err;
- }
- fblock++;
- }
- }
- }
- allocABs -= secondBestExtentABlen;
- }
- else
- {
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- return IMGTOOLERR_NOSPACE; /* This should never happen, as we pre-check that there is enough free space */
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_file_setABeof
-
- Set physical file EOF in ABs
-
- fileref (I/O): open mac file reference
- newABeof (I): desired number of allocated ABs for this file
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_setABeof(struct mac_fileref *fileref, uint32_t newABeof)
-{
- uint16_t AB_address = 0;
- uint16_t AB_link;
- int i, j;
- floppy_tag_record tag;
- int MDB_dirty = 0;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
-
- assert(fileref->l2_img->format == L2I_MFS);
-
- /* run through link chain until we reach the old or the new EOF */
- AB_link = fileref->mfs.stBlk;
- if ((AB_link == 0) || (AB_link >= fileref->l2_img->numABs+2))
- /* 0 -> ??? */
- return IMGTOOLERR_CORRUPTIMAGE;
- for (i=0; (i<newABeof) && (AB_link!=1); i++)
- {
- AB_address = AB_link - 2;
- AB_link = mfs_get_ABlink(fileref->l2_img, AB_address);
- if ((AB_link == 0) || (AB_link >= fileref->l2_img->numABs+2))
- /* 0 -> empty block: there is no way an empty block could make it
- into the link chain!!! */
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + AB_address * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if ((get_UINT32BE(tag.fileID) != fileref->fileID)
- || (((tag.ftype & 2) != 0) != (fileref->forkType == rsrc_fork))
- || (get_UINT16BE(tag.fblock) != ((i * fileref->l2_img->blocksperAB + j) & 0xffff)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- }
- }
- }
- }
-
- if (i == newABeof)
- { /* new EOF is shorter than old one */
- /* mark new eof */
- if (i==0)
- fileref->mfs.stBlk = 1;
- else
- {
- mfs_set_ABlink(fileref->l2_img, AB_address, 1);
- MDB_dirty = 1;
- }
-
- /* free all remaining blocks */
- while (AB_link != 1)
- {
- AB_address = AB_link - 2;
- AB_link = mfs_get_ABlink(fileref->l2_img, AB_address);
- if ((AB_link == 0) || (AB_link >= fileref->l2_img->numABs+2))
- { /* 0 -> empty block: there is no way an empty block could make
- it into the link chain!!! */
- if (MDB_dirty)
- { /* update MDB (freeABs field) and ABLink array */
- err = mfs_update_mdb(fileref->l2_img);
- if (err)
- return err;
- }
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + AB_address * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if ((get_UINT32BE(tag.fileID) != fileref->fileID)
- || (((tag.ftype & 2) != 0) != (fileref->forkType == rsrc_fork))
- || (get_UINT16BE(tag.fblock) != ((i * fileref->l2_img->blocksperAB + j) & 0xffff)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- }
- }
- }
-
- mfs_set_ABlink(fileref->l2_img, AB_address, 0);
- fileref->l2_img->freeABs++;
- MDB_dirty = 1;
- /* set tag to free */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- memset(&tag, 0, sizeof(tag));
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_write_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + AB_address * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
- }
- }
- i++;
- }
- }
- else
- { /* new EOF is larger than old one */
- err = mfs_file_allocABs(fileref, AB_address, newABeof - i, i * fileref->l2_img->blocksperAB);
- if (err)
- return err;
- MDB_dirty = 1;
- }
-
- if (MDB_dirty)
- { /* update MDB (freeABs field) and ABLink array */
- err = mfs_update_mdb(fileref->l2_img);
- if (err)
- return err;
- }
-
- fileref->pLen = newABeof * (fileref->l2_img->blocksperAB * 512);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- mfs_hashString
-
- Hash a string: under MFS, this provides the resource ID of the comment
- resource associated with the file whose name is provided (FCMT resource
- type).
-
- Ripped from Apple technote TB06 (converted from 68k ASM to C)
-
- string (I): string to hash
-
- Returns hash value
-*/
-static int mfs_hashString(const mac_str255 string)
-{
- int reply;
- int len;
- int i;
-
- len = string[0];
-
- reply = 0;
- for (i=0; i<len; i++)
- {
- reply ^= string[i+1];
- if (reply & 1)
- reply = ((reply >> 1) & 0x7fff) | ~0x7fff;
- else
- reply = ((reply >> 1) & 0x7fff);
- if (! (reply & 0x8000))
- reply = - reply;
- }
-
- return reply;
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark HFS IMPLEMENTATION
-#endif
-
-/*
- HFS extents B-tree key
-*/
-struct hfs_extentKey
-{
- uint8_t keyLength; /* length of key, excluding this field */
- uint8_t forkType; /* 0 = data fork, FF = resource fork */
- UINT32BE fileID; /* file ID */
- UINT16BE startBlock; /* first file allocation block number in this extent */
-};
-enum
-{
- keyLength_hfs_extentKey = sizeof(hfs_extentKey) - sizeof(uint8_t)
-};
-
-/*
- HFS catalog B-tree key
-*/
-struct hfs_catKey
-{
- uint8_t keyLen; /* key length */
- uint8_t resrv1; /* reserved */
- UINT32BE parID; /* parent directory ID */
- mac_str31 cName; /* catalog node name */
- /* note that in index nodes, it is a mac_str31, but
- in leaf keys it's a variable-length string */
-};
-
-/*
- HFS catalog data record for a folder - 70 bytes
-*/
-struct hfs_catFolderData
-{
- UINT16BE recordType; /* record type */
- UINT16BE flags; /* folder flags */
- UINT16BE valence; /* folder valence */
- UINT32BE folderID; /* folder ID */
- UINT32BE createDate; /* date and time of creation */
- UINT32BE modifyDate; /* date and time of last modification */
- UINT32BE backupDate; /* date and time of last backup */
- mac_DInfo userInfo; /* Finder information */
- mac_DXInfo finderInfo; /* additional Finder information */
- UINT32BE reserved[4]; /* reserved - set to zero */
-};
-
-/*
- HFS catalog data record for a file - 102 bytes
-*/
-struct hfs_catFileData
-{
- UINT16BE recordType; /* record type */
- uint8_t flags; /* file flags */
- uint8_t fileType; /* file type (reserved, always 0?) */
- mac_FInfo userInfo; /* Finder information */
- UINT32BE fileID; /* file ID */
- UINT16BE dataStartBlock; /* not used - set to zero */
- UINT32BE dataLogicalSize; /* logical EOF of data fork */
- UINT32BE dataPhysicalSize; /* physical EOF of data fork */
- UINT16BE rsrcStartBlock; /* not used - set to zero */
- UINT32BE rsrcLogicalSize; /* logical EOF of resource fork */
- UINT32BE rsrcPhysicalSize; /* physical EOF of resource fork */
- UINT32BE createDate; /* date and time of creation */
- UINT32BE modifyDate; /* date and time of last modification */
- UINT32BE backupDate; /* date and time of last backup */
- mac_FXInfo finderInfo; /* additional Finder information */
- UINT16BE clumpSize; /* file clump size (not used) */
- hfs_extent_3 dataExtents; /* first data fork extent record */
- hfs_extent_3 rsrcExtents; /* first resource fork extent record */
- UINT32BE reserved; /* reserved - set to zero */
-};
-
-/*
- HFS catalog data record for a thread - 46 bytes
-
- The key for a thread record features the CNID of the item and an empty
- name, instead of the CNID of the parent and the item name.
-*/
-struct hfs_catThreadData
-{
- UINT16BE recordType; /* record type */
- UINT32BE reserved[2]; /* reserved - set to zero */
- UINT32BE parID; /* parent ID for this catalog node */
- mac_str31 nodeName; /* name of this catalog node */
-};
-
-/*
- union for all types at once
-*/
-union hfs_catData
-{
- UINT16BE dataType;
- hfs_catFolderData folder;
- hfs_catFileData file;
- hfs_catThreadData thread;
-};
-
-/*
- HFS catalog record types
-*/
-enum
-{
- hcrt_Folder = 0x0100, /* Folder record */
- hcrt_File = 0x0200, /* File record */
- hcrt_FolderThread = 0x0300, /* Folder thread record */
- hcrt_FileThread = 0x0400 /* File thread record */
-};
-
-/*
- Catalog file record flags
-
- This is similar to the MFS catalog flag field, but the "thread exists" flag
- (0x02) is specific to HFS/HFS+, whereas the "Record in use" flag (0x80) is
- only used by MFS.
-*/
-enum
-{
- cfrf_fileLocked = 0x01, /* file is locked and cannot be written to */
- cfrf_threadExists = 0x02 /* a file thread record exists for this file */
-};
-
-/*
- BT functions used by HFS functions
-*/
-struct BT_leaf_rec_enumerator
-{
- mac_BTref *BTref;
- uint32_t cur_node;
- int cur_rec;
-};
-
-static imgtoolerr_t BT_open(mac_BTref *BTref, int (*key_compare_func)(const void *key1, const void *key2), int is_extent);
-static void BT_close(mac_BTref *BTref);
-static imgtoolerr_t BT_search_leaf_rec(mac_BTref *BTref, const void *search_key,
- uint32_t *node_ID, int *record_ID,
- void **record_ptr, int *record_len,
- int search_exact_match, int *match_found);
-static imgtoolerr_t BT_get_keyed_record_data(mac_BTref *BTref, void *rec_ptr, int rec_len, void **data_ptr, int *data_len);
-static imgtoolerr_t BT_leaf_rec_enumerator_open(mac_BTref *BTref, BT_leaf_rec_enumerator *enumerator);
-static imgtoolerr_t BT_leaf_rec_enumerator_read(BT_leaf_rec_enumerator *enumerator, void **record_ptr, int *rec_len);
-
-struct hfs_cat_enumerator
-{
- struct mac_l2_imgref *l2_img;
- BT_leaf_rec_enumerator BT_enumerator;
- uint32_t parID;
-};
-
-/*
- hfs_open_extents_file
-
- Open the file extents B-tree file
-
- l2_img (I/O): level-2 image reference
- mdb (I): copy of the MDB block
- fileref (O): mac open file reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_open_extents_file(struct mac_l2_imgref *l2_img, const struct hfs_mdb *mdb, struct mac_fileref *fileref)
-{
- assert(l2_img->format == L2I_HFS);
-
- fileref->l2_img = l2_img;
-
- fileref->fileID = 3;
- fileref->forkType = (mac_forkID)0x00;
-
- fileref->eof = fileref->pLen = get_UINT32BE(mdb->xtFlSize);
- memcpy(fileref->hfs.extents, mdb->xtExtRec, sizeof(hfs_extent_3));
-
- fileref->crPs = 0;
-
- fileref->reload_buf = true;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_open_cat_file
-
- Open the disk catalog B-tree file
-
- l2_img (I/O): level-2 image reference
- mdb (I): copy of the MDB block
- fileref (O): mac open file reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_open_cat_file(struct mac_l2_imgref *l2_img, const struct hfs_mdb *mdb, struct mac_fileref *fileref)
-{
- assert(l2_img->format == L2I_HFS);
-
- fileref->l2_img = l2_img;
-
- fileref->fileID = 4;
- fileref->forkType = (mac_forkID)0x00;
-
- fileref->eof = fileref->pLen = get_UINT32BE(mdb->ctFlSize);
- memcpy(fileref->hfs.extents, mdb->ctExtRec, sizeof(hfs_extent_3));
-
- fileref->crPs = 0;
-
- fileref->reload_buf = true;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_extentKey_compare
-
- key compare function for file extents B-tree
-
- p1 (I): pointer to first key
- p2 (I): pointer to second key
-
- Return a zero the two keys are equal, a negative value if the key pointed
- to by p1 is less than the key pointed to by p2, and a positive value if the
- key pointed to by p1 is greater than the key pointed to by p2.
-*/
-static int hfs_extentKey_compare(const void *p1, const void *p2)
-{
- const hfs_extentKey *key1 = (const hfs_extentKey*)p1;
- const hfs_extentKey *key2 = (const hfs_extentKey*)p2;
-
- /* let's keep it simple for now */
- return memcmp(key1, key2, sizeof(hfs_extentKey));
-}
-
-/*
- hfs_catKey_compare
-
- key compare function for disk catalog B-tree
-
- p1 (I): pointer to first key
- p2 (I): pointer to second key
-
- Return a zero the two keys are equal, a negative value if the key pointed
- to by p1 is less than the key pointed to by p2, and a positive value if the
- key pointed to by p1 is greater than the key pointed to by p2.
-*/
-static int hfs_catKey_compare(const void *p1, const void *p2)
-{
- const hfs_catKey *key1 = (const hfs_catKey *)p1;
- const hfs_catKey *key2 = (const hfs_catKey *)p2;
-
- if (get_UINT32BE(key1->parID) != get_UINT32BE(key2->parID))
- return (get_UINT32BE(key1->parID) < get_UINT32BE(key2->parID)) ? -1 : +1;
-
- return mac_stricmp(key1->cName, key2->cName);
-}
-
-/*
- hfs_image_open
-
- Open a HFS image. Image must already be open on level 1.
-
- l2_img (I/O): level-2 image reference to open (l1_img and format fields
- must be initialized)
- img_open_buf (I): buffer with the MDB block
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_image_open(imgtool::image &image, imgtool::stream::ptr &&stream)
-{
- imgtoolerr_t err;
- struct mac_l2_imgref *l2_img;
- img_open_buf buf_local;
- img_open_buf *buf;
-
- l2_img = get_imgref(image);
- l2_img->l1_img.image = &image;
- l2_img->l1_img.heads = 2;
- l2_img->format = L2I_HFS;
-
- /* read MDB */
- err = image_read_block(&l2_img->l1_img, 2, &buf_local.raw);
- if (err)
- return err;
- buf = &buf_local;
-
- /* check signature word */
- if ((buf->hfs_mdb.sigWord[0] != 0x42) || (buf->hfs_mdb.sigWord[1] != 0x44)
- || (buf->hfs_mdb.VN[0] > 27))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- l2_img->u.hfs.VBM_start = get_UINT16BE(buf->hfs_mdb.VBMSt);
-
- l2_img->numABs = get_UINT16BE(buf->hfs_mdb.nmAlBlks);
- if (get_UINT32BE(buf->hfs_mdb.alBlkSiz) % 512)
- return IMGTOOLERR_CORRUPTIMAGE;
- l2_img->blocksperAB = get_UINT32BE(buf->hfs_mdb.alBlkSiz) / 512;
- l2_img->u.hfs.ABStart = get_UINT16BE(buf->hfs_mdb.alBlSt);
-
- l2_img->nxtCNID = get_UINT32BE(buf->hfs_mdb.nxtCNID);
-
- l2_img->freeABs = get_UINT16BE(buf->hfs_mdb.freeABs);
-
- mac_strcpy(l2_img->u.hfs.volname, buf->hfs_mdb.VN);
-
- /* open extents and catalog BT */
- err = hfs_open_extents_file(l2_img, &buf->hfs_mdb, &l2_img->u.hfs.extents_BT.fileref);
- if (err)
- return err;
- err = BT_open(&l2_img->u.hfs.extents_BT, hfs_extentKey_compare, true);
- if (err)
- return err;
- if ((l2_img->u.hfs.extents_BT.attributes & btha_bigKeysMask)
- /*|| (l2_img->u.hfs.extents_BT.attributes & kBTVariableIndexKeysMask)*/
- || (l2_img->u.hfs.extents_BT.maxKeyLength != 7))
- { /* This is not supported by the HFS format */
- /* Variable Index keys are not supported either, but hopefully it will
- not break this imgtool module if it set (though it would probably break
- a real macintosh) */
- BT_close(&l2_img->u.hfs.extents_BT);
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- err = hfs_open_cat_file(l2_img, &buf->hfs_mdb, &l2_img->u.hfs.cat_BT.fileref);
- if (err)
- {
- BT_close(&l2_img->u.hfs.extents_BT);
- return err;
- }
- err = BT_open(&l2_img->u.hfs.cat_BT, hfs_catKey_compare, false);
- if (err)
- {
- return err;
- }
- if ((l2_img->u.hfs.cat_BT.attributes & btha_bigKeysMask)
- /*|| (l2_img->u.hfs.cat_BT.attributes & kBTVariableIndexKeysMask)*/
- || (l2_img->u.hfs.cat_BT.maxKeyLength != 37))
- { /* This is not supported by the HFS format */
- /* Variable Index keys are not supported either, but hopefully it will
- not break this imgtool module if it set (though it would probably break
- a real macintosh) */
- BT_close(&l2_img->u.hfs.extents_BT);
- BT_close(&l2_img->u.hfs.cat_BT);
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- /* extract volume bitmap */
- {
- int byte_len = (l2_img->numABs + 7) / 8;
- int cur_byte = 0;
- int cur_block = l2_img->u.hfs.VBM_start;
-
- while (cur_byte < byte_len)
- {
- /* read next block */
- err = image_read_block(&l2_img->l1_img, cur_block, buf->raw);
- if (err)
- return err;
- cur_block++;
-
- /* append this block to VBM */
- memcpy(l2_img->u.hfs.VBM+cur_byte, buf->raw, 512);
- cur_byte += 512;
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- hfs_image_close
-
- Close a HFS image.
-
- l2_img (I/O): level-2 image reference
-*/
-static void hfs_image_close(struct mac_l2_imgref *l2_img)
-{
- assert(l2_img->format == L2I_HFS);
-
- BT_close(&l2_img->u.hfs.extents_BT);
- BT_close(&l2_img->u.hfs.cat_BT);
-}
-#endif
-
-/*
- hfs_get_cat_record_data
-
- extract data from a catalog B-tree leaf record
-
- l2_img (I/O): level-2 image reference
- rec_raw (I): pointer to record key and data, as returned by
- BT_node_get_keyed_record
- rec_len (I): total length of record, as returned by
- BT_node_get_keyed_record
- rec_key (O): set to point to record key
- rec_data (O): set to point to record data
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_get_cat_record_data(struct mac_l2_imgref *l2_img, void *rec_raw, int rec_len, hfs_catKey **rec_key, hfs_catData **rec_data)
-{
- hfs_catKey *lrec_key;
- void *rec_data_raw;
- hfs_catData *lrec_data;
- int rec_data_len;
- int min_data_size;
- imgtoolerr_t err;
-
-
- assert(l2_img->format == L2I_HFS);
-
- lrec_key = (hfs_catKey*)rec_raw;
- /* check that key is long enough to hold it all */
- if ((lrec_key->keyLen+1) < (offsetof(hfs_catKey, cName) + lrec_key->cName[0] + 1))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* get pointer to record data */
- err = BT_get_keyed_record_data(&l2_img->u.hfs.cat_BT, rec_raw, rec_len, &rec_data_raw, &rec_data_len);
- if (err)
- return err;
- lrec_data = (hfs_catData*)rec_data_raw;
-
- /* extract record type */
- if (rec_data_len < 2)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* check that the record is large enough for its type */
- switch (get_UINT16BE(lrec_data->dataType))
- {
- case hcrt_Folder:
- min_data_size = sizeof(hfs_catFolderData);
- break;
-
- case hcrt_File:
- min_data_size = sizeof(hfs_catFileData);
- break;
-
- case hcrt_FolderThread:
- case hcrt_FileThread:
- min_data_size = sizeof(hfs_catThreadData);
- break;
-
- default:
- /* records of unknown type can be safely ignored */
- min_data_size = 0;
- break;
- }
-
- if (rec_data_len < min_data_size)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (rec_key)
- *rec_key = lrec_key;
- if (rec_data)
- *rec_data = lrec_data;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_cat_open
-
- Open an enumerator on the disk catalog
-
- l2_img (I/O): level-2 image reference
- enumerator (O): open catalog enumerator reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_cat_open(struct mac_l2_imgref *l2_img, const char *path, hfs_cat_enumerator *enumerator)
-{
- imgtoolerr_t err;
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
-
- assert(l2_img->format == L2I_HFS);
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(l2_img, path, &parID, filename, &cat_info, false);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_Folder)
- return IMGTOOLERR_FILENOTFOUND;
-
- enumerator->l2_img = l2_img;
- enumerator->parID = parID;
-
- return BT_leaf_rec_enumerator_open(&l2_img->u.hfs.cat_BT, &enumerator->BT_enumerator);
-}
-
-/*
- hfs_cat_read
-
- Enumerate the disk catalog
-
- enumerator (I/O): open catalog enumerator reference
- rec_key (O): set to point to record key
- rec_data (O): set to point to record data
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_cat_read(hfs_cat_enumerator *enumerator, hfs_catKey **rec_key, hfs_catData **rec_data)
-{
- void *rec;
- int rec_len = 0;
- imgtoolerr_t err;
-
-
- *rec_key = NULL;
- *rec_data = NULL;
-
- /* read next record */
- err = BT_leaf_rec_enumerator_read(&enumerator->BT_enumerator, &rec, &rec_len);
- if (err)
- return err;
-
- /* check EOList condition */
- if (rec == NULL)
- return IMGTOOLERR_SUCCESS;
-
- /* extract record data */
- err = hfs_get_cat_record_data(enumerator->l2_img, rec, rec_len, rec_key, rec_data);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_cat_search
-
- Search the catalog for a given file
-
- l2_img (I/O): level-2 image reference
- parID (I): CNID of file parent directory
- cName (I): file name
- rec_key (O): set to point to record key
- rec_data (O): set to point to record data
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_cat_search(struct mac_l2_imgref *l2_img, uint32_t parID, const mac_str31 cName, hfs_catKey **rec_key, hfs_catData **rec_data)
-{
- hfs_catKey search_key;
- void *rec;
- int rec_len;
- imgtoolerr_t err;
-
- assert(l2_img->format == L2I_HFS);
-
- if (cName[0] > 31)
- return IMGTOOLERR_UNEXPECTED;
-
- /* generate search key */
- search_key.keyLen = search_key.resrv1 = 0; /* these fields do not matter
- to the compare function, so we
- don't fill them */
- set_UINT32BE(&search_key.parID, parID);
- mac_strcpy(search_key.cName, cName);
-
- /* search key */
- err = BT_search_leaf_rec(&l2_img->u.hfs.cat_BT, &search_key, NULL, NULL, &rec, &rec_len, true, NULL);
- if (err)
- return err;
-
- /* extract record data */
- err = hfs_get_cat_record_data(l2_img, rec, rec_len, rec_key, rec_data);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_lookup_path
-
- Resolve a file path
-
- l2_img (I/O): level-2 image reference
- fpath (I): file path (C string)
- parID (O): set to the CNID of the file parent directory
- filename (O): set to the actual name of the file, with capitalization matching
- the one on the volume rather than the one in the fpath parameter (Mac
- string)
- cat_info (O): catalog info for this file extracted from the catalog file
- (may be NULL)
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, uint32_t *parID, mac_str255 filename, mac_dirent *cat_info)
-{
- const char *element_start;
- int element_len;
- mac_str255 mac_element_name;
- //int level;
- imgtoolerr_t err;
- hfs_catKey *catrec_key = NULL;
- hfs_catData *catrec_data = NULL;
- uint16_t dataRecType = hcrt_Folder;
-
- /* iterate each path element */
- element_start = fpath;
- //level = 0;
- *parID = 2; /* root parID is 2 */
-
- while(*element_start)
- {
- /* find next path element */
- element_len = strlen(element_start);
- /* decode path element name */
- c_to_mac_strncpy(mac_element_name, element_start, element_len);
-
- err = hfs_cat_search(l2_img, *parID, mac_element_name, &catrec_key, &catrec_data);
- if (err)
- return err;
-
- dataRecType = get_UINT16BE(catrec_data->dataType);
-
- /* regular folder/file name */
- if (dataRecType == hcrt_Folder)
- *parID = get_UINT32BE(catrec_data->folder.folderID);
- else if (element_start[element_len + 1])
- return IMGTOOLERR_BADFILENAME;
-
- /* iterate */
- element_start += element_len + 1;
- }
-
- if (catrec_key && (dataRecType == hcrt_File))
- {
- /* save ref */
- *parID = get_UINT32BE(catrec_key->parID);
- mac_strcpy(filename, catrec_key->cName);
- }
-
- if (cat_info)
- {
- if (catrec_data && (dataRecType == hcrt_File))
- {
- cat_info->flFinderInfo = catrec_data->file.userInfo;
- cat_info->flXFinderInfo = catrec_data->file.finderInfo;
- cat_info->flags = catrec_data->file.flags;
- cat_info->fileID = get_UINT32BE(catrec_data->file.fileID);
- cat_info->dataLogicalSize = get_UINT32BE(catrec_data->file.dataLogicalSize);
- cat_info->dataPhysicalSize = get_UINT32BE(catrec_data->file.dataPhysicalSize);
- cat_info->rsrcLogicalSize = get_UINT32BE(catrec_data->file.rsrcLogicalSize);
- cat_info->rsrcPhysicalSize = get_UINT32BE(catrec_data->file.rsrcPhysicalSize);
- cat_info->createDate = get_UINT32BE(catrec_data->file.createDate);
- cat_info->modifyDate = get_UINT32BE(catrec_data->file.modifyDate);
- }
- else
- {
- memset(cat_info, 0, sizeof(*cat_info));
- }
- cat_info->dataRecType = dataRecType;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_file_open_internal
-
- Open a file fork, given its catalog entry. This function should not be
- called directly: call hfs_file_open instead.
-
- l2_img (I/O): level-2 image reference
- file_rec (I): catalog entry for the file to open
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_file_open_internal(struct mac_l2_imgref *l2_img, const hfs_catFileData *file_rec, mac_forkID fork, struct mac_fileref *fileref)
-{
- assert(l2_img->format == L2I_HFS);
-
- fileref->l2_img = l2_img;
-
- fileref->fileID = get_UINT32BE(file_rec->fileID);
- fileref->forkType = fork;
-
- switch (fork)
- {
- case data_fork:
- fileref->eof = get_UINT32BE(file_rec->dataLogicalSize);
- fileref->pLen = get_UINT32BE(file_rec->dataPhysicalSize);
- memcpy(fileref->hfs.extents, file_rec->dataExtents, sizeof(hfs_extent_3));
- break;
-
- case rsrc_fork:
- fileref->eof = get_UINT32BE(file_rec->rsrcLogicalSize);
- fileref->pLen = get_UINT32BE(file_rec->rsrcPhysicalSize);
- memcpy(fileref->hfs.extents, file_rec->rsrcExtents, sizeof(hfs_extent_3));
- break;
- }
-
- fileref->crPs = 0;
-
- fileref->reload_buf = true;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_file_open
-
- Open a file located on a HFS volume. This function should not be called
- directly: call mac_file_open instead.
-
- l2_img (I/O): level-2 image reference
- parID (I): CNID of file parent directory
- filename (I): name of the file (Mac string)
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_file_open(struct mac_l2_imgref *l2_img, uint32_t parID, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref)
-{
- hfs_catKey *catrec_key;
- hfs_catData *catrec_data;
- uint16_t dataRecType;
- imgtoolerr_t err;
-
- /* lookup file in catalog */
- err = hfs_cat_search(l2_img, parID, filename, &catrec_key, &catrec_data);
- if (err)
- return err;
-
- dataRecType = get_UINT16BE(catrec_data->dataType);
-
- /* file expected */
- if (dataRecType != hcrt_File)
- return IMGTOOLERR_BADFILENAME;
-
- fileref->hfs.parID = get_UINT32BE(catrec_key->parID);
- mac_strcpy(fileref->hfs.filename, catrec_key->cName);
-
- /* open it */
- return hfs_file_open_internal(l2_img, &catrec_data->file, fork, fileref);
-}
-
-/*
- hfs_file_get_nth_block_address
-
- Get the disk block address of a given block in an open file on a MFS image.
- Called by macintosh file code.
-
- fileref (I/O): open mac file reference
- block_num (I): file block index
- block_address (O): disk block address for the file block
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_file_get_nth_block_address(struct mac_fileref *fileref, uint32_t block_num, uint32_t *block_address)
-{
- uint32_t AB_num;
- uint32_t cur_AB;
- uint32_t i;
- void *cur_extents_raw;
- hfs_extent *cur_extents;
- int cur_extents_len;
- void *extents_BT_rec;
- int extents_BT_rec_len;
- imgtoolerr_t err;
- uint16_t AB_address;
-
- assert(fileref->l2_img->format == L2I_HFS);
-
- AB_num = block_num / fileref->l2_img->blocksperAB;
- cur_AB = 0;
- cur_extents = fileref->hfs.extents;
-
- /* first look in catalog tree extents */
- for (i=0; i<3; i++)
- {
- if (AB_num < cur_AB+get_UINT16BE(cur_extents[i].numABlks))
- break;
- cur_AB += get_UINT16BE(cur_extents[i].numABlks);
- }
- if (i == 3)
- {
- /* extent not found: read extents record from extents BT */
- hfs_extentKey search_key;
- hfs_extentKey *found_key;
-
- search_key.keyLength = keyLength_hfs_extentKey;
- search_key.forkType = fileref->forkType;
- set_UINT32BE(&search_key.fileID, fileref->fileID);
- set_UINT16BE(&search_key.startBlock, AB_num);
-
- /* search for the record with the largest key lower than or equal to
- search_key. The keys are constructed in such a way that, if a record
- includes AB_num, it is that one. */
- err = BT_search_leaf_rec(&fileref->l2_img->u.hfs.extents_BT, &search_key,
- NULL, NULL, &extents_BT_rec, &extents_BT_rec_len,
- false, NULL);
- if (err)
- return err;
-
- if (extents_BT_rec == NULL)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- found_key = (hfs_extentKey*)extents_BT_rec;
- /* check that this record concerns the correct file */
- if ((found_key->forkType != fileref->forkType)
- || (get_UINT32BE(found_key->fileID) != fileref->fileID))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* extract start AB */
- cur_AB = get_UINT16BE(found_key->startBlock);
- /* get extents pointer */
- err = BT_get_keyed_record_data(&fileref->l2_img->u.hfs.extents_BT, extents_BT_rec, extents_BT_rec_len, &cur_extents_raw, &cur_extents_len);
- if (err)
- return err;
- if (cur_extents_len < 3*sizeof(hfs_extent))
- return IMGTOOLERR_CORRUPTIMAGE;
- cur_extents = (hfs_extent*)cur_extents_raw;
-
- /* pick correct extent in record */
- for (i=0; i<3; i++)
- {
- if (AB_num < cur_AB+get_UINT16BE(cur_extents[i].numABlks))
- break;
- cur_AB += get_UINT16BE(cur_extents[i].numABlks);
- }
- if (i == 3)
- /* extent not found */
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- AB_address = get_UINT16BE(cur_extents[i].stABN) + (AB_num-cur_AB);
-
- if (AB_address >= fileref->l2_img->numABs)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- *block_address = fileref->l2_img->u.hfs.ABStart + AB_address * fileref->l2_img->blocksperAB
- + block_num % fileref->l2_img->blocksperAB;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#if 0
-#pragma mark -
-#pragma mark B-TREE IMPLEMENTATION
-#endif
-
-/*
- B-tree (Balanced search tree) files are used by the HFS and HFS+ file
- systems: the Extents and Catalog files are both B-Tree.
-
- Note that these B-trees are B+-trees: data is only on the leaf level, and
- nodes located on the same level are also linked sequentially, which allows
- fast sequenctial access to the catalog file.
-
- These files are normal files, except for the fact that they are not
- referenced from the catalog but the MDB. They are allocated in fixed-size
- records of 512 bytes (HFS). (HFS+ supports any power of two from 512
- through 32768, and uses a default of 1024 for Extents, and 4096 for both
- Catalog and Attributes.)
-
- Nodes can contain any number of records. The nodes can be of any of four
- types: header node (unique node with b-tree information, pointer to root
- node and start of the node allocation bitmap), map nodes (which are created
- when the node allocation bitmap outgrows the header node), index nodes
- (root and branch node that enable to efficiently search the leaf nodes for
- a specific key value), and leaf nodes (which hold the actual user data
- records with keys and data). The first node is always a header node.
- Other nodes can be of any of the 3 other type, or they can be free.
-*/
-
-/*
- BTNodeHeader
-
- Header of a node record
-*/
-struct BTNodeHeader
-{
- UINT32BE fLink; /* (index of) next node at this level */
- UINT32BE bLink; /* (index of) previous node at this level */
- uint8_t kind; /* kind of node (leaf, index, header, map) */
- uint8_t height; /* zero for header, map; 1 for leaf, 2 through
- treeDepth for index (child is one LESS than
- parent, whatever IM says) */
- UINT16BE numRecords; /* number of records in this node */
- UINT16BE reserved; /* reserved; set to zero */
-};
-
-/*
- Constants for BTNodeHeader kind field
-*/
-enum
-{
- btnk_leafNode = 0xff, /* leaf nodes hold the actual user data records
- with keys and data */
- btnk_indexNode = 0, /* root and branch node that enable to efficiently
- search the leaf nodes for a specific key value */
- btnk_headerNode = 1, /* unique node with b-tree information, pointer to
- root node and start of the node allocation
- bitmap */
- btnk_mapNode = 2 /* map nodes are created when the node allocation
- bitmap outgrows the header node */
-};
-
-/*
- BTHeaderRecord: first record of a B-tree header node (second record is
- unused, and third is node allocation bitmap).
-*/
-struct BTHeaderRecord
-{
- UINT16BE treeDepth; /* maximum height (usually leaf nodes) */
- UINT32BE rootNode; /* node number of root node */
- UINT32BE leafRecords; /* number of leaf records in all leaf nodes */
- UINT32BE firstLeafNode; /* node number of first leaf node */
- UINT32BE lastLeafNode; /* node number of last leaf node */
- UINT16BE nodeSize; /* size of a node, in bytes */
- UINT16BE maxKeyLength; /* maximum length of data (index + leaf) record keys;
- length of all index record keys if
- btha_variableIndexKeysMask attribute flag is not set */
- UINT32BE totalNodes; /* total number of nodes in tree */
- UINT32BE freeNodes; /* number of unused (free) nodes in tree */
-
- UINT16BE reserved1; /* unused */
- UINT32BE clumpSize; /* used in some HFS implementations? (reserved in
- early HFS implementations, and in HFS Plus) */
- uint8_t btreeType; /* reserved - set to 0 */
- uint8_t reserved2; /* reserved */
- UINT32BE attributes; /* persistent attributes about the tree */
- UINT32BE reserved3[16]; /* reserved */
-};
-
-static imgtoolerr_t BT_check(mac_BTref *BTref, int is_extent);
-
-/*
- BT_open
-
- Open a file as a B-tree. The file must be already open as a macintosh
- file.
-
- BTref (I/O): B-tree file handle to open (BTref->fileref must have been
- open previously)
- key_compare_func (I): function that compares two keys
- is_extent (I): true if we are opening the extent B-tree (we want to do
- extra checks in this case because the extent B-Tree may include extent
- records for the extent B-tree itself, and if an extent record for the
- extent B-tree is located in an extent that has not been defined by
- previous extent records, then we can never retreive this extent record)
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_open(mac_BTref *BTref, int (*key_compare_func)(const void *key1, const void *key2), int is_extent)
-{
- imgtoolerr_t err;
- BTNodeHeader node_header;
- BTHeaderRecord header_rec;
-
- /* seek to node 0 */
- err = mac_file_seek(&BTref->fileref, 0);
- if (err)
- return err;
-
- /* read node header */
- err = mac_file_read(&BTref->fileref, sizeof(node_header), &node_header);
- if (err)
- return err;
-
- if ((node_header.kind != btnk_headerNode) || (get_UINT16BE(node_header.numRecords) < 3)
- || (node_header.height != 0))
- return IMGTOOLERR_CORRUPTIMAGE; /* right??? */
-
- /* CHEESY HACK: we assume that the header record immediately follows the
- node header. This is because we need to know the node length to know where
- the record pointers are located, but we need to read the header record to
- know the node length. */
- err = mac_file_read(&BTref->fileref, sizeof(header_rec), &header_rec);
- if (err)
- return err;
-
- BTref->nodeSize = get_UINT16BE(header_rec.nodeSize);
- BTref->rootNode = get_UINT32BE(header_rec.rootNode);
- BTref->firstLeafNode = get_UINT32BE(header_rec.firstLeafNode);
- BTref->attributes = get_UINT32BE(header_rec.attributes);
- BTref->treeDepth = get_UINT16BE(header_rec.treeDepth);
- BTref->maxKeyLength = get_UINT16BE(header_rec.maxKeyLength);
-
- BTref->key_compare_func = key_compare_func;
-
- BTref->node_buf = malloc(BTref->nodeSize);
- if (!BTref->node_buf)
- return IMGTOOLERR_OUTOFMEMORY;
-
- if (BTREE_CHECKS)
- {
- /* optional: check integrity of B-tree */
- err = BT_check(BTref, is_extent);
- if (err)
- return err;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_close
-
- Close a B-tree
-
- BTref (I/O): open B-tree file handle
-*/
-static void BT_close(mac_BTref *BTref)
-{
- free(BTref->node_buf);
-}
-
-/*
- BT_read_node
-
- Read a node from a B-tree
-
- BTref (I/O): open B-tree file handle
- node_ID (I): index of the node to read
- expected_kind (I): kind of the node to read
- expected_depth (I): depth of the node to read
- dest (O): destination buffer
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_read_node(mac_BTref *BTref, uint32_t node_ID, int expected_kind, int expected_depth, void *dest)
-{
- imgtoolerr_t err;
-
- /* seek to node */
- err = mac_file_seek(&BTref->fileref, node_ID*BTref->nodeSize);
- if (err)
- return err;
-
- /* read it */
- err = mac_file_read(&BTref->fileref, BTref->nodeSize, dest);
- if (err)
- return err;
-
- /* check node kind and depth */
- if ((((BTNodeHeader *) dest)->kind != expected_kind)
- || (((BTNodeHeader *) dest)->height != expected_depth))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_node_get_record
-
- Extract a raw record from a B-tree node
-
- BTref (I/O): open B-tree file handle
- node_buf (I): buffer with the node the record should be extracted from
- recnum (I): index of record to read
- rec_ptr (O): set to point to start of record (key + data)
- rec_len (O): set to total length of record (key + data)
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_node_get_record(mac_BTref *BTref, void *node_buf, unsigned recnum, void **rec_ptr, int *rec_len)
-{
- uint16_t node_numRecords = get_UINT16BE(((BTNodeHeader *) node_buf)->numRecords);
- uint16_t offset;
- uint16_t next_offset;
-
- if (recnum >= node_numRecords)
- return IMGTOOLERR_UNEXPECTED;
-
- int recnum_s = (int)recnum;
- offset = get_UINT16BE(((UINT16BE *)((uint8_t *) node_buf + BTref->nodeSize))[-recnum_s - 1]);
- next_offset = get_UINT16BE(((UINT16BE *)((uint8_t *) node_buf + BTref->nodeSize))[-recnum_s - 2]);
-
- if ((offset < sizeof(BTNodeHeader)) || (offset > BTref->nodeSize-2*node_numRecords)
- || (next_offset < sizeof(BTNodeHeader)) || (next_offset > BTref->nodeSize-2*node_numRecords)
- || (offset & 1) || (next_offset & 1)
- || (offset > next_offset))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- *rec_ptr = (uint8_t *)node_buf + offset;
- *rec_len = next_offset - offset;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_node_get_keyed_record
-
- Extract a keyed record from a B-tree node. Equivalent to
- BT_node_get_record, only we do extra checks.
-
- BTref (I/O): open B-tree file handle
- node_buf (I): buffer with the node the record should be extracted from
- node_is_index (I): true if node is index node
- recnum (I): index of record to read
- rec_ptr (O): set to point to start of record (key + data)
- rec_len (O): set to total length of record (key + data)
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_node_get_keyed_record(mac_BTref *BTref, void *node_buf, int node_is_index, unsigned recnum, void **rec_ptr, int *rec_len)
-{
- imgtoolerr_t err;
- void *lrec_ptr;
- int lrec_len;
- int key_len;
-
- /* extract record */
- err = BT_node_get_record(BTref, node_buf, recnum, &lrec_ptr, &lrec_len);
- if (err)
- return err;
-
- /* read key len */
- key_len = (BTref->attributes & btha_bigKeysMask)
- ? get_UINT16BE(* (UINT16BE *)lrec_ptr)
- : (* (uint8_t *)lrec_ptr);
-
- /* check that key fits in record */
- if ((key_len + ((BTref->attributes & btha_bigKeysMask) ? 2 : 1)) > lrec_len)
- /* hurk! */
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (key_len > BTref->maxKeyLength)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (node_is_index && (! (BTref->attributes & btha_variableIndexKeysMask)) && (key_len != BTref->maxKeyLength))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (rec_ptr)
- *rec_ptr = lrec_ptr;
- if (rec_len)
- *rec_len = lrec_len;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_get_keyed_record_data
-
- extract data from a keyed record
-
- BTref (I/O): open B-tree file handle
- rec_ptr (I): point to start of record (key + data)
- rec_len (I): total length of record (key + data)
- data_ptr (O): set to point to record data
- data_len (O): set to length of record data
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_get_keyed_record_data(mac_BTref *BTref, void *rec_ptr, int rec_len, void **data_ptr, int *data_len)
-{
- int lkey_len;
- int data_offset;
-
- /* read key len */
- lkey_len = (BTref->attributes & btha_bigKeysMask)
- ? get_UINT16BE(* (UINT16BE *)rec_ptr)
- : (* (uint8_t *)rec_ptr);
-
- /* compute offset to data record */
- data_offset = lkey_len + ((BTref->attributes & btha_bigKeysMask) ? 2 : 1);
- if (data_offset > rec_len)
- /* hurk! */
- return IMGTOOLERR_CORRUPTIMAGE;
- /* fix alignment */
- if (data_offset & 1)
- data_offset++;
-
- if (data_ptr)
- *data_ptr = (uint8_t *)rec_ptr + data_offset;
- if (data_len)
- *data_len = (rec_len > data_offset) ? rec_len-data_offset : 0;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_check
-
- Check integrity of a complete B-tree
-
- BTref (I/O): open B-tree file handle
- is_extent (I): true if we are opening the extent B-tree (we want to do
- extra checks in this case because the extent B-Tree may include extent
- records for the extent B-tree itself, and if an extent record for the
- extent B-tree is located in an extent that has not been defined by
- previous extent records, then we can never retreive this extent record)
-
- Return imgtool error code
-*/
-struct data_nodes_t
-{
- void *buf;
- uint32_t node_num;
- uint32_t cur_rec;
- uint32_t num_recs;
-};
-static imgtoolerr_t BT_check(mac_BTref *BTref, int is_extent)
-{
- uint16_t node_numRecords;
- BTHeaderRecord *header_rec;
- uint8_t *bitmap;
-
- data_nodes_t *data_nodes;
- int i, j;
- uint32_t cur_node, prev_node;
- void *rec1, *rec2;
- int rec1_len, rec2_len;
- void *rec1_data;
- int rec1_data_len;
- uint32_t totalNodes, lastLeafNode;
- uint32_t freeNodes;
- int compare_result;
- uint32_t map_count, map_len;
- uint32_t run_len;
- uint32_t run_bit_len;
- uint32_t actualFreeNodes;
- imgtoolerr_t err;
- uint32_t maxExtentAB = 0, maxExtentNode = 0, extentEOL = 0; /* if is_extent is true */
-
- if (is_extent)
- {
- switch (BTref->fileref.l2_img->format)
- {
- case L2I_MFS:
- /* MFS does not feature any extents B-tree! */
- return IMGTOOLERR_UNEXPECTED;
-
- case L2I_HFS:
- maxExtentAB = 0;
- for (j=0; j<3; j++)
- maxExtentAB += get_UINT16BE(BTref->fileref.hfs.extents[j].numABlks);
- maxExtentNode = (uint64_t)maxExtentAB * 512 * BTref->fileref.l2_img->blocksperAB
- / BTref->nodeSize;
- extentEOL = false;
- break;
- }
- }
-
- /* read header node */
- if ((! is_extent) || (0 < maxExtentNode))
- err = BT_read_node(BTref, 0, btnk_headerNode, 0, BTref->node_buf);
- else
- err = IMGTOOLERR_CORRUPTIMAGE;
- if (err)
- return err;
-
- /* check we have enough records */
- node_numRecords = get_UINT16BE(((BTNodeHeader *) BTref->node_buf)->numRecords);
- if (node_numRecords < 3)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* get header record */
- err = BT_node_get_record(BTref, BTref->node_buf, 0, &rec1, &rec1_len);
- if (err)
- return err;
- header_rec = (BTHeaderRecord *)rec1;
-
- /* check length of header record */
- if (rec1_len < sizeof(BTHeaderRecord))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- totalNodes = get_UINT32BE(header_rec->totalNodes);
- if (totalNodes == 0)
- /* we need at least one header node */
- return IMGTOOLERR_CORRUPTIMAGE;
- lastLeafNode = get_UINT32BE(header_rec->lastLeafNode);
- freeNodes = get_UINT32BE(header_rec->freeNodes);
-
- /* check file length */
- if ((BTref->nodeSize * totalNodes) > BTref->fileref.pLen)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* initialize for the function postlog ("bail:" tag) */
- err = IMGTOOLERR_SUCCESS;
- bitmap = NULL;
- data_nodes = NULL;
-
- /* alloc buffer for reconstructed bitmap */
- map_len = (totalNodes + 7) / 8;
- bitmap = (uint8_t*)malloc(map_len);
- if (! bitmap)
- return IMGTOOLERR_OUTOFMEMORY;
- memset(bitmap, 0, map_len);
-
- /* check B-tree data nodes (i.e. index and leaf nodes) */
- if (BTref->treeDepth == 0)
- {
- /* B-tree is empty */
- if (BTref->rootNode || BTref->firstLeafNode || lastLeafNode)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto bail;
- }
- }
- else
- {
- /* alloc array of buffers for catalog data nodes */
- data_nodes = (data_nodes_t *)malloc(sizeof(data_nodes_t) * BTref->treeDepth);
- if (! data_nodes)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto bail;
- }
- for (i=0; i<BTref->treeDepth; i++)
- data_nodes[i].buf = NULL; /* required for function postlog to work should next loop fail */
- for (i=0; i<BTref->treeDepth; i++)
- {
- data_nodes[i].buf = malloc(BTref->nodeSize);
- if (!data_nodes[i].buf)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto bail;
- }
- }
-
- /* read first data nodes */
- cur_node = BTref->rootNode;
- for (i=BTref->treeDepth-1; i>=0; i--)
- {
- /* check node index */
- if (cur_node >= totalNodes)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* check that node has not been used for another purpose */
- /* this check is unecessary because the current consistency checks
- that forward and back linking match and that node height is correct
- are enough to detect such errors */
-#if 0
- if (bitmap[cur_node >> 3] & (0x80 >> (cur_node & 7)))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-#endif
- /* add node in bitmap */
- bitmap[cur_node >> 3] |= (0x80 >> (cur_node & 7));
- /* read node */
- if ((! is_extent) || (cur_node < maxExtentNode))
- err = BT_read_node(BTref, cur_node, i ? btnk_indexNode : btnk_leafNode, i+1, data_nodes[i].buf);
- else
- err = IMGTOOLERR_CORRUPTIMAGE;
- if (err)
- goto bail;
- /* check that it is the first node at this level */
- if (get_UINT32BE(((BTNodeHeader *) data_nodes[i].buf)->bLink))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* fill other fields */
- data_nodes[i].node_num = cur_node;
- data_nodes[i].cur_rec = 0;
- data_nodes[i].num_recs = get_UINT16BE(((BTNodeHeader *) data_nodes[i].buf)->numRecords);
- /* check that there is at least one record */
- if (data_nodes[i].num_recs == 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* iterate to next level if applicable */
- if (i != 0)
- {
- /* extract first record */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, true, 0, &rec1, &rec1_len);
- if (err)
- goto bail;
-
- /* extract record data ptr */
- err = BT_get_keyed_record_data(BTref, rec1, rec1_len, &rec1_data, &rec1_data_len);
- if (err)
- goto bail;
- if (rec1_data_len < sizeof(UINT32BE))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* iterate to next level */
- cur_node = get_UINT32BE(* (UINT32BE *)rec1_data);
- }
- }
-
- /* check that a) the root node has no successor, and b) that we have really
- read the first leaf node */
- if (get_UINT32BE(((BTNodeHeader *) data_nodes[BTref->treeDepth-1].buf)->fLink)
- || (cur_node != BTref->firstLeafNode))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* check that keys are ordered correctly */
- while (1)
- {
- /* iterate through parent nodes */
- i = 0;
- while ((i<BTref->treeDepth) && ((data_nodes[i].cur_rec == 0) || (data_nodes[i].cur_rec == data_nodes[i].num_recs)))
- {
- /* read next node if necessary */
- if (data_nodes[i].cur_rec == data_nodes[i].num_recs)
- {
- /* get link to next node */
- cur_node = get_UINT32BE(((BTNodeHeader *) data_nodes[i].buf)->fLink);
- if (cur_node == 0)
- {
- if (i == 0)
- /* normal End of List */
- goto end_of_list;
- else
- {
- /* error */
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- }
- /* add node in bitmap */
- bitmap[cur_node >> 3] |= (0x80 >> (cur_node & 7));
- /* read node */
- if ((! is_extent) || (cur_node < maxExtentNode))
- err = BT_read_node(BTref, cur_node, i ? btnk_indexNode : btnk_leafNode, i+1, data_nodes[i].buf);
- else
- err = IMGTOOLERR_CORRUPTIMAGE;
- if (err)
- goto bail;
- /* check that backward linking match forward linking */
- if (get_UINT32BE(((BTNodeHeader *) data_nodes[i].buf)->bLink) != data_nodes[i].node_num)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* fill other fields */
- data_nodes[i].node_num = cur_node;
- data_nodes[i].cur_rec = 0;
- data_nodes[i].num_recs = get_UINT16BE(((BTNodeHeader *) data_nodes[i].buf)->numRecords);
- /* check that there is at least one record */
- if (data_nodes[i].num_recs == 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* next test is not necessary because we have checked that
- the root node has no successor */
-#if 0
- if (i < BTref->treeDepth-1)
- {
-#endif
- data_nodes[i+1].cur_rec++;
-#if 0
- }
- else
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-#endif
- }
- i++;
- }
-
- if (is_extent && !extentEOL)
- {
- /* extract current leaf record and update maxExtentAB and
- maxExtentNode */
- hfs_extentKey *extentKey;
- hfs_extent *extentData;
-
- /* extract current leaf record */
- err = BT_node_get_keyed_record(BTref, data_nodes[0].buf, false, data_nodes[0].cur_rec, &rec1, &rec1_len);
- if (err)
- goto bail;
-
- extentKey = (hfs_extentKey*)rec1;
- if ((extentKey->keyLength < 7) || (extentKey->forkType != 0) || (get_UINT32BE(extentKey->fileID) != 3)
- || (get_UINT16BE(extentKey->startBlock) != maxExtentAB))
- /* the key is corrupt or does not concern the extent
- B-tree: set the extentEOL flag so that we stop looking for
- further extent records for the extent B-tree */
- extentEOL = true;
- else
- { /* this key concerns the extent B-tree: update maxExtentAB
- and maxExtentNode */
- /* extract record data ptr */
- err = BT_get_keyed_record_data(BTref, rec1, rec1_len, &rec1_data, &rec1_data_len);
- if (err)
- goto bail;
- if (rec1_data_len < sizeof(hfs_extent)*3)
- /* the record is corrupt: set the extentEOL flag so
- that we stop looking for further extent records for the
- extent B-tree */
- extentEOL = true;
- else
- {
- extentData = (hfs_extent*)rec1_data;
-
- for (j=0; j<3; j++)
- maxExtentAB += get_UINT16BE(extentData[j].numABlks);
- maxExtentNode = (uint64_t)maxExtentAB * 512 * BTref->fileref.l2_img->blocksperAB
- / BTref->nodeSize;
- }
- }
- if (extentEOL)
- {
- /* check that the extent B-Tree has been defined entirely */
- if (maxExtentNode < totalNodes)
- { /* no good */
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- }
- }
-
- if (i<BTref->treeDepth)
- {
- /* extract current record */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, i > 0, data_nodes[i].cur_rec, &rec1, &rec1_len);
- if (err)
- goto bail;
-
- /* extract previous record */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, i > 0, data_nodes[i].cur_rec-1, &rec2, &rec2_len);
- if (err)
- goto bail;
-
- /* check that it is sorted correctly */
- compare_result = (*BTref->key_compare_func)(rec1, rec2);
- if (compare_result <= 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- i--;
- }
- else
- {
- i--;
- if (i>0)
- { /* extract first record of root if it is an index node */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, true, data_nodes[i].cur_rec, &rec1, &rec1_len);
- if (err)
- goto bail;
- }
- i--;
- }
-
- while (i>=0)
- {
- /* extract first record of current level */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, i > 0, data_nodes[i].cur_rec, &rec2, &rec2_len);
- if (err)
- goto bail;
-
- /* compare key with key of current record of upper level */
- compare_result = (*BTref->key_compare_func)(rec1, rec2);
- if (compare_result != 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* extract record data ptr */
- err = BT_get_keyed_record_data(BTref, rec1, rec1_len, &rec1_data, &rec1_data_len);
- if (err)
- goto bail;
- if (rec1_data_len < sizeof(UINT32BE))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- cur_node = get_UINT32BE(* (UINT32BE *)rec1_data);
-
- /* compare node index with data of current record of upper
- level */
- if (cur_node != data_nodes[i].node_num)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* iterate to next level */
- rec1 = rec2;
- rec1_len = rec2_len;
- i--;
- }
-
- /* next leaf record */
- data_nodes[0].cur_rec++;
- }
-
-end_of_list:
- /* check that we are at the end of list for each index level */
- for (i=1; i<BTref->treeDepth; i++)
- {
- if ((data_nodes[i].cur_rec != (data_nodes[i].num_recs-1))
- || get_UINT32BE(((BTNodeHeader *) data_nodes[i].buf)->fLink))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- }
- /* check that the last leaf node is what it is expected to be */
- if (data_nodes[0].node_num != lastLeafNode)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- }
-
- /* check map node chain */
- cur_node = 0; /* node 0 is the header node... */
- bitmap[0] |= 0x80;
- /* check back linking */
- if (get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->bLink))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* get pointer to next node */
- cur_node = get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->fLink);
- while (cur_node != 0)
- {
- /* save node address */
- prev_node = cur_node;
- /* check that node has not been used for another purpose */
- /* this check is unecessary because the current consistency checks that
- forward and back linking match and that node height is correct are
- enough to detect such errors */
-#if 0
- if (bitmap[cur_node >> 3] & (0x80 >> (cur_node & 7)))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-#endif
- /* add node in bitmap */
- bitmap[cur_node >> 3] |= (0x80 >> (cur_node & 7));
- /* read map node */
- if ((! is_extent) || (cur_node < maxExtentNode))
- err = BT_read_node(BTref, cur_node, btnk_mapNode, 0, BTref->node_buf);
- else
- err = IMGTOOLERR_CORRUPTIMAGE;
- if (err)
- goto bail;
- /* check back linking */
- if (get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->bLink) != prev_node)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* get pointer to next node */
- cur_node = get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->fLink);
- }
-
- /* re-read header node */
- err = BT_read_node(BTref, 0, btnk_headerNode, 0, BTref->node_buf);
- if (err)
- goto bail;
-
- /* get header bitmap record */
- err = BT_node_get_record(BTref, BTref->node_buf, 2, &rec1, &rec1_len);
- if (err)
- goto bail;
-
- /* check bitmap, iterating map nodes */
- map_count = 0;
- actualFreeNodes = 0;
- while (map_count < map_len)
- {
- /* compute compare len */
- run_len = rec1_len;
- if (run_len > (map_len-map_count))
- run_len = map_len-map_count;
- /* check that all used nodes are marked as such in the B-tree bitmap */
- for (i=0; i<run_len; i++)
- if (bitmap[map_count+i] & ~((uint8_t *)rec1)[i])
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* count free nodes */
- run_bit_len = rec1_len*8;
- if (run_bit_len > (totalNodes-map_count*8))
- run_bit_len = totalNodes-map_count*8;
- for (i=0; i<run_bit_len; i++)
- if (! (((uint8_t *)rec1)[i>>3] & (0x80 >> (i & 7))))
- actualFreeNodes++;
- map_count += run_len;
- /* read next map node if required */
- if (map_count < map_len)
- {
- /* get pointer to next node */
- cur_node = get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->fLink);
- if (cur_node == 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* read map node */
- err = BT_read_node(BTref, cur_node, btnk_mapNode, 0, BTref->node_buf);
- if (err)
- goto bail;
- /* get map record */
- err = BT_node_get_record(BTref, BTref->node_buf, 0, &rec1, &rec1_len);
- if (err)
- goto bail;
- header_rec = (BTHeaderRecord *)rec1;
- }
- }
-
- /* check free node count */
- if (freeNodes != actualFreeNodes)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
-bail:
- /* free buffers */
- if (data_nodes)
- {
- for (i=0; i<BTref->treeDepth; i++)
- if (data_nodes[i].buf)
- free(data_nodes[i].buf);
- free(data_nodes);
- }
- if (bitmap)
- free(bitmap);
-
- return err;
-}
-
-/*
- BT_search_leaf_rec
-
- Search for a given key in a B-Tree. If exact match found, returns
- corresponding leaf record. Otherwise, may return the greatest record less
- than the requested key (of course, this will fail if the key is lower than
- all keys in the B-Tree).
-
- BTref (I/O): open B-tree file handle
- search_key (I): key to search the B-Tree for
- node_ID (O): set to the node ID of the node the record is located in (may
- be NULL)
- record_ID (O): set to the index of the record in the node (may be NULL)
- record_ptr (O): set to point to record in node buffer (may be NULL)
- record_len (O): set to total record len (may be NULL)
- search_exact_match (I): if true, the function will search for a record
- equal to search_key; if false, the function will search for the
- greatest record less than or equal to search_key
- match_found (O): set to true if an exact match for search_key has been
- found (only makes sense if search_exact_match is false) (may be NULL)
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_search_leaf_rec(mac_BTref *BTref, const void *search_key,
- uint32_t *node_ID, int *record_ID,
- void **record_ptr, int *record_len,
- int search_exact_match, int *match_found)
-{
- imgtoolerr_t err;
- int i;
- uint32_t cur_node;
- void *cur_rec;
- int cur_rec_len;
- void *last_rec;
- int last_rec_len = 0;
- void *rec_data;
- int rec_data_len;
- int depth;
- uint16_t node_numRecords;
- int compare_result = 0;
-
- /* start with root node */
- if ((BTref->rootNode == 0) || (BTref->treeDepth == 0))
- /* tree is empty */
- return ((BTref->rootNode == 0) == (BTref->treeDepth == 0))
- ? IMGTOOLERR_FILENOTFOUND
- : IMGTOOLERR_CORRUPTIMAGE;
-
- cur_node = BTref->rootNode;
- depth = BTref->treeDepth;
-
- while (1)
- {
- /* read current node */
- err = BT_read_node(BTref, cur_node, (depth > 1) ? btnk_indexNode : btnk_leafNode, depth, BTref->node_buf);
- if (err)
- return err;
-
- /* search for key */
- node_numRecords = get_UINT16BE(((BTNodeHeader *) BTref->node_buf)->numRecords);
- last_rec = cur_rec = NULL;
- for (i=0; i<node_numRecords; i++)
- {
- err = BT_node_get_keyed_record(BTref, BTref->node_buf, depth > 1, i, &cur_rec, &cur_rec_len);
- if (err)
- return err;
-
- compare_result = (*BTref->key_compare_func)(cur_rec, search_key);
- if (compare_result > 0)
- break;
- last_rec = cur_rec;
- last_rec_len = cur_rec_len;
- if (compare_result == 0)
- break;
- }
-
- if (! last_rec)
- { /* all keys are greater than the search key: the search key is
- nowhere in the tree */
- if (search_exact_match)
- return IMGTOOLERR_FILENOTFOUND;
-
- if (match_found)
- *match_found = false;
-
- if (node_ID)
- *node_ID = 0;
-
- if (record_ID)
- *record_ID = -1;
-
- if (record_ptr)
- *record_ptr = NULL;
-
- return IMGTOOLERR_SUCCESS;
- }
-
- if (((BTNodeHeader *) BTref->node_buf)->kind == btnk_leafNode)
- /* leaf node -> end of search */
- break;
-
- /* extract record data ptr */
- err = BT_get_keyed_record_data(BTref, last_rec, last_rec_len, &rec_data, &rec_data_len);
- if (err)
- return err;
- if (rec_data_len < sizeof(UINT32BE))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* iterate to next level */
- cur_node = get_UINT32BE(* (UINT32BE *)rec_data);
- depth--;
- }
-
- if (compare_result != 0)
- /* key not found */
- if (search_exact_match)
- return IMGTOOLERR_FILENOTFOUND;
-
- if (match_found)
- *match_found = (compare_result == 0);
-
- if (node_ID)
- *node_ID = cur_node;
-
- if (record_ID)
- *record_ID = i;
-
- if (record_ptr)
- *record_ptr = last_rec;
-
- if (record_len)
- *record_len = last_rec_len;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_leaf_rec_enumerator_open
-
- Open enumerator for leaf records of a B-Tree
-
- BTref (I/O): open B-tree file handle
- enumerator (O): B-Tree enumerator to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_leaf_rec_enumerator_open(mac_BTref *BTref, BT_leaf_rec_enumerator *enumerator)
-{
- enumerator->BTref = BTref;
- enumerator->cur_node = BTref->firstLeafNode;
- enumerator->cur_rec = 0;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_leaf_rec_enumerator_read
-
- Read next leaf record of a B-Tree
-
- enumerator (I/O): open B-Tree enumerator
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_leaf_rec_enumerator_read(BT_leaf_rec_enumerator *enumerator, void **record_ptr, int *rec_len)
-{
- uint16_t node_numRecords;
- imgtoolerr_t err;
-
-
- *record_ptr = NULL;
-
- /* check EOList condition */
- if (enumerator->cur_node == 0)
- return IMGTOOLERR_SUCCESS;
-
- /* read current node */
- err = BT_read_node(enumerator->BTref, enumerator->cur_node, btnk_leafNode, 1, enumerator->BTref->node_buf);
- if (err)
- return err;
- node_numRecords = get_UINT16BE(((BTNodeHeader *) enumerator->BTref->node_buf)->numRecords);
-
- /* skip nodes until we find a record */
- while ((enumerator->cur_rec >= node_numRecords) && (enumerator->cur_node != 0))
- {
- enumerator->cur_node = get_UINT32BE(((BTNodeHeader *) enumerator->BTref->node_buf)->fLink);
- enumerator->cur_rec = 0;
-
- /* read node */
- err = BT_read_node(enumerator->BTref, enumerator->cur_node, btnk_leafNode, 1, enumerator->BTref->node_buf);
- if (err)
- return err;
- node_numRecords = get_UINT16BE(((BTNodeHeader *) enumerator->BTref->node_buf)->numRecords);
- }
-
- /* check EOList condition */
- if (enumerator->cur_node == 0)
- return IMGTOOLERR_SUCCESS;
-
- /* get current record */
- err = BT_node_get_keyed_record(enumerator->BTref, enumerator->BTref->node_buf, false, enumerator->cur_rec, record_ptr, rec_len);
- if (err)
- return err;
-
- /* iterate to next record */
- enumerator->cur_rec++;
- if (enumerator->cur_rec >= node_numRecords)
- { /* iterate to next node if last record (not required, but will improve
- performance on next iteration) */
- enumerator->cur_node = get_UINT32BE(((BTNodeHeader *) enumerator->BTref->node_buf)->fLink);
- enumerator->cur_rec = 0;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- B-Tree extend EOF algorithm:
- * see if the bitmap will need to be extended
- * extend EOF by min 1 (if bitmap is large engough) or 2 (if bitmap needs
- to be extended) and max ClumpSiz (see extClpSiz and ctClpSiz in MDB)
- ***If we are extending the extent B-Tree, we need to defer the possible
- creation of an additional extent record, or we might enter an endless
- recursion loop***
-
- Empty node alloc algorithm:
-
- * see if there is any free node in B-tree bitmap
- * optionally, try to compact the B-tree if file is full
- * if file is still full, extend EOF and try again
- * mark new block as used and return its index
-
-
- Empty node delete algorithm:
-
- * remove node from link list
- * mark node as free in the B-tree bitmap
- * optionally, if more than N% of the B-tree is free, compact the B-tree and
- free some disk space
- * Count nodes on this level; if there is only one left, delete parent index
- node and mark the relaining node as root; if it was the last leaf node,
- update header node with an empty B-tree; in either case, decrement tree
- depth
-
-
- Record shifting algorithm:
-
- For a given node and its first non-empty successor node:
-
- * compute how much free room there is in the node
- * see if the first record of the first non-empty successor can fit
- * if so, move it (i.e. delete the first record of the later node, and add a
- copy of it to the end of the former)
-
-
- Node merging algorithm
-
- * Consider node and its predecessor. If there is room, shift all records
- from later to former, then delete empty later node, and delete later
- record from parent index node.
-
-
- Node splitting algorithm (non-first)
-
- * Consider node and its predecessor. Create new middle node and split
- records in 3 even sets. Update record for last node and insert record
- for middle node in parent index node.
-
-
- Node splitting algorithm (first node)
-
- * Create new successor node, and split records in 2 1/3 and 2/3 sets.
- Insert record for later node in parent index node.
-
-
- Record delete algorithm:
-
- * remove record from node
- * if record was first in node, test if node is now empty
- * if node is not empty, substitute key of deleted record with key of
- new head record in index tree
- * if node is empty, delete key of deleted record in index tree, then
- delete empty node
- * optionally, look the predecessor node. Merge the two nodes if possible.
-
-
- Record insert algorithm:
-
- * if there room, just insert new record in node; if new record is in first
- position, update record in parent index node
- * else consider predecessor: see if we can make enough room by shifting
- records. If so, do shift records, insert new record, update record in
- parent index node
- * else split the nodes and insert record
-*/
-/*
- Possible additions:
-
- Node compaction algorithm:
-
- This algorithm can be executed with a specific start point and max number
- of nodes, or with all nodes on a level.
-
- * see how many nodes we can save by shifting records left
- * if we will save at least one node, do shift as many records as possible
- (try to leave free space split homogeneously???)
-*/
-
-/*static void*/
-
-#if 0
-#pragma mark -
-#pragma mark RESOURCE IMPLEMENTATION
-#endif
-
-/*
- Resource manager
-
- The resource manager stores arbitrary chunks of data (resource) identified
- by a type/id pair. The resource type is a 4-char code, which generally
- implies the format of the data (e.g. 'PICT' is for a quickdraw picture,
- 'STR ' for a macintosh string, 'CODE' for 68k machine code, etc). The
- resource id is a signed 16-bit number that uniquely identifies each
- resource of a given type. Note that, with most resource types, resources
- with id < 128 are system resources that are available to all applications,
- whereas resources with id >= 128 are application resources visible only to
- the application that defines them.
-
- Each resource can optionally have a resource name, which is a macintosh
- string of 255 chars at most.
-
- Limits:
- 16MBytes of data
- 64kbytes of type+reference lists
- 64kbytes of resource names
-
- The Macintosh toolbox can open several resource files simulteanously to
- overcome these restrictions.
-
- Resources are used virtually everywhere in the Macintosh Toolbox, so it is
- no surprise that file comments and MFS folders are stored in resource files.
-*/
-
-/*
- Resource header
-*/
-struct rsrc_header
-{
- UINT32BE data_offs; /* Offset from beginning of resource fork to resource data */
- UINT32BE map_offs; /* Offset from beginning of resource fork to resource map */
- UINT32BE data_len; /* Length of resource data */
- UINT32BE map_len; /* Length of resource map */
-};
-
-/*
- Resource data: each data entry is preceded by its len (UINT32BE)
- Offset to specific data fields are gotten from the resource map
-*/
-
-/*
- Resource map:
-*/
-struct rsrc_map_header
-{
- rsrc_header reserved0; /* Reserved for copy of resource header */
- UINT32BE reserved1; /* Reserved for handle to next resource map */
- UINT16BE reserved2; /* Reserved for file reference number */
-
- UINT16BE attr; /* Resource fork attributes */
- UINT16BE typelist_offs; /* Offset from beginning of map to resource type list */
- UINT16BE namelist_offs; /* Offset from beginning of map to resource name list */
- UINT16BE type_count; /* Number of types in the map minus 1 */
- /* This is actually part of the type list, which matters for offsets */
-};
-
-/*
- Resource type list entry
-*/
-struct rsrc_type_entry
-{
- UINT32BE type; /* Resource type */
- UINT16BE ref_count; /* Number of resources of this type in map minus 1 */
- UINT16BE ref_offs; /* Offset from beginning of resource type list to reference list for this type */
-};
-
-/*
- Resource reference list entry
-*/
-struct rsrc_ref_entry
-{
- UINT16BE id; /* Resource ID */
- UINT16BE name_offs; /* Offset from beginning of resource name list to resource name */
- /* (-1 if none) */
- uint8_t attr; /* Resource attributes */
- UINT24BE data_offs; /* Offset from beginning of resource data to data for this resource */
- UINT32BE reserved; /* Reserved for handle to resource */
-};
-
-/*
- Resource name list entry: this is just a standard macintosh string
-*/
-
-struct mac_resfileref
-{
- mac_fileref fileref; /* open resource fork ref (you may open resources
- files in data fork, too, if you ever need to,
- but Classic MacOS never does such a thing
- (MacOS X often does so, though)) */
- uint32_t data_offs; /* Offset from beginning of resource file to resource data */
- uint32_t map_offs; /* Offset from beginning of resource file to resource data */
-
- uint16_t typelist_offs; /* Offset from beginning of map to resource type list */
- uint16_t namelist_offs; /* Offset from beginning of map to resource name list */
- uint16_t type_count; /* Number of types in the map minus 1 */
- /* This is actually part of the type list, which matters for offsets */
-};
-
-#ifdef UNUSED_FUNCTION
-/*
- resfile_open
-
- Open a file as a resource file. The file must be already open as a
- macintosh file.
-
- resfileref (I/O): resource file handle to open (resfileref->fileref must
- have been opened previously)
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_open(mac_resfileref *resfileref)
-{
- imgtoolerr_t err;
- rsrc_header header;
- rsrc_map_header map_header;
-
- /* seek to resource header */
- err = mac_file_seek(&resfileref->fileref, 0);
- if (err)
- return err;
-
- err = mac_file_read(&resfileref->fileref, sizeof(header), &header);
- if (err)
- return err;
-
- resfileref->data_offs = get_UINT32BE(header.data_offs);
- resfileref->map_offs = get_UINT32BE(header.map_offs);
-
- /* seek to resource map header */
- err = mac_file_seek(&resfileref->fileref, resfileref->map_offs);
- if (err)
- return err;
-
- err = mac_file_read(&resfileref->fileref, sizeof(map_header), &map_header);
- if (err)
- return err;
-
- resfileref->typelist_offs = get_UINT16BE(map_header.typelist_offs);
- resfileref->namelist_offs = get_UINT16BE(map_header.namelist_offs);
- resfileref->type_count = get_UINT16BE(map_header.type_count);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- resfile_get_entry
-
- Get the resource entry in the resource map associated with a given type/id
- pair.
-
- resfileref (I/O): open resource file handle
- type (I): type of the resource
- id (I): id of the resource
- entry (O): resource entry that has been read
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_get_entry(mac_resfileref *resfileref, uint32_t type, uint16_t id, rsrc_ref_entry *entry)
-{
- imgtoolerr_t err;
- rsrc_type_entry type_entry;
- uint16_t ref_count;
- int i;
-
- /* seek to resource type list in resource map */
- err = mac_file_seek(&resfileref->fileref, resfileref->map_offs+resfileref->typelist_offs+2);
- if (err)
- return err;
-
- if (resfileref->type_count == 0xffff)
- /* type list is empty */
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i=0; i<=resfileref->type_count; i++)
- {
- err = mac_file_read(&resfileref->fileref, sizeof(type_entry), &type_entry);
- if (err)
- return err;
- if (type == get_UINT32BE(type_entry.type))
- break;
- }
- if (i > resfileref->type_count)
- /* type not found in list */
- return IMGTOOLERR_FILENOTFOUND;
-
- ref_count = get_UINT16BE(type_entry.ref_count);
-
- /* seek to resource ref list for this type in resource map */
- err = mac_file_seek(&resfileref->fileref, resfileref->map_offs+resfileref->typelist_offs+get_UINT16BE(type_entry.ref_offs));
- if (err)
- return err;
-
- if (ref_count == 0xffff)
- /* ref list is empty */
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i=0; i<=ref_count; i++)
- {
- err = mac_file_read(&resfileref->fileref, sizeof(*entry), entry);
- if (err)
- return err;
- if (id == get_UINT16BE(entry->id))
- break;
- }
- if (i > ref_count)
- /* id not found in list */
- return IMGTOOLERR_FILENOTFOUND;
-
- /* type+id have been found... */
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- resfile_get_resname
-
- Get the name of a resource.
-
- resfileref (I/O): open resource file handle
- entry (I): resource entry in the resource map (returned by
- resfile_get_entry)
- string (O): resource name
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_get_resname(mac_resfileref *resfileref, const rsrc_ref_entry *entry, mac_str255 string)
-{
- imgtoolerr_t err;
- uint16_t name_offs;
- uint8_t len;
-
- name_offs = get_UINT16BE(entry->name_offs);
-
- if (name_offs == 0xffff)
- /* ref list is empty */
- return IMGTOOLERR_UNEXPECTED;
-
- /* seek to resource name in name list in resource map */
- err = mac_file_seek(&resfileref->fileref, resfileref->map_offs+name_offs);
- if (err)
- return err;
-
- /* get string length */
- err = mac_file_read(&resfileref->fileref, 1, &len);
- if (err)
- return err;
-
- string[0] = len;
-
- /* get string data */
- err = mac_file_read(&resfileref->fileref, len, string+1);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- resfile_get_reslen
-
- Get the data length for a given resource.
-
- resfileref (I/O): open resource file handle
- entry (I): resource entry in the resource map (returned by
- resfile_get_entry)
- len (O): resource length
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_get_reslen(mac_resfileref *resfileref, const rsrc_ref_entry *entry, uint32_t *len)
-{
- imgtoolerr_t err;
- uint32_t data_offs;
- UINT32BE llen;
-
- data_offs = get_UINT24BE(entry->data_offs);
-
- /* seek to resource data in resource data section */
- err = mac_file_seek(&resfileref->fileref, resfileref->data_offs+data_offs);
- if (err)
- return err;
-
- /* get data length */
- err = mac_file_read(&resfileref->fileref, sizeof(llen), &llen);
- if (err)
- return err;
-
- *len = get_UINT32BE(llen);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- resfile_get_resdata
-
- Get the data for a given resource.
-
- resfileref (I/O): open resource file handle
- entry (I): resource entry in the resource map (returned by
- resfile_get_entry)
- offset (I): offset the data should be read from, usually 0
- len (I): length of the data to read, usually the value returned by
- resfile_get_reslen
- dest (O): resource data
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_get_resdata(mac_resfileref *resfileref, const rsrc_ref_entry *entry, uint32_t offset, uint32_t len, void *dest)
-{
- imgtoolerr_t err;
- uint32_t data_offs;
- UINT32BE llen;
-
- data_offs = get_UINT24BE(entry->data_offs);
-
- /* seek to resource data in resource data section */
- err = mac_file_seek(&resfileref->fileref, resfileref->data_offs+data_offs);
- if (err)
- return err;
-
- /* get data length */
- err = mac_file_read(&resfileref->fileref, sizeof(llen), &llen);
- if (err)
- return err;
-
- /* check that we do not ask to read more data than avalaible */
- if ((offset + len) > get_UINT32BE(llen))
- return IMGTOOLERR_UNEXPECTED;
-
- if (offset)
- { /* seek to resource data offset in resource data section */
- err = mac_file_seek(&resfileref->fileref, resfileref->data_offs+data_offs+4+offset);
- if (err)
- return err;
- }
-
- /* get data */
- err = mac_file_read(&resfileref->fileref, len, dest);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark DESKTOP FILE IMPLEMENTATION
-#endif
-/*
- All macintosh volumes have information stored in the desktop file or the
- desktop database.
-
- Such information include file comments, copy of BNDL and FREF resources
- that describes supported file types for each application on the volume,
- copy of icons for each file type registered by each application on the
- volume, etc. On MFS volumes, the list of folders is stored in the desktop
- file as well.
-
-
- There have been two implementations of the desktop metadata:
-
- * The original desktop file. The database is stored in the resource fork
- of a (usually invisible) file called "Desktop" (case may change
- according to system versions), located at the root of the volume. The
- desktop file is used by System 6 and earlier for all volumes (unless
- Appleshare 2 is installed and the volume is shared IIRC), and by System
- 7 and later for volumes smaller than 2MBytes (so that floppy disks
- remain fully compatible with earlier versions of system). The desktop
- file is incompletely documented by Apple technote TB06.
-
- * The desktop database. The database is stored in the resource fork is
- stored in the data fork of two (usually invisible) files called
- "Desktop DF" and "Desktop DF". The desktop database is used for
- volumes shared by Appleshare 2, and for most volumes under System 7 and
- later. The format of these file is not documented AFAIK.
-
-
- The reasons for the introduction of the desktop database were:
- * the macintosh resource manager cannot share resource files, which was
- a problem for Appleshare
- * the macintosh resource manager is pretty limited (+/-16MByte of data and
- 2727 resources at most), which was a problem for large hard disks with
- many programs/comments
-*/
-
-#ifdef UNUSED_FUNCTION
-/*
- get_comment
-
- Get a comment from the Desktop file
-
- l2_img (I): macintosh image the data should be read from
- id (I): comment id (from mfs_hashString(), or HFS FXInfo/DXInfo records)
- comment (O): comment that has been read
-
- Return imgtool error code
-*/
-static imgtoolerr_t get_comment(struct mac_l2_imgref *l2_img, uint16_t id, mac_str255 comment)
-{
- static const uint8_t desktop_fname[] = {'\7','D','e','s','k','t','o','p'};
- #define restype_FCMT (('F' << 24) | ('C' << 16) | ('M' << 8) | 'T')
- mac_resfileref resfileref;
- rsrc_ref_entry resentry;
- uint32_t reslen;
- imgtoolerr_t err;
-
- /* open rsrc fork of file Desktop in root directory */
- err = mac_file_open(l2_img, 2, desktop_fname, rsrc_fork, &resfileref.fileref);
- if (err)
- return err;
-
- /* open resource structures */
- err = resfile_open(&resfileref);
- if (err)
- return err;
-
- /* look for resource FCMT #id */
- err = resfile_get_entry(&resfileref, restype_FCMT, id, &resentry);
- if (err)
- return err;
-
- /* extract comment len */
- err = resfile_get_reslen(&resfileref, &resentry, &reslen);
- if (err)
- return err;
-
- /* check comment len */
- if (reslen > 256)
- /* hurk */
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- /* people willing to extend the MFM comment field (you know, the kind
- of masochists that try to support 20-year-old OSes) might append extra
- fields, so we just truncate the resource */
- reslen = 256;
-
- /* extract comment data */
- err = resfile_get_resdata(&resfileref, &resentry, 0, reslen, comment);
- if (err)
- return err;
-
- /* phew, we are done! */
- return IMGTOOLERR_SUCCESS;
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark IMGTOOL MODULE IMPLEMENTATION
-#endif
-
-#ifdef UNUSED_FUNCTION
-static void mac_image_exit(imgtool::image *img);
-#endif
-static void mac_image_info(imgtool::image &img, std::ostream &stream);
-static imgtoolerr_t mac_image_beginenum(imgtool::directory &enumeration, const char *path);
-static imgtoolerr_t mac_image_nextenum(imgtool::directory &enumeration, imgtool_dirent &ent);
-static imgtoolerr_t mac_image_freespace(imgtool::partition &partition, uint64_t *size);
-static imgtoolerr_t mac_image_readfile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &destf);
-static imgtoolerr_t mac_image_writefile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &sourcef, util::option_resolution *writeoptions);
-
-#ifdef UNUSED_FUNCTION
-/*
- close a mfs/hfs image
-*/
-static void mac_image_exit(imgtool::image *img)
-{
- struct mac_l2_imgref *image = get_imgref(img);
-
- mac_image_close(image);
-}
-#endif
-
-/*
- get basic information on a mfs/hfs image
-
- Currently returns the volume name
-*/
-static void mac_image_info(imgtool::image &img, std::ostream &stream)
-{
- char buffer[256] = { 0, };
- struct mac_l2_imgref *image = get_imgref(img);
-
- switch (image->format)
- {
- case L2I_MFS:
- mac_to_c_strncpy(buffer, ARRAY_LENGTH(buffer), image->u.mfs.volname);
- break;
-
- case L2I_HFS:
- mac_to_c_strncpy(buffer, ARRAY_LENGTH(buffer), image->u.hfs.volname);
- break;
- }
-
- stream << buffer;
-}
-
-/*
- MFS/HFS catalog iterator, used when imgtool reads the catalog
-*/
-struct mac_iterator
-{
- mac_format format;
- struct mac_l2_imgref *l2_img;
- union
- {
- struct
- {
- mfs_dirref dirref; /* open directory reference */
- } mfs;
- struct
- {
- hfs_cat_enumerator catref; /* catalog file enumerator */
- } hfs;
- } u;
-};
-
-/*
- Open the disk catalog for enumeration
-*/
-static imgtoolerr_t mac_image_beginenum(imgtool::directory &enumeration, const char *path)
-{
- struct mac_l2_imgref *image = get_imgref(enumeration.image());
- mac_iterator *iter = (mac_iterator *) enumeration.extra_bytes();
- imgtoolerr_t err = IMGTOOLERR_UNEXPECTED;
-
- iter->format = image->format;
- iter->l2_img = image;
-
- switch (iter->format)
- {
- case L2I_MFS:
- err = mfs_dir_open(image, path, &iter->u.mfs.dirref);
- break;
-
- case L2I_HFS:
- err = hfs_cat_open(image, path, &iter->u.hfs.catref);
- break;
- }
-
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Enumerate disk catalog next entry (MFS)
-*/
-static imgtoolerr_t mfs_image_nextenum(mac_iterator *iter, imgtool_dirent &ent)
-{
- mfs_dir_entry *cur_dir_entry;
- imgtoolerr_t err;
-
-
- assert(iter->format == L2I_MFS);
-
- ent.corrupt = 0;
- ent.eof = 0;
-
- err = mfs_dir_read(&iter->u.mfs.dirref, &cur_dir_entry);
- if (err)
- {
- /* error */
- ent.corrupt = 1;
- return err;
- }
- else if (!cur_dir_entry)
- {
- /* EOF */
- ent.eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
-
- /* copy info */
- mac_to_c_strncpy(ent.filename, ARRAY_LENGTH(ent.filename), cur_dir_entry->name);
- ent.filesize = get_UINT32BE(cur_dir_entry->dataPhysicalSize)
- + get_UINT32BE(cur_dir_entry->rsrcPhysicalSize);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#if 0
-/*
- Concatenate path elements in the reverse order
-
- dest (O): destination buffer
- dest_cur_pos (I/O): current position in destination buffer (buffer is
- filled from end to start)
- dest_max_len (I): length of destination buffer (use length minus one if you
- want to preserve a trailing NUL character)
- src (I): source C string
-*/
-static void concat_fname(char *dest, int *dest_cur_pos, int dest_max_len, const char *src)
-{
- static const char ellipsis[] = { '.', '.', '.' };
- int src_len = strlen(src); /* number of chars from src to insert */
-
- if (src_len <= *dest_cur_pos)
- {
- *dest_cur_pos -= src_len;
- memcpy(dest + *dest_cur_pos, src, src_len);
- }
- else
- {
- memcpy(dest, src + src_len - *dest_cur_pos, *dest_cur_pos);
- *dest_cur_pos = 0;
- memcpy(dest, ellipsis, (sizeof(ellipsis) <= dest_max_len)
- ? sizeof(ellipsis)
- : dest_max_len);
- }
-}
-#endif
-
-/*
- Enumerate disk catalog next entry (HFS)
-*/
-static imgtoolerr_t hfs_image_nextenum(mac_iterator *iter, imgtool_dirent &ent)
-{
- hfs_catKey *catrec_key;
- hfs_catData *catrec_data;
- uint16_t dataRecType;
- imgtoolerr_t err;
- /* currently, the mac->C conversion transcodes one mac char with at most 3
- C chars */
- int cur_name_head;
-
- assert(iter->format == L2I_HFS);
-
- ent.corrupt = 0;
- ent.eof = 0;
-
- do
- {
- err = hfs_cat_read(&iter->u.hfs.catref, &catrec_key, &catrec_data);
- if (err)
- {
- /* error */
- ent.corrupt = 1;
- return err;
- }
- else if (!catrec_key)
- {
- /* EOF */
- ent.eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
- dataRecType = get_UINT16BE(catrec_data->dataType);
- } while (((dataRecType != hcrt_Folder) && (dataRecType != hcrt_File))
- || (get_UINT32BE(catrec_key->parID) != iter->u.hfs.catref.parID));
-
- /* copy info */
- switch (get_UINT16BE(catrec_data->dataType))
- {
- case hcrt_Folder:
- ent.directory = 1;
- ent.filesize = 0;
- break;
-
- case hcrt_File:
- ent.directory = 0;
- ent.filesize = get_UINT32BE(catrec_data->file.dataPhysicalSize)
- + get_UINT32BE(catrec_data->file.rsrcPhysicalSize);
- break;
- }
-
- /* initialize file path buffer */
- cur_name_head = ARRAY_LENGTH(ent.filename);
- if (cur_name_head > 0)
- {
- cur_name_head--;
- ent.filename[cur_name_head] = '\0';
- }
-
- /* insert folder/file name in buffer */
- mac_to_c_strncpy(ent.filename, ARRAY_LENGTH(ent.filename), catrec_key->cName);
-// concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename) - 1, buf);
-
-#if 0
- /* extract parent directory ID */
- parID = get_UINT32BE(catrec_key->parID);
-
- /* looping while (parID != 1) will display the volume name; looping while
- (parID != 2) won't */
- while (parID != /*1*/2)
- {
- /* search catalog for folder thread */
- err = hfs_cat_search(iter->l2_img, parID, mac_empty_str, &catrec_key, &catrec_data);
- if (err)
- {
- /* error */
- concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename) - 1, ":");
- concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename) - 1, "???");
-
- memmove(ent.filename, ent.filename+cur_name_head, ARRAY_LENGTH(ent.filename) - cur_name_head);
- ent.corrupt = 1;
- return err;
- }
-
- dataRecType = get_UINT16BE(catrec_data->dataType);
-
- if (dataRecType != hcrt_FolderThread)
- {
- /* error */
- concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename)-1, ":");
- concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename)-1, "???");
-
- memmove(ent.filename, ent.filename+cur_name_head, ARRAY_LENGTH(ent.filename)-cur_name_head);
- ent.corrupt = 1;
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- /* got folder thread record: insert the folder name at the start of
- file path, then iterate */
- mac_to_c_strncpy(buf, sizeof(buf), catrec_data->thread.nodeName);
- concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename) - 1, ":");
- concat_fname(ent.filename, &cur_name_head, ARRAY_LENGTH(ent.filename) - 1, buf);
-
- /* extract parent directory ID */
- parID = get_UINT32BE(catrec_data->thread.parID);
- }
- memmove(ent.filename, ent.filename+cur_name_head, ARRAY_LENGTH(ent.filename) -cur_name_head);
-#endif
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Enumerate disk catalog next entry
-*/
-static imgtoolerr_t mac_image_nextenum(imgtool::directory &enumeration, imgtool_dirent &ent)
-{
- imgtoolerr_t err;
- mac_iterator *iter = (mac_iterator *) enumeration.extra_bytes();
-
- switch (iter->format)
- {
- case L2I_MFS:
- err = mfs_image_nextenum(iter, ent);
- break;
-
- case L2I_HFS:
- err = hfs_image_nextenum(iter, ent);
- break;
-
- default:
- assert(1);
- err = IMGTOOLERR_UNEXPECTED;
- break;
- }
- return err;
-}
-
-/*
- Compute free space on disk image in bytes
-*/
-static imgtoolerr_t mac_image_freespace(imgtool::partition &partition, uint64_t *size)
-{
- imgtool::image &image(partition.image());
- *size = ((uint64_t) get_imgref(image)->freeABs) * 512;
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t mac_get_comment(struct mac_l2_imgref *image, mac_str255 filename, const mac_dirent *cat_info, mac_str255 comment)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- uint16_t commentID;
-
- comment[0] = '\0';
-
- /* get comment from Desktop file */
- switch (image->format)
- {
- case L2I_MFS:
- commentID = mfs_hashString(filename);
- err = get_comment(image, commentID, comment);
- break;
-
- case L2I_HFS:
- /* This is the way to get Finder comments in system <= 7. Attached
- comments use another method, and Finder 8 uses yet another one. */
- commentID = get_UINT16BE(cat_info->flXFinderInfo.comment);
- if (commentID)
- err = get_comment(image, commentID, comment);
- break;
- }
- return err;
-}
-#endif
-
-
-/*
- Extract a file from a disk image.
-*/
-static imgtoolerr_t mac_image_readfile(imgtool::partition &partition, const char *fpath, const char *fork, imgtool::stream &destf)
-{
- imgtoolerr_t err;
- imgtool::image &img(partition.image());
- struct mac_l2_imgref *image = get_imgref(img);
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
- mac_fileref fileref;
- uint8_t buf[512];
- uint32_t i, run_len, data_len;
- mac_fork_t fork_num;
-
- err = mac_identify_fork(fork, &fork_num);
- if (err)
- return err;
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, fpath, &parID, filename, &cat_info, false);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- /* open file */
- err = mac_file_open(image, parID, filename, fork_num ? rsrc_fork : data_fork, &fileref);
- if (err)
- return err;
-
- data_len = fork_num ? cat_info.rsrcLogicalSize : cat_info.dataLogicalSize;
-
- /* extract DF */
- i = 0;
- while(i < data_len)
- {
- run_len = std::min(size_t(data_len - i), sizeof(buf));
-
- err = mac_file_read(&fileref, run_len, buf);
- if (err)
- return err;
- if (destf.write(buf, run_len) != run_len)
- return IMGTOOLERR_WRITEERROR;
- i += run_len;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Add a file to a disk image.
-*/
-static imgtoolerr_t mac_image_writefile(imgtool::partition &partition, const char *fpath, const char *fork, imgtool::stream &sourcef, util::option_resolution *writeoptions)
-{
- imgtool::image &img(partition.image());
- struct mac_l2_imgref *image = get_imgref(img);
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
- mac_fileref fileref;
- uint32_t fork_len;
- /*uint16_t commentID;*/
- /*mac_str255 comment;*/
- uint8_t buf[512];
- uint32_t i, run_len;
- imgtoolerr_t err;
- mac_fork_t fork_num;
-
- (void) writeoptions;
-
- if (image->format == L2I_HFS)
- return IMGTOOLERR_UNIMPLEMENTED;
-
- err = mac_identify_fork(fork, &fork_num);
- if (err)
- return err;
-
-#if 0
- if (header.version_old != 0)
- return IMGTOOLERR_UNIMPLEMENTED;
-#endif
- /*mac_strcpy(filename, header.filename);*/
- memset(&cat_info, 0, sizeof(cat_info));
- set_UINT32BE(&cat_info.flFinderInfo.type, 0x3F3F3F3F);
- set_UINT32BE(&cat_info.flFinderInfo.creator, 0x3F3F3F3F);
- fork_len = sourcef.size();
- /*comment[0] = get_UINT16BE(header.comment_len);*/ /* comment length */
- /* Next two fields are set to 0 with MFS volumes. IIRC, 0 normally
- means system script: I don't think MFS stores the file name script code
- anywhere on disk, so it should be a reasonable approximation. */
-
- /* create file */
- /* clear inited flag and file location in window */
- set_UINT16BE(&cat_info.flFinderInfo.flags, get_UINT16BE(cat_info.flFinderInfo.flags) & ~fif_hasBeenInited);
- set_UINT16BE(&cat_info.flFinderInfo.location.v, 0);
- set_UINT16BE(&cat_info.flFinderInfo.location.h, 0);
-
- /* resolve path and create file */
- err = mac_lookup_path(image, fpath, &parID, filename, &cat_info, true);
- if (err)
- return err;
-
- /* open file fork */
- err = mac_file_open(image, parID, filename, (fork_num ? rsrc_fork : data_fork), &fileref);
- if (err)
- return err;
-
- err = mac_file_seteof(&fileref, fork_len);
- if (err)
- return err;
-
- /* extract fork */
- for (i=0; i<fork_len;)
- {
- run_len = fork_len - i;
- if (run_len > 512)
- run_len = 512;
- if (sourcef.read(buf, run_len) != run_len)
- return IMGTOOLERR_READERROR;
- err = mac_file_write(&fileref, run_len, buf);
- if (err)
- return err;
- i += run_len;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t mac_image_listforks(imgtool::partition &partition, const char *path, std::vector<imgtool::fork_entry> &forks)
-{
- imgtoolerr_t err;
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
- imgtool::image &img(partition.image());
- struct mac_l2_imgref *image = get_imgref(img);
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, false);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- // specify data fork
- forks.emplace_back(cat_info.dataLogicalSize, imgtool::fork_entry::type_t::DATA);
-
- if (cat_info.rsrcLogicalSize > 0)
- {
- // specify the resource fork
- forks.emplace_back(cat_info.rsrcLogicalSize, imgtool::fork_entry::type_t::RESOURCE);
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t mac_image_getattrs(imgtool::partition &partition, const char *path, const uint32_t *attrs, imgtool_attribute *values)
-{
- imgtoolerr_t err;
- imgtool::image &img(partition.image());
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
- struct mac_l2_imgref *image = get_imgref(img);
- int i;
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, false);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i = 0; attrs[i]; i++)
- {
- switch(attrs[i])
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- values[i].i = get_UINT32BE(cat_info.flFinderInfo.type);
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- values[i].i = get_UINT32BE(cat_info.flFinderInfo.creator);
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- values[i].i = get_UINT16BE(cat_info.flFinderInfo.flags);
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- values[i].i = get_UINT16BE(cat_info.flFinderInfo.location.h);
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- values[i].i = get_UINT16BE(cat_info.flFinderInfo.location.v);
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- values[i].i = get_UINT16BE(cat_info.flFinderInfo.fldr);
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- values[i].i = get_UINT16BE(cat_info.flXFinderInfo.iconID);
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- values[i].i = cat_info.flXFinderInfo.script;
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- values[i].i = cat_info.flXFinderInfo.XFlags;
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- values[i].i = get_UINT16BE(cat_info.flXFinderInfo.comment);
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- values[i].i = get_UINT32BE(cat_info.flXFinderInfo.putAway);
- break;
-
- case IMGTOOLATTR_TIME_CREATED:
- values[i].t = mac_crack_time(cat_info.createDate).to_time_t();
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- values[i].t = mac_crack_time(cat_info.modifyDate).to_time_t();
- break;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t mac_image_setattrs(imgtool::partition &partition, const char *path, const uint32_t *attrs, const imgtool_attribute *values)
-{
- imgtoolerr_t err;
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
- imgtool::image &img(partition.image());
- struct mac_l2_imgref *image = get_imgref(img);
- int i;
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, false);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i = 0; attrs[i]; i++)
- {
- switch(attrs[i])
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- set_UINT32BE(&cat_info.flFinderInfo.type, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- set_UINT32BE(&cat_info.flFinderInfo.creator, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- set_UINT16BE(&cat_info.flFinderInfo.flags, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- set_UINT16BE(&cat_info.flFinderInfo.location.h, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- set_UINT16BE(&cat_info.flFinderInfo.location.v, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- set_UINT16BE(&cat_info.flFinderInfo.fldr, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- set_UINT16BE(&cat_info.flXFinderInfo.iconID, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- cat_info.flXFinderInfo.script = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- cat_info.flXFinderInfo.XFlags = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- set_UINT16BE(&cat_info.flXFinderInfo.comment, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- set_UINT32BE(&cat_info.flXFinderInfo.putAway, values[i].i);
- break;
-
- case IMGTOOLATTR_TIME_CREATED:
- cat_info.createDate = mac_setup_time(values[i].t);
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- cat_info.modifyDate = mac_setup_time(values[i].t);
- break;
- }
- }
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, true);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*************************************
- *
- * Our very own resource manager
- *
- *************************************/
-
-static const void *mac_walk_resources(const void *resource_fork, size_t resource_fork_length,
- uint32_t resource_type,
- int (*discriminator)(const void *resource, uint16_t id, uint32_t length, void *param_),
- void *param, uint16_t *resource_id, uint32_t *resource_length)
-{
- uint32_t resource_data_offset, resource_data_length;
- uint32_t resource_map_offset, resource_map_length;
- uint32_t resource_typelist_count, resource_typelist_offset;
- uint32_t resource_entry_offset, resource_entry_count;
- uint32_t i, this_resource_type;
- uint32_t this_resource_data, this_resource_length;
- uint16_t this_resource_id;
- const void *this_resource_ptr;
-
- if (resource_fork_length < 16)
- return NULL;
-
- /* read resource header; its ok if anything past this point fails */
- resource_data_offset = pick_integer_be(resource_fork, 0, 4);
- resource_map_offset = pick_integer_be(resource_fork, 4, 4);
- resource_data_length = pick_integer_be(resource_fork, 8, 4);
- resource_map_length = pick_integer_be(resource_fork, 12, 4);
- if ((resource_data_offset + resource_data_length) > resource_fork_length)
- return NULL;
- if ((resource_map_offset + resource_map_length) > resource_fork_length)
- return NULL;
- if (resource_map_length < 30)
- return NULL;
-
- /* read resource map and locate the resource type list */
- resource_typelist_offset = pick_integer_be(resource_fork,
- resource_map_offset + 24, 2) + resource_map_offset;
- if ((resource_typelist_offset + 2) > resource_fork_length)
- return NULL;
- resource_typelist_count = pick_integer_be(resource_fork,
- resource_typelist_offset, 2) + 1;
- if ((resource_typelist_offset + resource_typelist_count * 16 + 2) > resource_fork_length)
- return NULL;
-
- /* scan the resource type list and locate the entries for this type */
- resource_entry_count = 0;
- resource_entry_offset = 0;
- for (i = 0; i < resource_typelist_count; i++)
- {
- this_resource_type = pick_integer_be(resource_fork, resource_typelist_offset
- + (i * 8) + 2 + 0, 4);
- if (this_resource_type == resource_type)
- {
- resource_entry_count = pick_integer_be(resource_fork, resource_typelist_offset
- + (i * 8) + 2 + 4, 2) + 1;
- resource_entry_offset = pick_integer_be(resource_fork, resource_typelist_offset
- + (i * 8) + 2 + 6, 2) + resource_typelist_offset;
- break;
- }
- }
-
- /* scan the resource entries, and find the correct resource */
- for (i = 0; i < resource_entry_count; i++)
- {
- this_resource_id = pick_integer_be(resource_fork, resource_entry_offset
- + (i * 12) + 0, 2);
- this_resource_data = pick_integer_be(resource_fork, resource_entry_offset
- + (i * 12) + 5, 3) + resource_data_offset;
- if ((this_resource_data + 4) > resource_fork_length)
- return NULL;
-
- /* gauge the length */
- this_resource_length = pick_integer_be(resource_fork, this_resource_data, 4);
- this_resource_data += 4;
- if ((this_resource_data + this_resource_length) > resource_fork_length)
- return NULL;
-
- this_resource_ptr = ((const uint8_t *) resource_fork) + this_resource_data;
- if (discriminator(this_resource_ptr, this_resource_id,
- this_resource_length, param))
- {
- if (resource_length)
- *resource_length = this_resource_length;
- if (resource_id)
- *resource_id = this_resource_id;
- return this_resource_ptr;
- }
- }
-
- return NULL;
-}
-
-
-
-static int get_resource_discriminator(const void *resource, uint16_t id, uint32_t length, void *param)
-{
- const uint16_t *id_ptr = (const uint16_t *) param;
- return id == *id_ptr;
-}
-
-
-
-static const void *mac_get_resource(const void *resource_fork, size_t resource_fork_length,
- uint32_t resource_type, uint16_t resource_id, uint32_t *resource_length)
-{
- return mac_walk_resources(resource_fork, resource_fork_length,
- resource_type, get_resource_discriminator, &resource_id, NULL, resource_length);
-}
-
-
-
-/*************************************
- *
- * Custom icons
- *
- *************************************/
-
-static int bundle_discriminator(const void *resource, uint16_t id, uint32_t length, void *param)
-{
- uint32_t this_creator_code = pick_integer_be(resource, 0, 4);
- uint32_t desired_creator_code = *((uint32_t *) param);
- return this_creator_code == desired_creator_code;
-}
-
-
-
-static uint8_t get_pixel(const uint8_t *src, int width, int height, int bpp,
- int x, int y)
-{
- uint8_t byte, mask;
- int bit_position;
-
- byte = src[(y * width + x) * bpp / 8];
- bit_position = 8 - ((x % (8 / bpp)) + 1) * bpp;
- mask = (1 << bpp) - 1;
- return (byte >> bit_position) & mask;
-}
-
-
-
-static bool load_icon(uint32_t *dest, const void *resource_fork, uint64_t resource_fork_length,
- uint32_t resource_type, uint16_t resource_id, int width, int height, int bpp,
- const uint32_t *palette, bool has_mask)
-{
- bool success = false;
- uint32_t frame_length = width * height * bpp / 8;
- uint32_t total_length = frame_length * (has_mask ? 2 : 1);
- uint32_t resource_length;
-
- // attempt to fetch resource
- const uint8_t *src = (const uint8_t*)mac_get_resource(resource_fork, resource_fork_length, resource_type,
- resource_id, &resource_length);
- if (src && (resource_length == total_length))
- {
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x ++)
- {
- // check the color
- uint8_t color = get_pixel(src, width, height, bpp, x, y);
-
- // then check the mask
- bool is_masked = has_mask
- ? get_pixel(src + frame_length, width, height, bpp, x, y) != 0
- : dest[y * width + x] >= 0x80000000;
-
- // is this actually masked? (note there is a special case when bpp == 1; Mac B&W icons
- // had a XOR effect, and this cannot be blocked by the mask)
- uint32_t pixel;
- if (is_masked || (color && bpp == 1))
- {
- // mask is ok; check the actual icon
- pixel = palette[color] | 0xFF000000;
- }
- else
- {
- // masked out; nothing
- pixel = 0x00000000;
- }
-
- dest[y * width + x] = pixel;
- }
- }
- success = true;
- }
- return success;
-}
-
-
-
-static imgtoolerr_t mac_image_geticoninfo(imgtool::partition &partition, const char *path, imgtool_iconinfo *iconinfo)
-{
- static const uint32_t mac_palette_1bpp[2] = { 0xFFFFFF, 0x000000 };
-
- static const uint32_t mac_palette_4bpp[16] =
- {
- 0xFFFFFF, 0xFCF305, 0xFF6402, 0xDD0806, 0xF20884, 0x4600A5,
- 0x0000D4, 0x02ABEA, 0x1FB714, 0x006411, 0x562C05, 0x90713A,
- 0xC0C0C0, 0x808080, 0x404040, 0x000000
- };
-
- static const uint32_t mac_palette_8bpp[256] =
- {
- 0xFFFFFF, 0xFFFFCC, 0xFFFF99, 0xFFFF66, 0xFFFF33, 0xFFFF00,
- 0xFFCCFF, 0xFFCCCC, 0xFFCC99, 0xFFCC66, 0xFFCC33, 0xFFCC00,
- 0xFF99FF, 0xFF99CC, 0xFF9999, 0xFF9966, 0xFF9933, 0xFF9900,
- 0xFF66FF, 0xFF66CC, 0xFF6699, 0xFF6666, 0xFF6633, 0xFF6600,
- 0xFF33FF, 0xFF33CC, 0xFF3399, 0xFF3366, 0xFF3333, 0xFF3300,
- 0xFF00FF, 0xFF00CC, 0xFF0099, 0xFF0066, 0xFF0033, 0xFF0000,
- 0xCCFFFF, 0xCCFFCC, 0xCCFF99, 0xCCFF66, 0xCCFF33, 0xCCFF00,
- 0xCCCCFF, 0xCCCCCC, 0xCCCC99, 0xCCCC66, 0xCCCC33, 0xCCCC00,
- 0xCC99FF, 0xCC99CC, 0xCC9999, 0xCC9966, 0xCC9933, 0xCC9900,
- 0xCC66FF, 0xCC66CC, 0xCC6699, 0xCC6666, 0xCC6633, 0xCC6600,
- 0xCC33FF, 0xCC33CC, 0xCC3399, 0xCC3366, 0xCC3333, 0xCC3300,
- 0xCC00FF, 0xCC00CC, 0xCC0099, 0xCC0066, 0xCC0033, 0xCC0000,
- 0x99FFFF, 0x99FFCC, 0x99FF99, 0x99FF66, 0x99FF33, 0x99FF00,
- 0x99CCFF, 0x99CCCC, 0x99CC99, 0x99CC66, 0x99CC33, 0x99CC00,
- 0x9999FF, 0x9999CC, 0x999999, 0x999966, 0x999933, 0x999900,
- 0x9966FF, 0x9966CC, 0x996699, 0x996666, 0x996633, 0x996600,
- 0x9933FF, 0x9933CC, 0x993399, 0x993366, 0x993333, 0x993300,
- 0x9900FF, 0x9900CC, 0x990099, 0x990066, 0x990033, 0x990000,
- 0x66FFFF, 0x66FFCC, 0x66FF99, 0x66FF66, 0x66FF33, 0x66FF00,
- 0x66CCFF, 0x66CCCC, 0x66CC99, 0x66CC66, 0x66CC33, 0x66CC00,
- 0x6699FF, 0x6699CC, 0x669999, 0x669966, 0x669933, 0x669900,
- 0x6666FF, 0x6666CC, 0x666699, 0x666666, 0x666633, 0x666600,
- 0x6633FF, 0x6633CC, 0x663399, 0x663366, 0x663333, 0x663300,
- 0x6600FF, 0x6600CC, 0x660099, 0x660066, 0x660033, 0x660000,
- 0x33FFFF, 0x33FFCC, 0x33FF99, 0x33FF66, 0x33FF33, 0x33FF00,
- 0x33CCFF, 0x33CCCC, 0x33CC99, 0x33CC66, 0x33CC33, 0x33CC00,
- 0x3399FF, 0x3399CC, 0x339999, 0x339966, 0x339933, 0x339900,
- 0x3366FF, 0x3366CC, 0x336699, 0x336666, 0x336633, 0x336600,
- 0x3333FF, 0x3333CC, 0x333399, 0x333366, 0x333333, 0x333300,
- 0x3300FF, 0x3300CC, 0x330099, 0x330066, 0x330033, 0x330000,
- 0x00FFFF, 0x00FFCC, 0x00FF99, 0x00FF66, 0x00FF33, 0x00FF00,
- 0x00CCFF, 0x00CCCC, 0x00CC99, 0x00CC66, 0x00CC33, 0x00CC00,
- 0x0099FF, 0x0099CC, 0x009999, 0x009966, 0x009933, 0x009900,
- 0x0066FF, 0x0066CC, 0x006699, 0x006666, 0x006633, 0x006600,
- 0x0033FF, 0x0033CC, 0x003399, 0x003366, 0x003333, 0x003300,
- 0x0000FF, 0x0000CC, 0x000099, 0x000066, 0x000033, 0xEE0000,
- 0xDD0000, 0xBB0000, 0xAA0000, 0x880000, 0x770000, 0x550000,
- 0x440000, 0x220000, 0x110000, 0x00EE00, 0x00DD00, 0x00BB00,
- 0x00AA00, 0x008800, 0x007700, 0x005500, 0x004400, 0x002200,
- 0x001100, 0x0000EE, 0x0000DD, 0x0000BB, 0x0000AA, 0x000088,
- 0x000077, 0x000055, 0x000044, 0x000022, 0x000011, 0xEEEEEE,
- 0xDDDDDD, 0xBBBBBB, 0xAAAAAA, 0x888888, 0x777777, 0x555555,
- 0x444444, 0x222222, 0x111111, 0x000000
- };
-
- static const uint32_t attrs[4] =
- {
- IMGTOOLATTR_INT_MAC_TYPE,
- IMGTOOLATTR_INT_MAC_CREATOR,
- IMGTOOLATTR_INT_MAC_FINDERFLAGS
- };
-
- imgtoolerr_t err;
- imgtool_attribute attr_values[3];
- uint32_t type_code, creator_code, finder_flags;
- imgtool::stream::ptr stream;
- const void *resource_fork;
- uint64_t resource_fork_length;
- const void *bundle;
- uint32_t bundle_length, pos, fref_pos, icn_pos, i;
- uint16_t local_id = 0, resource_id;
- uint32_t fref_bundleentry_length, icn_bundleentry_length;
- const void *fref;
- uint32_t resource_length;
-
- assert((ARRAY_LENGTH(attrs) - 1)
- == ARRAY_LENGTH(attr_values));
-
- /* first retrieve type and creator code */
- err = mac_image_getattrs(partition, path, attrs, attr_values);
- if (err)
- return err;
- type_code = (uint32_t) attr_values[0].i;
- creator_code = (uint32_t) attr_values[1].i;
- finder_flags = (uint32_t) attr_values[2].i;
-
- /* check the bundle bit; if clear (and the type is not 'APPL'), use the
- * desktop file */
- if (!(finder_flags & 0x2000) && (type_code != /* APPL */ 0x4150504C))
- path = "Desktop\0";
-
- stream = imgtool::stream::open_mem(NULL, 0);
- if (!stream)
- return IMGTOOLERR_SUCCESS;
-
- /* read in the resource fork */
- err = mac_image_readfile(partition, path, "RESOURCE_FORK", *stream);
- if (err)
- return err;
- resource_fork = stream->getptr();
- resource_fork_length = stream->size();
-
- /* attempt to look up the bundle */
- bundle = mac_walk_resources(resource_fork, resource_fork_length, /* BNDL */ 0x424E444C,
- bundle_discriminator, &creator_code, NULL, &bundle_length);
- if (!bundle)
- return err;
-
- /* find the FREF and the icon family */
- pos = 8;
- fref_pos = icn_pos = 0;
- fref_bundleentry_length = icn_bundleentry_length = 0;
- while((pos + 10) <= bundle_length)
- {
- uint32_t this_bundleentry_type = pick_integer_be(bundle, pos + 0, 4);
- uint32_t this_bundleentry_length = pick_integer_be(bundle, pos + 4, 2) + 1;
-
- if (this_bundleentry_type == /* FREF */ 0x46524546)
- {
- fref_pos = pos;
- fref_bundleentry_length = this_bundleentry_length;
- }
- if (this_bundleentry_type == /* ICN# */ 0x49434E23)
- {
- icn_pos = pos;
- icn_bundleentry_length = this_bundleentry_length;
- }
- pos += 6 + this_bundleentry_length * 4;
- }
- if (!fref_pos || !icn_pos)
- return err;
-
- /* look up the FREF */
- for (i = 0; i < fref_bundleentry_length; i++)
- {
- local_id = pick_integer_be(bundle, fref_pos + (i * 4) + 6, 2);
- resource_id = pick_integer_be(bundle, fref_pos + (i * 4) + 8, 2);
-
- fref = mac_get_resource(resource_fork, resource_fork_length,
- /* FREF */ 0x46524546, resource_id, &resource_length);
- if (fref && (resource_length >= 7))
- {
- if (pick_integer_be(fref, 0, 4) == type_code)
- break;
- }
- }
- if (i >= fref_bundleentry_length)
- return err;
-
- /* now look up the icon family */
- resource_id = 0;
- for (i = 0; i < icn_bundleentry_length; i++)
- {
- if (pick_integer_be(bundle, icn_pos + (i * 4) + 6, 2) == local_id)
- {
- resource_id = pick_integer_be(bundle, icn_pos + (i * 4) + 8, 2);
- break;
- }
- }
- if (i >= icn_bundleentry_length)
- return err;
-
- /* fetch 32x32 icons (ICN#, icl4, icl8) */
- if (load_icon((uint32_t *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* ICN# */ 0x49434E23, resource_id, 32, 32, 1, mac_palette_1bpp, true))
- {
- iconinfo->icon32x32_specified = 1;
-
- load_icon((uint32_t *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* icl4 */ 0x69636C34, resource_id, 32, 32, 4, mac_palette_4bpp, false);
- load_icon((uint32_t *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* icl8 */ 0x69636C38, resource_id, 32, 32, 8, mac_palette_8bpp, false);
- }
-
- /* fetch 16x16 icons (ics#, ics4, ics8) */
- if (load_icon((uint32_t *) iconinfo->icon16x16, resource_fork, resource_fork_length,
- /* ics# */ 0x69637323, resource_id, 16, 16, 1, mac_palette_1bpp, true))
- {
- iconinfo->icon16x16_specified = 1;
-
- load_icon((uint32_t *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* ics4 */ 0x69637334, resource_id, 32, 32, 4, mac_palette_4bpp, false);
- load_icon((uint32_t *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* ics8 */ 0x69637338, resource_id, 32, 32, 8, mac_palette_8bpp, false);
- }
-
- return err;
-}
-
-
-
-/*************************************
- *
- * File transfer suggestions
- *
- *************************************/
-
-static imgtoolerr_t mac_image_suggesttransfer(imgtool::partition &partition, const char *path, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- imgtoolerr_t err;
- uint32_t parID;
- mac_str255 filename;
- mac_dirent cat_info;
- imgtool::image &img(partition.image());
- struct mac_l2_imgref *image = get_imgref(img);
- mac_filecategory_t file_category = MAC_FILECATEGORY_DATA;
-
- if (path)
- {
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, false);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- file_category = (cat_info.rsrcLogicalSize > 0) ? MAC_FILECATEGORY_FORKED : MAC_FILECATEGORY_DATA;
- }
-
- mac_suggest_transfer(file_category, suggestions, suggestions_length);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*************************************
-*
-* MacOS Roman Conversion
-*
-*************************************/
-
-static const char32_t macos_roman_code_page[128] =
-{
- // 0x80 - 0x8F
- 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8,
- // 0x90 - 0x9F
- 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC,
- // 0xA0 - 0xAF
- 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF, 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8,
- // 0xB0 - 0xBF
- 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211, 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8,
- // 0xC0 - 0xCF
- 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153,
- // 0xD0 - 0xDF
- 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02,
- // 0xE0 - 0xEF
- 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1, 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4,
- // 0xF0 - 0xFF
- 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7
-};
-
-static imgtool::simple_charconverter charconverter_macos_roman(macos_roman_code_page);
-
-
-/*************************************
- *
- * Module population
- *
- *************************************/
-
-static void generic_mac_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case IMGTOOLINFO_INT_OPEN_IS_STRICT: info->i = 1; break;
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(struct mac_l2_imgref); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct mac_iterator); break;
- case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = ':'; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_EOLN: strcpy(info->s = imgtool_temp_str(), "\r"); 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_CLOSE: /* info->close = mac_image_exit */; break;
- case IMGTOOLINFO_PTR_INFO: info->info = mac_image_info; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = mac_image_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = mac_image_nextenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = mac_image_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = mac_image_readfile; break;
- case IMGTOOLINFO_PTR_LIST_FORKS: info->list_forks = mac_image_listforks; break;
- case IMGTOOLINFO_PTR_GET_ATTRS: info->get_attrs = mac_image_getattrs; break;
- case IMGTOOLINFO_PTR_SET_ATTRS: info->set_attrs = mac_image_setattrs; break;
- case IMGTOOLINFO_PTR_GET_ICON_INFO: info->get_iconinfo = mac_image_geticoninfo; break;
- case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = mac_image_suggesttransfer; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_apple35_mac; break;
- case IMGTOOLINFO_PTR_CHARCONVERTER: info->charconverter = &charconverter_macos_roman; break;
- }
-}
-
-
-
-void mac_mfs_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "mac_mfs"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Mac MFS Floppy"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_FLOPPY_CREATE: info->create = mfs_image_create; break;
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = mfs_image_open; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = mac_image_writefile; break;
-
- default: generic_mac_get_info(imgclass, state, info); break;
- }
-}
-
-
-
-void mac_hfs_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "mac_hfs"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Mac HFS Floppy"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = hfs_image_open; break;
-
- default: generic_mac_get_info(imgclass, state, info); break;
- }
-}
diff --git a/src/tools/imgtool/modules/macbin.cpp b/src/tools/imgtool/modules/macbin.cpp
deleted file mode 100644
index 30400dffdbb..00000000000
--- a/src/tools/imgtool/modules/macbin.cpp
+++ /dev/null
@@ -1,381 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- macbin.cpp
-
- MacBinary filter for use with Mac and ProDOS drivers
-
-*****************************************************************************
-
- MacBinary file format
-
- Offset Length Description
- ------ ------ -----------
- 0 1 [I] Magic byte (0x00)
- 1 64 [I] File name (Pascal String)
- 65 4 [I] File Type Code
- 69 4 [I] File Creator Code
- 73 1 [I] Finder Flags (bits 15-8)
- 74 1 [I] Magic byte (0x00)
- 75 2 [I] File Vertical Position
- 77 2 [I] File Horizontal Position
- 79 2 [I] Window/Folder ID
- 81 1 [I] Protected (bit 0)
- 82 1 [I] Magic byte (0x00)
- 83 4 [I] Data Fork Length
- 87 4 [I] Resource Fork Length
- 91 4 [I] Creation Date
- 95 4 [I] Last Modified Date
- 99 2 [I] "Get Info" comment length
- 101 1 [II] Finder Flags (bits 7-0)
- 102 4 [III] MacBinary III Signature 'mBIN'
- 106 1 [III] Script of Filename
- 107 1 [III] Extended Finder Flags
- 116 4 [II] Unpacked Length
- 120 2 [II] Secondary Header Length
- 122 1 [II] MacBinary II Version Number (II: 0x81, III: 0x82)
- 123 1 [II] Minimum Compatible MacBinary II Version Number (0x81)
- 124 2 [II] CRC of previous 124 bytes
-
- For more information, consult http://www.lazerware.com/formats/macbinary.html
-
- TODO: I believe that the script code is some sort of identifier identifying
- the character set used for the filename. If this is true, we are not
- handling that properly
-
-*****************************************************************************/
-
-#include <string.h>
-
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "macutil.h"
-
-
-
-static uint32_t pad128(uint32_t length)
-{
- if (length % 128)
- length += 128 - (length % 128);
- return length;
-}
-
-
-
-static imgtoolerr_t macbinary_readfile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &destf)
-{
- static const uint32_t attrs[] =
- {
- IMGTOOLATTR_TIME_CREATED,
- IMGTOOLATTR_TIME_LASTMODIFIED,
- IMGTOOLATTR_INT_MAC_TYPE,
- IMGTOOLATTR_INT_MAC_CREATOR,
- IMGTOOLATTR_INT_MAC_FINDERFLAGS,
- IMGTOOLATTR_INT_MAC_COORDX,
- IMGTOOLATTR_INT_MAC_COORDY,
- IMGTOOLATTR_INT_MAC_FINDERFOLDER,
- IMGTOOLATTR_INT_MAC_SCRIPTCODE,
- IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS,
- 0
- };
- imgtoolerr_t err;
- uint8_t header[128];
- const char *basename;
-
- uint32_t type_code = 0x3F3F3F3F;
- uint32_t creator_code = 0x3F3F3F3F;
- uint16_t finder_flags = 0;
- uint16_t coord_x = 0;
- uint16_t coord_y = 0;
- uint16_t finder_folder = 0;
- uint8_t script_code = 0;
- uint8_t extended_flags = 0;
-
- uint32_t creation_time = 0;
- uint32_t lastmodified_time = 0;
- imgtool_attribute attr_values[10];
-
- // get the forks
- std::vector<imgtool::fork_entry> fork_entries;
- err = partition.list_file_forks(filename, fork_entries);
- if (err)
- return err;
-
- const imgtool::fork_entry *data_fork = nullptr;
- const imgtool::fork_entry *resource_fork = nullptr;
- for (const auto &entry : fork_entries)
- {
- switch (entry.type())
- {
- case imgtool::fork_entry::type_t::DATA:
- data_fork = &entry;
- break;
- case imgtool::fork_entry::type_t::RESOURCE:
- resource_fork = &entry;
- break;
- default:
- // do nothing
- break;
- }
- }
-
- /* get the attributes */
- err = partition.get_file_attributes(filename, attrs, attr_values);
- if (err && (ERRORCODE(err) != IMGTOOLERR_UNIMPLEMENTED))
- return err;
- if (err == IMGTOOLERR_SUCCESS)
- {
- creation_time = mac_setup_time(attr_values[0].t);
- lastmodified_time = mac_setup_time(attr_values[1].t);
- type_code = attr_values[2].i;
- creator_code = attr_values[3].i;
- finder_flags = attr_values[4].i;
- coord_x = attr_values[5].i;
- coord_y = attr_values[6].i;
- finder_folder = attr_values[7].i;
- script_code = attr_values[8].i;
- extended_flags = attr_values[9].i;
- }
-
- memset(header, 0, sizeof(header));
-
- /* place filename */
- basename = filename;
- while(basename[strlen(basename) + 1])
- basename += strlen(basename) + 1;
- pascal_from_c_string((unsigned char *) &header[1], 64, basename);
-
- place_integer_be(header, 65, 4, type_code);
- place_integer_be(header, 69, 4, creator_code);
- place_integer_be(header, 73, 1, (finder_flags >> 8) & 0xFF);
- place_integer_be(header, 75, 2, coord_x);
- place_integer_be(header, 77, 2, coord_y);
- place_integer_be(header, 79, 2, finder_folder);
- place_integer_be(header, 83, 4, data_fork ? data_fork->size() : 0);
- place_integer_be(header, 87, 4, resource_fork ? resource_fork->size() : 0);
- place_integer_be(header, 91, 4, creation_time);
- place_integer_be(header, 95, 4, lastmodified_time);
- place_integer_be(header, 101, 1, (finder_flags >> 0) & 0xFF);
- place_integer_be(header, 102, 4, 0x6D42494E);
- place_integer_be(header, 106, 1, script_code);
- place_integer_be(header, 107, 1, extended_flags);
- place_integer_be(header, 122, 1, 0x82);
- place_integer_be(header, 123, 1, 0x81);
- place_integer_be(header, 124, 2, ccitt_crc16(0, header, 124));
-
- destf.write(header, sizeof(header));
-
- if (data_fork)
- {
- err = partition.read_file(filename, "", destf, NULL);
- if (err)
- return err;
-
- destf.fill(0, pad128(data_fork->size()));
- }
-
- if (resource_fork)
- {
- err = partition.read_file(filename, "RESOURCE_FORK", destf, NULL);
- if (err)
- return err;
-
- destf.fill(0, pad128(resource_fork->size()));
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t write_fork(imgtool::partition &partition, const char *filename, const char *fork,
- imgtool::stream &sourcef, uint64_t pos, uint64_t fork_len, util::option_resolution *opts)
-{
- imgtoolerr_t err;
- imgtool::stream::ptr mem_stream;
- size_t len;
-
- if (fork_len > 0)
- {
- mem_stream = imgtool::stream::open_mem(nullptr, 0);
- if (!mem_stream)
- return IMGTOOLERR_OUTOFMEMORY;
-
- sourcef.seek(pos, SEEK_SET);
- len = imgtool::stream::transfer(*mem_stream, sourcef, fork_len);
- if (len < fork_len)
- mem_stream->fill(0, fork_len);
-
- mem_stream->seek(0, SEEK_SET);
- err = partition.write_file(filename, fork, *mem_stream, opts, NULL);
- if (err)
- return err;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t macbinary_writefile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &sourcef, util::option_resolution *opts)
-{
- static const uint32_t attrs[] =
- {
- IMGTOOLATTR_TIME_CREATED,
- IMGTOOLATTR_TIME_LASTMODIFIED,
- IMGTOOLATTR_INT_MAC_TYPE,
- IMGTOOLATTR_INT_MAC_CREATOR,
- IMGTOOLATTR_INT_MAC_FINDERFLAGS,
- IMGTOOLATTR_INT_MAC_COORDX,
- IMGTOOLATTR_INT_MAC_COORDY,
- IMGTOOLATTR_INT_MAC_FINDERFOLDER,
- IMGTOOLATTR_INT_MAC_SCRIPTCODE,
- IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS,
- 0
- };
- imgtoolerr_t err;
- imgtool::image *image = &partition.image();
- uint8_t header[128];
- uint32_t datafork_size;
- uint32_t resourcefork_size;
- uint64_t total_size;
- uint32_t creation_time;
- uint32_t lastmodified_time;
- //int version;
- imgtool_attribute attr_values[10];
-
- uint32_t type_code;
- uint32_t creator_code;
- uint16_t finder_flags;
- uint16_t coord_x;
- uint16_t coord_y;
- uint16_t finder_folder;
- uint8_t script_code = 0;
- uint8_t extended_flags = 0;
-
- /* read in the header */
- memset(header, 0, sizeof(header));
- sourcef.read(header, sizeof(header));
-
- /* check magic and zero fill bytes */
- if (header[0] != 0x00)
- return IMGTOOLERR_CORRUPTFILE;
- if (header[74] != 0x00)
- return IMGTOOLERR_CORRUPTFILE;
- if (header[82] != 0x00)
- return IMGTOOLERR_CORRUPTFILE;
-
- datafork_size = pick_integer_be(header, 83, 4);
- resourcefork_size = pick_integer_be(header, 87, 4);
- total_size = sourcef.size();
-
- /* size of a MacBinary header is always 128 bytes */
- if (total_size - pad128(datafork_size) - pad128(resourcefork_size) != 128)
- return IMGTOOLERR_CORRUPTFILE;
-
- /* check filename length byte */
- if ((header[1] <= 0x00) || (header[1] > 0x3F))
- return IMGTOOLERR_CORRUPTFILE;
-
- /* check the CRC */
- if (pick_integer_be(header, 124, 2) != ccitt_crc16(0, header, 124))
- {
- /* the CRC does not match; this file is MacBinary I */
- //version = 1;
- }
- else if (pick_integer_be(header, 102, 4) != 0x6D42494E)
- {
- /* did not see 'mBIN'; this file is MacBinary II */
- if (header[122] < 0x81)
- return IMGTOOLERR_CORRUPTFILE;
- if (header[123] < 0x81)
- return IMGTOOLERR_CORRUPTFILE;
- //version = 2;
- }
- else
- {
- /* we did see 'mBIN'; this file is MacBinary III */
- if (header[122] < 0x82)
- return IMGTOOLERR_CORRUPTFILE;
- if (header[123] < 0x81)
- return IMGTOOLERR_CORRUPTFILE;
- //version = 3;
- }
-
- type_code = pick_integer_be(header, 65, 4);
- creator_code = pick_integer_be(header, 69, 4);
- finder_flags = pick_integer_be(header, 73, 1) << 8;
- coord_x = pick_integer_be(header, 75, 2);
- coord_y = pick_integer_be(header, 77, 2);
- finder_folder = pick_integer_be(header, 79, 2);
- creation_time = pick_integer_be(header, 91, 4);
- lastmodified_time = pick_integer_be(header, 95, 4);
-
- if (image)
- {
- /* write out both forks */
- err = write_fork(partition, filename, "", sourcef, sizeof(header), datafork_size, opts);
- if (err)
- return err;
- err = write_fork(partition, filename, "RESOURCE_FORK", sourcef, sizeof(header) + pad128(datafork_size), resourcefork_size, opts);
- if (err)
- return err;
-
- /* set up attributes */
- attr_values[0].t = mac_crack_time(creation_time).to_time_t();
- attr_values[1].t = mac_crack_time(lastmodified_time).to_time_t();
- attr_values[2].i = type_code;
- attr_values[3].i = creator_code;
- attr_values[4].i = finder_flags;
- attr_values[5].i = coord_x;
- attr_values[6].i = coord_y;
- attr_values[7].i = finder_folder;
- attr_values[8].i = script_code;
- attr_values[9].i = extended_flags;
-
- err = partition.put_file_attributes(filename, attrs, attr_values);
- if (err)
- return err;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-// this was completely broken - it was calling macbinary_writefile() with a nullptr partition
-#if 0
-static imgtoolerr_t macbinary_checkstream(imgtool::stream &stream, imgtool_suggestion_viability_t *viability)
-{
- imgtoolerr_t err;
-
- err = macbinary_writefile(NULL, NULL, NULL, stream, NULL);
- if (err == IMGTOOLERR_CORRUPTFILE)
- {
- /* the filter returned corrupt; this is not a valid file */
- *viability = SUGGESTION_END;
- err = IMGTOOLERR_SUCCESS;
- }
- else if (err == IMGTOOLERR_SUCCESS)
- {
- /* success; lets recommend this filter */
- *viability = SUGGESTION_RECOMMENDED;
- }
- return err;
-}
-#endif
-
-
-
-void filter_macbinary_getinfo(uint32_t state, union filterinfo *info)
-{
- switch(state)
- {
- case FILTINFO_STR_NAME: info->s = "macbinary"; break;
- case FILTINFO_STR_HUMANNAME: info->s = "MacBinary"; break;
- case FILTINFO_STR_EXTENSION: info->s = "bin"; break;
- case FILTINFO_PTR_READFILE: info->read_file = macbinary_readfile; break;
- case FILTINFO_PTR_WRITEFILE: info->write_file = macbinary_writefile; break;
- //case FILTINFO_PTR_CHECKSTREAM: info->check_stream = macbinary_checkstream; break;
- }
-}
diff --git a/src/tools/imgtool/modules/macutil.cpp b/src/tools/imgtool/modules/macutil.cpp
deleted file mode 100644
index 08c8b84989f..00000000000
--- a/src/tools/imgtool/modules/macutil.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- macutil.cpp
-
- Imgtool Utility code for manipulating certain Apple/Mac data structures
- and conventions
-
-*****************************************************************************/
-
-#include "macutil.h"
-#include "timeconv.h"
-
-
-typedef util::arbitrary_clock<std::uint32_t, 1904, 1, 1, 0, 0, 0, std::ratio<1, 1> > classic_mac_clock;
-
-//-------------------------------------------------
-// mac_crack_time
-//-------------------------------------------------
-
-imgtool::datetime mac_crack_time(uint32_t t)
-{
- classic_mac_clock::duration d(t);
- std::chrono::time_point<classic_mac_clock> tp(d);
- return imgtool::datetime(imgtool::datetime::datetime_type::LOCAL, tp);
-}
-
-
-//-------------------------------------------------
-// mac_setup_time
-//-------------------------------------------------
-
-uint32_t mac_setup_time(const imgtool::datetime &t)
-{
- auto mac_time_point = classic_mac_clock::from_arbitrary_time_point(t.time_point());
- return mac_time_point.time_since_epoch().count();
-}
-
-
-//-------------------------------------------------
-// mac_setup_time
-//-------------------------------------------------
-
-uint32_t mac_setup_time(time_t t)
-{
- imgtool::datetime dt(imgtool::datetime::datetime_type::LOCAL, t);
- return mac_setup_time(dt);
-}
-
-
-//-------------------------------------------------
-// mac_time_now
-//-------------------------------------------------
-
-uint32_t mac_time_now(void)
-{
- imgtool::datetime dt = imgtool::datetime::now(imgtool::datetime::datetime_type::LOCAL);
- return mac_setup_time(dt);
-}
-
-
-//-------------------------------------------------
-// mac_identify_fork
-//-------------------------------------------------
-
-imgtoolerr_t mac_identify_fork(const char *fork_string, mac_fork_t *fork_num)
-{
- if (!strcmp(fork_string, ""))
- *fork_num = MAC_FORK_DATA;
- else if (!strcmp(fork_string, "RESOURCE_FORK"))
- *fork_num = MAC_FORK_RESOURCE;
- else
- return IMGTOOLERR_FORKNOTFOUND;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-void mac_suggest_transfer(mac_filecategory_t file_category, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- suggestions[0].viability = (file_category == MAC_FILECATEGORY_FORKED) ? SUGGESTION_RECOMMENDED : SUGGESTION_POSSIBLE;
- suggestions[0].filter = filter_macbinary_getinfo;
- suggestions[0].fork = NULL;
- suggestions[0].description = NULL;
-
- suggestions[1].viability = (file_category == MAC_FILECATEGORY_TEXT) ? SUGGESTION_RECOMMENDED : SUGGESTION_POSSIBLE;
- suggestions[1].filter = filter_eoln_getinfo;
- suggestions[1].fork = NULL;
- suggestions[1].description = NULL;
-
- suggestions[2].viability = (file_category == MAC_FILECATEGORY_DATA) ? SUGGESTION_RECOMMENDED : SUGGESTION_POSSIBLE;
- suggestions[2].filter = NULL;
- suggestions[2].fork = "";
- suggestions[2].description = "Raw (data fork)";
-
- suggestions[3].viability = SUGGESTION_POSSIBLE;
- suggestions[3].filter = NULL;
- suggestions[3].fork = "RESOURCE_FORK";
- suggestions[3].description = "Raw (resource fork)";
-}
-
-
-
-void pascal_from_c_string(unsigned char *pstring, size_t pstring_len, const char *cstring)
-{
- size_t cstring_len, i;
-
- cstring_len = strlen(cstring);
- pstring[0] = std::min(cstring_len, pstring_len - 1);
-
- for (i = 0; i < pstring[0]; i++)
- pstring[1 + i] = cstring[i];
- while(i < pstring_len - 1)
- pstring[1 + i++] = '\0';
-}
diff --git a/src/tools/imgtool/modules/macutil.h b/src/tools/imgtool/modules/macutil.h
deleted file mode 100644
index 0ab3315874b..00000000000
--- a/src/tools/imgtool/modules/macutil.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- macutil.h
-
- Imgtool Utility code for manipulating certain Apple/Mac data structures
- and conventions
-
-*****************************************************************************/
-
-#ifndef MACUTIL_H
-#define MACUTIL_H
-
-#include "imgtool.h"
-
-enum mac_fork_t
-{
- MAC_FORK_DATA,
- MAC_FORK_RESOURCE
-};
-
-enum mac_filecategory_t
-{
- MAC_FILECATEGORY_DATA,
- MAC_FILECATEGORY_TEXT,
- MAC_FILECATEGORY_FORKED
-};
-
-
-/* converting Classic Mac OS time <==> Imgtool time */
-imgtool::datetime mac_crack_time(uint32_t t);
-uint32_t mac_setup_time(const imgtool::datetime &t);
-uint32_t mac_setup_time(time_t t);
-uint32_t mac_time_now(void);
-
-imgtoolerr_t mac_identify_fork(const char *fork_string, mac_fork_t *fork_num);
-
-void mac_suggest_transfer(mac_filecategory_t file_category, imgtool_transfer_suggestion *suggestions, size_t suggestions_length);
-
-void pascal_from_c_string(unsigned char *pstring, size_t pstring_len, const char *cstring);
-
-#endif /* MACUTIL_H */
diff --git a/src/tools/imgtool/modules/os9.cpp b/src/tools/imgtool/modules/os9.cpp
index cc016250c31..97fdcb9e209 100644
--- a/src/tools/imgtool/modules/os9.cpp
+++ b/src/tools/imgtool/modules/os9.cpp
@@ -8,13 +8,16 @@
****************************************************************************/
-#include <time.h>
-
#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "formats/coco_dsk.h"
#include "iflopimg.h"
+#include "formats/coco_dsk.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <cstdio>
+#include <ctime>
+
enum creation_policy_t
{
CREATE_NONE,
@@ -44,7 +47,7 @@ struct os9_diskinfo
unsigned int octal_track_density : 1;
char name[33];
- uint8_t *allocation_bitmap;
+ uint8_t allocation_bitmap[65536];
};
@@ -96,20 +99,13 @@ static void pick_string(const void *ptr, size_t offset, size_t length, char *des
-static void place_string(void *ptr, size_t offset, size_t length, const char *s)
+static void place_string(uint8_t *bptr, size_t length, const char *s)
{
- size_t i;
- uint8_t b;
- uint8_t *bptr;
-
- bptr = (uint8_t *) ptr;
- bptr += offset;
-
bptr[0] = 0x80;
- for (i = 0; s[i] && (i < length); i++)
+ for (size_t i = 0; s[i] && (i < length); i++)
{
- b = ((uint8_t) s[i]) & 0x7F;
+ uint8_t b = ((uint8_t) s[i]) & 0x7F;
if (s[i+1] == '\0')
b |= 0x80;
bptr[i] = b;
@@ -228,7 +224,7 @@ static int os9_interpret_dirent(void *entry, char **filename, uint32_t *lsn, int
entry_b[i] &= 0x7F;
entry_b[i+1] = '\0';
- *lsn = pick_integer_be(entry, 29, 3);
+ *lsn = get_u24be((uint8_t *) &entry_b[29]);
if (strcmp(entry_b, ".") && strcmp(entry_b, ".."))
*filename = entry_b;
return *filename != NULL;
@@ -257,10 +253,10 @@ static imgtoolerr_t os9_decode_file_header(imgtool::image &image,
return err;
info->lsn = lsn;
- attributes = pick_integer_be(header, 0, 1);
- info->owner_id = pick_integer_be(header, 1, 2);
- info->link_count = pick_integer_be(header, 8, 1);
- info->file_size = pick_integer_be(header, 9, 4);
+ attributes = header[0];
+ info->owner_id = get_u16be(&header[1]);
+ info->link_count = header[8];
+ info->file_size = get_u32be(&header[9]);
info->directory = (attributes & 0x80) ? 1 : 0;
info->non_sharable = (attributes & 0x40) ? 1 : 0;
info->public_execute = (attributes & 0x20) ? 1 : 0;
@@ -275,11 +271,11 @@ static imgtoolerr_t os9_decode_file_header(imgtool::image &image,
/* read all sector map entries */
max_entries = (disk_info->sector_size - 16) / 5;
- max_entries = (std::min<std::size_t>)(max_entries, ARRAY_LENGTH(info->sector_map) - 1);
+ max_entries = (std::min<std::size_t>)(max_entries, std::size(info->sector_map) - 1);
for (i = 0; i < max_entries; i++)
{
- lsn = pick_integer_be(header, 16 + (i * 5) + 0, 3);
- count = pick_integer_be(header, 16 + (i * 5) + 3, 2);
+ lsn = get_u24be(&header[16 + (i * 5) + 0]);
+ count = get_u16be(&header[16 + (i * 5) + 3]);
if (count <= 0)
break;
@@ -393,7 +389,7 @@ static imgtoolerr_t os9_set_file_size(imgtool::image &image,
/* first find out the size of our sector map */
sector_map_length = 0;
lsn = 0;
- while((lsn < current_lsn_count) && (sector_map_length < ARRAY_LENGTH(file_info->sector_map)))
+ while((lsn < current_lsn_count) && (sector_map_length < std::size(file_info->sector_map)))
{
if (file_info->sector_map[sector_map_length].count == 0)
return os9_corrupt_file_error(file_info);
@@ -434,7 +430,7 @@ static imgtoolerr_t os9_set_file_size(imgtool::image &image,
{
file_info->sector_map[sector_map_length - 1].count++;
}
- else if (sector_map_length >= ARRAY_LENGTH(file_info->sector_map))
+ else if (sector_map_length >= std::size(file_info->sector_map))
{
return IMGTOOLERR_NOSPACE;
}
@@ -456,15 +452,15 @@ static imgtoolerr_t os9_set_file_size(imgtool::image &image,
return err;
file_info->file_size = new_size;
- place_integer_be(header, 9, 4, file_info->file_size);
+ put_u32be(&header[9], file_info->file_size);
/* do we have to write the sector map? */
if (sector_map_length >= 0)
{
- for (i = 0; i < (std::min<std::size_t>)(sector_map_length + 1, ARRAY_LENGTH(file_info->sector_map)); i++)
+ for (i = 0; i < (std::min<std::size_t>)(sector_map_length + 1, std::size(file_info->sector_map)); i++)
{
- place_integer_be(header, 16 + (i * 5) + 0, 3, file_info->sector_map[i].lsn);
- place_integer_be(header, 16 + (i * 5) + 3, 2, file_info->sector_map[i].count);
+ put_u24be(&header[16 + (i * 5) + 0], file_info->sector_map[i].lsn);
+ put_u16be(&header[16 + (i * 5) + 3], file_info->sector_map[i].count);
}
}
@@ -567,7 +563,7 @@ static imgtoolerr_t os9_lookup_path(imgtool::image &img, const char *path,
/* write the file */
memset(block, 0, sizeof(block));
- place_integer_be(block, 0, 1, 0x1B | ((create == CREATE_DIR) ? 0x80 : 0x00));
+ block[0] = 0x1B | ((create == CREATE_DIR) ? 0x80 : 0x00);
err = os9_write_lsn(img, allocated_lsn, 0, block, sizeof(block));
if (err)
goto done;
@@ -585,8 +581,8 @@ static imgtoolerr_t os9_lookup_path(imgtool::image &img, const char *path,
/* now prepare the directory entry */
memset(entry, 0, sizeof(entry));
- place_string(entry, 0, 28, path);
- place_integer_be(entry, 29, 3, allocated_lsn);
+ place_string(&entry[0], 28, path);
+ put_u24be(&entry[29], allocated_lsn);
/* now write the directory entry */
entry_index = dir_size;
@@ -638,20 +634,19 @@ static imgtoolerr_t os9_diskimage_open(imgtool::image &image, imgtool::stream::p
if (ferr)
return imgtool_floppy_error(ferr);
- info->total_sectors = pick_integer_be(header, 0, 3);
- track_size_in_sectors = pick_integer_be(header, 3, 1);
- info->allocation_bitmap_bytes = pick_integer_be(header, 4, 2);
- info->cluster_size = pick_integer_be(header, 6, 2);
- info->root_dir_lsn = pick_integer_be(header, 8, 3);
- info->owner_id = pick_integer_be(header, 11, 2);
-// attributes =
- pick_integer_be(header, 13, 1);
- info->disk_id = pick_integer_be(header, 14, 2);
- info->format_flags = pick_integer_be(header, 16, 1);
- info->sectors_per_track = pick_integer_be(header, 17, 2);
- info->bootstrap_lsn = pick_integer_be(header, 21, 3);
- info->bootstrap_size = pick_integer_be(header, 24, 2);
- info->sector_size = pick_integer_be(header, 104, 2);
+ info->total_sectors = get_u24be(&header[ 0]);
+ track_size_in_sectors = header[ 3];
+ info->allocation_bitmap_bytes = get_u16be(&header[ 4]);
+ info->cluster_size = get_u16be(&header[ 6]);
+ info->root_dir_lsn = get_u24be(&header[ 8]);
+ info->owner_id = get_u16be(&header[ 11]);
+// attributes = header[ 13];
+ info->disk_id = get_u16be(&header[ 14]);
+ info->format_flags = header[ 16];
+ info->sectors_per_track = get_u16be(&header[ 17]);
+ info->bootstrap_lsn = get_u24be(&header[ 21]);
+ info->bootstrap_size = get_u16be(&header[ 24]);
+ info->sector_size = get_u16be(&header[104]);
info->sides = (info->format_flags & 0x01) ? 2 : 1;
info->double_density = (info->format_flags & 0x02) ? 1 : 0;
@@ -670,10 +665,7 @@ static imgtoolerr_t os9_diskimage_open(imgtool::image &image, imgtool::stream::p
return IMGTOOLERR_CORRUPTIMAGE;
/* is the allocation bitmap too big? */
- info->allocation_bitmap = (uint8_t*)image.malloc(info->allocation_bitmap_bytes);
- if (!info->allocation_bitmap)
- return IMGTOOLERR_OUTOFMEMORY;
- memset(info->allocation_bitmap, 0, info->allocation_bitmap_bytes);
+ memset(&info->allocation_bitmap[0], 0, info->allocation_bitmap_bytes);
/* sectors per track and track size don't jive? */
if (info->sectors_per_track != track_size_in_sectors)
@@ -747,30 +739,30 @@ static imgtoolerr_t os9_diskimage_create(imgtool::image &img, imgtool::stream::p
format_flags = ((heads > 1) ? 0x01 : 0x00) | ((tracks > 40) ? 0x02 : 0x00);
memset(&header[0], 0, sector_bytes);
- place_integer_be(&header[0], 0, 3, heads * tracks * sectors);
- place_integer_be(&header[0], 3, 1, sectors);
- place_integer_be(&header[0], 4, 2, (allocation_bitmap_bits + 7) / 8);
- place_integer_be(&header[0], 6, 2, cluster_size);
- place_integer_be(&header[0], 8, 3, 1 + allocation_bitmap_lsns);
- place_integer_be(&header[0], 11, 2, owner_id);
- place_integer_be(&header[0], 13, 1, attributes);
- place_integer_be(&header[0], 14, 2, disk_id);
- place_integer_be(&header[0], 16, 1, format_flags);
- place_integer_be(&header[0], 17, 2, sectors);
- place_string(&header[0], 31, 32, title);
- place_integer_be(&header[0], 103, 2, sector_bytes / 256);
+ put_u24be(&header[ 0], heads * tracks * sectors);
+ header[ 3] = sectors;
+ put_u16be(&header[ 4], (allocation_bitmap_bits + 7) / 8);
+ put_u16be(&header[ 6], cluster_size);
+ put_u24be(&header[ 8], 1 + allocation_bitmap_lsns);
+ put_u16be(&header[ 11], owner_id);
+ header[ 13] = attributes;
+ put_u16be(&header[ 14], disk_id);
+ header[ 16] = format_flags;
+ put_u16be(&header[ 17], sectors);
+ place_string(&header[ 31], 32, title);
+ put_u16be(&header[103], sector_bytes / 256);
/* path descriptor options */
- place_integer_be(&header[0], 0x3f+0x00, 1, 1); /* device class */
- place_integer_be(&header[0], 0x3f+0x01, 1, 1); /* drive number */
- place_integer_be(&header[0], 0x3f+0x03, 1, 0x20); /* device type */
- place_integer_be(&header[0], 0x3f+0x04, 1, 1); /* density capability */
- place_integer_be(&header[0], 0x3f+0x05, 2, tracks); /* number of tracks */
- place_integer_be(&header[0], 0x3f+0x07, 1, heads); /* number of sides */
- place_integer_be(&header[0], 0x3f+0x09, 2, sectors); /* sectors per track */
- place_integer_be(&header[0], 0x3f+0x0b, 2, sectors); /* sectors on track zero */
- place_integer_be(&header[0], 0x3f+0x0d, 1, 3); /* sector interleave factor */
- place_integer_be(&header[0], 0x3f+0x0e, 1, 8); /* default sectors per allocation */
+ header[0x3f+0x00] = 1; /* device class */
+ header[0x3f+0x01] = 1; /* drive number */
+ header[0x3f+0x03] = 0x20; /* device type */
+ header[0x3f+0x04] = 1; /* density capability */
+ put_u16be(&header[0x3f+0x05], tracks); /* number of tracks */
+ header[0x3f+0x07] = heads; /* number of sides */
+ put_u16be(&header[0x3f+0x09], sectors); /* sectors per track */
+ put_u16be(&header[0x3f+0x0b], sectors); /* sectors on track zero */
+ header[0x3f+0x0d] = 3; /* sector interleave factor */
+ header[0x3f+0x0e] = 8; /* default sectors per allocation */
err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */
if (err)
@@ -824,8 +816,8 @@ static imgtoolerr_t os9_diskimage_create(imgtool::image &img, imgtool::stream::p
header[0x0D] = (uint8_t) (ltime->tm_year % 100);
header[0x0E] = (uint8_t) ltime->tm_mon;
header[0x0F] = (uint8_t) ltime->tm_mday;
- place_integer_be(&header[0], 0x10, 3, 1 + allocation_bitmap_lsns + 1);
- place_integer_be(&header[0], 0x13, 2, 8);
+ put_u24be(&header[0x10], 1 + allocation_bitmap_lsns + 1);
+ put_u16be(&header[0x13], 8);
err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 1 + allocation_bitmap_lsns, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */
if (err)
@@ -929,7 +921,7 @@ static imgtoolerr_t os9_diskimage_nextenum(imgtool::directory &enumeration, imgt
}
/* if the filename is ".", the file should point to the current directory */
- if (!strcmp(filename, ".") && (pick_integer_be(dir_entry, 29, 3) != os9enum->dir_info.lsn))
+ if (!strcmp(filename, ".") && (get_u24be(&dir_entry[29]) != os9enum->dir_info.lsn))
{
imgtool_warn("Directory \".\" does not point back to same directory");
}
@@ -946,14 +938,14 @@ static imgtoolerr_t os9_diskimage_nextenum(imgtool::directory &enumeration, imgt
while(!filename[0] || !strcmp(filename, ".") || !strcmp(filename, ".."));
/* read file attributes */
- lsn = pick_integer_be(dir_entry, 29, 3);
+ lsn = get_u24be(&dir_entry[29]);
err = os9_decode_file_header(enumeration.image(), lsn, &file_info);
if (err)
return err;
/* fill out imgtool_dirent structure */
- snprintf(ent.filename, ARRAY_LENGTH(ent.filename), "%s", filename);
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "%c%c%c%c%c%c%c%c",
+ snprintf(ent.filename, std::size(ent.filename), "%s", filename);
+ snprintf(ent.attr, std::size(ent.attr), "%c%c%c%c%c%c%c%c",
file_info.directory ? 'd' : '-',
file_info.non_sharable ? 's' : '-',
file_info.public_execute ? 'x' : '-',
@@ -1143,7 +1135,7 @@ static imgtoolerr_t os9_diskimage_delete(imgtool::partition &partition, const ch
if (err)
return err;
- for (i = 0; (i < ARRAY_LENGTH(file_info.sector_map)) && file_info.sector_map[i].count; i++)
+ for (i = 0; (i < std::size(file_info.sector_map)) && file_info.sector_map[i].count; i++)
{
lsn = file_info.sector_map[i].lsn;
for (j = 0; j < file_info.sector_map[i].count; j++)
@@ -1185,10 +1177,10 @@ static imgtoolerr_t os9_diskimage_createdir(imgtool::partition &partition, const
/* create intial directories */
memset(dir_data, 0, sizeof(dir_data));
- place_string(dir_data, 0, 32, "..");
- place_integer_be(dir_data, 29, 3, parent_lsn);
- place_string(dir_data, 32, 32, ".");
- place_integer_be(dir_data, 61, 3, file_info.lsn);
+ place_string(&dir_data[ 0], 32, "..");
+ put_u24be(&dir_data[29], parent_lsn);
+ place_string(&dir_data[32], 32, ".");
+ put_u24be(&dir_data[61], file_info.lsn);
err = os9_write_lsn(image, file_info.sector_map[0].lsn, 0, dir_data, sizeof(dir_data));
if (err)
diff --git a/src/tools/imgtool/modules/pc_flop.cpp b/src/tools/imgtool/modules/pc_flop.cpp
index 211b7f7b938..6a242d16abf 100644
--- a/src/tools/imgtool/modules/pc_flop.cpp
+++ b/src/tools/imgtool/modules/pc_flop.cpp
@@ -9,11 +9,14 @@
****************************************************************************/
#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "formats/pc_dsk.h"
#include "fat.h"
#include "iflopimg.h"
+#include "formats/pc_dsk_legacy.h"
+
+#include "multibyte.h"
+#include "opresolv.h"
+
#define FAT_SECLEN 512
@@ -31,10 +34,10 @@ static imgtoolerr_t fat_image_create(imgtool::image &image, imgtool::stream::ptr
/* set up just enough of a boot sector to specify geometry */
memset(buffer, 0, sizeof(buffer));
- place_integer_le(buffer, 24, 2, sectors);
- place_integer_le(buffer, 26, 2, heads);
- place_integer_le(buffer, 19, 2, (uint16_t) (((uint64_t) tracks * heads * sectors) >> 0));
- place_integer_le(buffer, 32, 4, (uint16_t) (((uint64_t) tracks * heads * sectors) >> 16));
+ put_u16le(&buffer[24], sectors);
+ put_u16le(&buffer[26], heads);
+ put_u16le(&buffer[19], uint16_t((uint64_t(tracks) * heads * sectors) >> 0));
+ put_u32le(&buffer[32], uint16_t((uint64_t(tracks) * heads * sectors) >> 16));
err = image.write_block(0, buffer);
if (err)
goto done;
@@ -44,7 +47,7 @@ static imgtoolerr_t fat_image_create(imgtool::image &image, imgtool::stream::ptr
imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_CREATE_PARTITION);
/* actually create the partition */
- err = fat_partition_create(image, 0, ((uint64_t) tracks) * heads * sectors);
+ err = fat_partition_create(image, 0, uint64_t(tracks) * heads * sectors);
if (err)
goto done;
@@ -64,11 +67,11 @@ static imgtoolerr_t fat_image_get_geometry(imgtool::image &image, uint32_t *trac
if (err)
return err;
- total_sectors = pick_integer_le(buffer, 19, 2)
- | (pick_integer_le(buffer, 32, 4) << 16);
+ total_sectors = get_u16le(&buffer[19])
+ | uint64_t(get_u32le(&buffer[32]) << 16);
- *sectors = pick_integer_le(buffer, 24, 2);
- *heads = pick_integer_le(buffer, 26, 2);
+ *sectors = get_u16le(&buffer[24]);
+ *heads = get_u16le(&buffer[26]);
*tracks = total_sectors / *heads / *sectors;
return IMGTOOLERR_SUCCESS;
}
diff --git a/src/tools/imgtool/modules/pc_hard.cpp b/src/tools/imgtool/modules/pc_hard.cpp
index c04ad33cce6..353a6b5dac5 100644
--- a/src/tools/imgtool/modules/pc_hard.cpp
+++ b/src/tools/imgtool/modules/pc_hard.cpp
@@ -50,9 +50,11 @@
****************************************************************************/
#include "imgtool.h"
-#include "formats/imageutl.h"
#include "imghd.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
#define FAT_SECLEN 512
OPTION_GUIDE_START( pc_chd_create_optionguide )
@@ -103,15 +105,12 @@ static pc_chd_image_info *pc_chd_get_image_info(imgtool::image &image)
static void pc_chd_locate_block(imgtool::image &image, uint64_t block, uint32_t *cylinder, uint32_t *head, uint32_t *sector)
{
- pc_chd_image_info *info;
- const hard_disk_info *hd_info;
-
- info = pc_chd_get_image_info(image);
- hd_info = imghd_get_header(&info->hard_disk);
+ pc_chd_image_info *info = pc_chd_get_image_info(image);
+ const auto &hd_info = imghd_get_header(&info->hard_disk);
- *sector = block % hd_info->sectors;
- *head = (block / hd_info->sectors) % hd_info->heads;
- *cylinder = block / hd_info->sectors / hd_info->heads;
+ *sector = block % hd_info.sectors;
+ *head = (block / hd_info.sectors) % hd_info.heads;
+ *cylinder = block / hd_info.sectors / hd_info.heads;
}
@@ -168,16 +167,16 @@ static imgtoolerr_t pc_chd_partition_create(imgtool::image &image, int partition
/* fill out the partition entry */
partition_entry = &header_block[446 + (partition_index * 16)];
- place_integer_le(partition_entry, 0, 1, 0x80);
- place_integer_le(partition_entry, 1, 1, first_head);
- place_integer_le(partition_entry, 2, 1, ((first_sector & 0x3F) | (first_cylinder >> 8 << 2)));
- place_integer_le(partition_entry, 3, 1, first_cylinder);
- place_integer_le(partition_entry, 4, 1, partition_type);
- place_integer_le(partition_entry, 5, 1, last_head);
- place_integer_le(partition_entry, 6, 1, ((last_sector & 0x3F) | (last_cylinder >> 8 << 2)));
- place_integer_le(partition_entry, 7, 1, last_cylinder);
- place_integer_le(partition_entry, 8, 4, first_block);
- place_integer_le(partition_entry, 12, 4, block_count);
+ partition_entry[0] = 0x80;
+ partition_entry[1] = first_head;
+ partition_entry[2] = ((first_sector & 0x3F) | (first_cylinder >> 8 << 2));
+ partition_entry[3] = first_cylinder;
+ partition_entry[4] = partition_type;
+ partition_entry[5] = last_head;
+ partition_entry[6] = ((last_sector & 0x3F) | (last_cylinder >> 8 << 2));
+ partition_entry[7] = last_cylinder;
+ put_u32le(&partition_entry[ 8], first_block);
+ put_u32le(&partition_entry[12], block_count);
/* write the partition header */
err = image.write_block(0, header_block);
@@ -193,7 +192,6 @@ done:
static imgtoolerr_t pc_chd_read_partition_header(imgtool::image &image)
{
imgtoolerr_t err;
- int i;
const uint8_t *partition_info;
pc_chd_image_info *info;
uint8_t buffer[FAT_SECLEN];
@@ -209,7 +207,7 @@ static imgtoolerr_t pc_chd_read_partition_header(imgtool::image &image)
if ((buffer[510] != 0x55) || (buffer[511] != 0xAA))
return IMGTOOLERR_CORRUPTIMAGE;
- for (i = 0; i < ARRAY_LENGTH(info->partitions); i++)
+ for (int i = 0; i < std::size(info->partitions); i++)
{
partition_info = &buffer[446 + i * 16];
@@ -221,8 +219,8 @@ static imgtoolerr_t pc_chd_read_partition_header(imgtool::image &image)
info->partitions[i].ending_track = ((partition_info[6] << 2) & 0xFF00) | partition_info[7];
info->partitions[i].ending_sector = partition_info[6] & 0x3F;
- info->partitions[i].sector_index = pick_integer_le(partition_info, 8, 4);
- info->partitions[i].total_sectors = pick_integer_le(partition_info, 12, 4);
+ info->partitions[i].sector_index = get_u32le(&partition_info[ 8]);
+ info->partitions[i].total_sectors = get_u32le(&partition_info[12]);
if (info->partitions[i].starting_track > info->partitions[i].ending_track)
return IMGTOOLERR_CORRUPTIMAGE;
@@ -310,15 +308,12 @@ static void pc_chd_image_close(imgtool::image &image)
static imgtoolerr_t pc_chd_image_get_geometry(imgtool::image &image, uint32_t *tracks, uint32_t *heads, uint32_t *sectors)
{
- pc_chd_image_info *info;
- const hard_disk_info *hd_info;
-
- info = pc_chd_get_image_info(image);
- hd_info = imghd_get_header(&info->hard_disk);
+ pc_chd_image_info *info = pc_chd_get_image_info(image);
+ const auto &hd_info = imghd_get_header(&info->hard_disk);
- *tracks = hd_info->cylinders;
- *heads = hd_info->heads;
- *sectors = hd_info->sectors;
+ *tracks = hd_info.cylinders;
+ *heads = hd_info.heads;
+ *sectors = hd_info.sectors;
return IMGTOOLERR_SUCCESS;
}
@@ -327,13 +322,11 @@ static imgtoolerr_t pc_chd_image_get_geometry(imgtool::image &image, uint32_t *t
static uint32_t pc_chd_calc_lbasector(pc_chd_image_info &info, uint32_t track, uint32_t head, uint32_t sector)
{
uint32_t lbasector;
- const hard_disk_info *hd_info;
-
- hd_info = imghd_get_header(&info.hard_disk);
+ const auto &hd_info = imghd_get_header(&info.hard_disk);
lbasector = track;
- lbasector *= hd_info->heads;
+ lbasector *= hd_info.heads;
lbasector += head;
- lbasector *= hd_info->sectors;
+ lbasector *= hd_info.sectors;
lbasector += sector;
return lbasector;
}
@@ -345,7 +338,7 @@ static imgtoolerr_t pc_chd_image_readsector(imgtool::image &image, uint32_t trac
pc_chd_image_info *info = pc_chd_get_image_info(image);
// get the sector size and resize the buffer
- uint32_t sector_size = imghd_get_header(&info->hard_disk)->sectorbytes;
+ uint32_t sector_size = imghd_get_header(&info->hard_disk).sectorbytes;
try { buffer.resize(sector_size); }
catch (std::bad_alloc const &) { return IMGTOOLERR_OUTOFMEMORY; }
diff --git a/src/tools/imgtool/modules/prodos.cpp b/src/tools/imgtool/modules/prodos.cpp
deleted file mode 100644
index 6db41ae529b..00000000000
--- a/src/tools/imgtool/modules/prodos.cpp
+++ /dev/null
@@ -1,2267 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- prodos.cpp
-
- Apple II ProDOS disk images
-
-*****************************************************************************
-
- Notes:
- - ProDOS disks are split into 512 byte blocks.
-
- ProDOS directory structure:
-
- Offset Length Description
- ------ ------ -----------
- 0 2 ???
- 2 2 Next block (0 if end)
- 4 39 Directory Entry
- 43 39 Directory Entry
- ...
- 472 39 Directory Entry
- 511 1 ???
-
-
- ProDOS directory entry structure:
-
- Offset Length Description
- ------ ------ -----------
- 0 1 Storage type (bits 7-4)
- 10 - Seedling File (1 block)
- 20 - Sapling File (2-256 blocks)
- 30 - Tree File (257-32768 blocks)
- 40 - Pascal Areas on ProFile HDs (???)
- 50 - GS/OS Extended File (data and rsrc fork)
- E0 - Subdirectory Header
- F0 - Volume Header
- 1 15 File name (NUL padded)
- 16 1 File type
- 17 2 Key pointer
- 19 2 Blocks used
- 21 3 File size
- 24 4 Creation date
- 28 1 ProDOS version that created the file
- 29 1 Minimum ProDOS version needed to read the file
- 30 1 Access byte
- 31 2 Auxilary file type
- 33 4 Last modified date
- 37 2 Header pointer
-
-
- In "seedling files", the key pointer points to a single block that is the
- whole file. In "sapling files", the key pointer points to an index block
- that contains 256 2-byte index pointers that point to the actual blocks of
- the files. These 2-byte values are not contiguous; the low order byte is
- in the first half of the block, and the high order byte is in the second
- half of the block. In "tree files", the key pointer points to an index
- block of index blocks.
-
- ProDOS dates are 32-bit little endian values
-
- bits 0- 4 Day
- bits 5- 8 Month (0-11)
- bits 9-15 Year (0-49 is 2000-2049, 50-99 is 1950-1999)
- bits 16-21 Minute
- bits 24-28 Hour
-
-
- ProDOS directory and volume headers have this information:
-
- Offset Length Description
- ------ ------ -----------
- 31 1 Length of the entry; generally is 39
- 32 1 Number of entries per block; generally is 13
- 33 2 Active entry count in directory
- 35 2 Volume bitmap block number
- 37 2 Total blocks on volume
-
- GS/OS Extended Files (storage type $5) point to an extended key block that
- contains information about the two forks. The first half of the extended
- key block contains info about the data form, and the second half the
- resource fork. Both sides have the following format:
-
- Offset Length Description
- ------ ------ -----------
- 0 1 Storage type (bits 3-0, unlike the directory entry)
- 1 2 Key pointer
- 3 2 Blocks used
- 5 3 File size
- 8 1 Size of secondary info #1 (must be 18 to be valid)
- 9 1 Secondary info #1 type (1=FInfo 2=xFInfo)
- 10 16 FInfo or xFInfo
- 26 1 Size of secondary info #2 (must be 18 to be valid)
- 27 1 Secondary info #2 type (1=FInfo 2=xFInfo)
- 28 16 FInfo or xFInfo
-
- FInfo format:
-
- Offset Length Description
- ------ ------ -----------
- 0 4 File type
- 4 4 File creator
- 8 2 Finder flags
- 10 2 X Coordinate
- 12 2 Y Coordinate
- 14 2 Finder folder
-
- xFInfo format:
-
- Offset Length Description
- ------ ------ -----------
- 0 2 Icon ID
- 2 6 Reserved
- 8 1 Script Code
- 9 1 Extended flags
- 10 2 Comment ID
- 12 4 Put Away Directory
-
-
- For more info, consult ProDOS technical note #25
- (http://web.pdx.edu/~heiss/technotes/pdos/tn.pdos.25.html)
-
-*****************************************************************************/
-
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "formats/ap2_dsk.h"
-#include "formats/ap_dsk35.h"
-#include "iflopimg.h"
-#include "macutil.h"
-
-#define ROOTDIR_BLOCK 2
-#define BLOCK_SIZE 512
-
-struct prodos_diskinfo
-{
- imgtoolerr_t (*load_block)(imgtool::image &image, int block, void *buffer);
- imgtoolerr_t (*save_block)(imgtool::image &image, int block, const void *buffer);
- uint8_t dirent_size;
- uint8_t dirents_per_block;
- uint16_t volume_bitmap_block;
- uint16_t total_blocks;
-};
-
-struct prodos_direnum
-{
- uint32_t block;
- uint32_t index;
- uint8_t block_data[BLOCK_SIZE];
-};
-
-struct prodos_dirent
-{
- char filename[16];
- uint8_t storage_type;
- uint16_t extkey_pointer;
- uint16_t key_pointer[2];
- uint32_t filesize[2];
- int depth[2];
- uint32_t lastmodified_time;
- uint32_t creation_time;
-
- /* FInfo */
- uint32_t file_type;
- uint32_t file_creator;
- uint16_t finder_flags;
- uint16_t coord_x;
- uint16_t coord_y;
- uint16_t finder_folder;
-
- /* xFInfo */
- uint16_t icon_id;
- uint8_t script_code;
- uint8_t extended_flags;
- uint16_t comment_id;
- uint32_t putaway_directory;
-};
-
-enum creation_policy_t
-{
- CREATE_NONE,
- CREATE_FILE,
- CREATE_DIR
-};
-
-
-
-static imgtool::datetime prodos_crack_time(uint32_t prodos_time)
-{
- util::arbitrary_datetime dt;
- dt.second = 0;
- dt.minute = ((prodos_time >> 16) & 0x3F);
- dt.hour = ((prodos_time >> 24) & 0x1F);
- dt.day_of_month = ((prodos_time >> 0) & 0x1F);
- dt.month = ((prodos_time >> 5) & 0x0F) + 1;
- dt.year = ((prodos_time >> 9) & 0x7F) + 1900;
- if (dt.year <= 1949)
- dt.year += 100;
-
- return imgtool::datetime(imgtool::datetime::datetime_type::LOCAL, dt);
-}
-
-
-
-static uint32_t prodos_setup_time(time_t ansi_time)
-{
- struct tm t;
- uint32_t result = 0;
-
- t = *localtime(&ansi_time);
- if ((t.tm_year >= 100) && (t.tm_year <= 149))
- t.tm_year -= 100;
-
- result |= (((uint32_t) t.tm_min) & 0x003F) << 16;
- result |= (((uint32_t) t.tm_hour) & 0x001F) << 24;
- result |= (((uint32_t) t.tm_mday) & 0x001F) << 0;
- result |= (((uint32_t) t.tm_mon) & 0x000F) << 5;
- result |= (((uint32_t) t.tm_year) & 0x007F) << 9;
- return result;
-}
-
-
-
-static uint32_t prodos_time_now(void)
-{
- time_t now;
- time(&now);
- return prodos_setup_time(now);
-}
-
-
-
-static int is_file_storagetype(uint8_t storage_type)
-{
- return ((storage_type >= 0x10) && (storage_type <= 0x3F))
- || ((storage_type >= 0x50) && (storage_type <= 0x5F));
-}
-
-
-
-static int is_normalfile_storagetype(uint8_t storage_type)
-{
- return ((storage_type >= 0x10) && (storage_type <= 0x3F));
-}
-
-
-
-static int is_extendedfile_storagetype(uint8_t storage_type)
-{
- return ((storage_type >= 0x50) && (storage_type <= 0x5F));
-}
-
-
-
-static int is_dir_storagetype(uint8_t storage_type)
-{
- return (storage_type >= 0xE0) && (storage_type <= 0xEF);
-}
-
-
-
-static prodos_diskinfo *get_prodos_info(imgtool::image &image)
-{
- prodos_diskinfo *info;
- info = (prodos_diskinfo *) imgtool_floppy_extrabytes(image);
- return info;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static void prodos_find_block_525(imgtool::image &image, int block,
- uint32_t *track, uint32_t *head, uint32_t *sector1, uint32_t *sector2)
-{
- static const uint8_t skewing[] =
- {
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
- 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F
- };
-
- block *= 2;
-
- *track = block / APPLE2_SECTOR_COUNT;
- *head = 0;
- *sector1 = skewing[block % APPLE2_SECTOR_COUNT + 0];
- *sector2 = skewing[block % APPLE2_SECTOR_COUNT + 1];
-}
-
-
-
-static imgtoolerr_t prodos_load_block_525(imgtool::image &image,
- int block, void *buffer)
-{
- floperr_t ferr;
- uint32_t track, head, sector1, sector2;
-
- prodos_find_block_525(image, block, &track, &head, &sector1, &sector2);
-
- /* read first sector */
- ferr = floppy_read_sector(imgtool_floppy(image), head, track,
- sector1, 0, ((uint8_t *) buffer) + 0, 256);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- /* read second sector */
- ferr = floppy_read_sector(imgtool_floppy(image), head, track,
- sector2, 0, ((uint8_t *) buffer) + 256, 256);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_save_block_525(imgtool::image &image,
- int block, const void *buffer)
-{
- floperr_t ferr;
- uint32_t track, head, sector1, sector2;
-
- prodos_find_block_525(image, block, &track, &head, &sector1, &sector2);
-
- /* read first sector */
- ferr = floppy_write_sector(imgtool_floppy(image), head, track,
- sector1, 0, ((const uint8_t *) buffer) + 0, 256, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- /* read second sector */
- ferr = floppy_write_sector(imgtool_floppy(image), head, track,
- sector2, 0, ((const uint8_t *) buffer) + 256, 256, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void prodos_setprocs_525(imgtool::image &image)
-{
- prodos_diskinfo *info;
- info = get_prodos_info(image);
- info->load_block = prodos_load_block_525;
- info->save_block = prodos_save_block_525;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_find_block_35(imgtool::image &image, int block,
- uint32_t *track, uint32_t *head, uint32_t *sector)
-{
- int sides = 2;
-
- *track = 0;
- while(block >= (apple35_sectors_per_track(imgtool_floppy(image), *track) * sides))
- {
- block -= (apple35_sectors_per_track(imgtool_floppy(image), (*track)++) * sides);
- if (*track >= 80)
- return IMGTOOLERR_SEEKERROR;
- }
-
- *head = block / apple35_sectors_per_track(imgtool_floppy(image), *track);
- *sector = block % apple35_sectors_per_track(imgtool_floppy(image), *track);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_load_block_35(imgtool::image &image,
- int block, void *buffer)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- uint32_t track, head, sector;
-
- err = prodos_find_block_35(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_read_sector(imgtool_floppy(image), head, track, sector, 0, buffer, 512);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_save_block_35(imgtool::image &image,
- int block, const void *buffer)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- uint32_t track, head, sector;
-
- err = prodos_find_block_35(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_write_sector(imgtool_floppy(image), head, track, sector, 0, buffer, 512, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void prodos_setprocs_35(imgtool::image &image)
-{
- prodos_diskinfo *info;
- info = get_prodos_info(image);
- info->load_block = prodos_load_block_35;
- info->save_block = prodos_save_block_35;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_load_block(imgtool::image &image,
- int block, void *buffer)
-{
- prodos_diskinfo *diskinfo;
- diskinfo = get_prodos_info(image);
- return diskinfo->load_block(image, block, buffer);
-}
-
-
-
-static imgtoolerr_t prodos_save_block(imgtool::image &image,
- int block, const void *buffer)
-{
- prodos_diskinfo *diskinfo;
- diskinfo = get_prodos_info(image);
- return diskinfo->save_block(image, block, buffer);
-}
-
-
-
-static imgtoolerr_t prodos_clear_block(imgtool::image &image, int block)
-{
- uint8_t buffer[BLOCK_SIZE];
- memset(buffer, 0, sizeof(buffer));
- return prodos_save_block(image, block, buffer);
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_diskimage_open(imgtool::image &image)
-{
- imgtoolerr_t err;
- uint8_t buffer[BLOCK_SIZE];
- prodos_diskinfo *di;
- const uint8_t *ent;
-
- di = get_prodos_info(image);
-
- /* specify defaults */
- di->dirent_size = 39;
- di->dirents_per_block = 13;
-
- /* load the first block, hoping that the volume header is first */
- err = prodos_load_block(image, ROOTDIR_BLOCK, buffer);
- if (err)
- return err;
-
- ent = &buffer[4];
-
- /* did we find the volume header? */
- if ((ent[0] & 0xF0) == 0xF0)
- {
- di->dirent_size = pick_integer_le(ent, 31, 1);
- di->dirents_per_block = pick_integer_le(ent, 32, 1);
- di->volume_bitmap_block = pick_integer_le(ent, 35, 2);
- di->total_blocks = pick_integer_le(ent, 37, 2);
- }
-
- /* sanity check these values */
- if (di->dirent_size < 39)
- return IMGTOOLERR_CORRUPTIMAGE;
- if (di->dirents_per_block * di->dirent_size >= BLOCK_SIZE)
- return IMGTOOLERR_CORRUPTIMAGE;
- if (di->volume_bitmap_block >= di->total_blocks)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_open_525(imgtool::image &image, imgtool::stream::ptr &&dummy)
-{
- prodos_setprocs_525(image);
- return prodos_diskimage_open(image);
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_open_35(imgtool::image &image, imgtool::stream::ptr &&dummy)
-{
- prodos_setprocs_35(image);
- return prodos_diskimage_open(image);
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_load_volume_bitmap(imgtool::image &image, uint8_t **bitmap)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- uint8_t *alloc_bitmap;
- uint32_t bitmap_blocks, i;
-
- di = get_prodos_info(image);
-
- bitmap_blocks = (di->total_blocks + (BLOCK_SIZE * 8) - 1) / (BLOCK_SIZE * 8);
- alloc_bitmap = (uint8_t*)malloc(bitmap_blocks * BLOCK_SIZE);
- if (!alloc_bitmap)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
-
- for (i = 0; i < bitmap_blocks; i++)
- {
- err = prodos_load_block(image, di->volume_bitmap_block + i,
- &alloc_bitmap[i * BLOCK_SIZE]);
- if (err)
- goto done;
- }
-
- err = IMGTOOLERR_SUCCESS;
-
-done:
- if (err && alloc_bitmap)
- {
- free(alloc_bitmap);
- alloc_bitmap = NULL;
- }
- *bitmap = alloc_bitmap;
- return err;
-}
-
-
-
-static imgtoolerr_t prodos_save_volume_bitmap(imgtool::image &image, const uint8_t *bitmap)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- uint32_t bitmap_blocks, i;
-
- di = get_prodos_info(image);
-
- bitmap_blocks = (di->total_blocks + (BLOCK_SIZE * 8) - 1) / (BLOCK_SIZE * 8);
-
- for (i = 0; i < bitmap_blocks; i++)
- {
- err = prodos_save_block(image, di->volume_bitmap_block + i,
- &bitmap[i * BLOCK_SIZE]);
- if (err)
- return err;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void prodos_set_volume_bitmap_bit(uint8_t *buffer, uint16_t block, int value)
-{
- uint8_t mask;
- buffer += block / 8;
- mask = 1 << (7 - (block % 8));
- if (value)
- *buffer |= mask;
- else
- *buffer &= ~mask;
-}
-
-
-
-static int prodos_get_volume_bitmap_bit(const uint8_t *buffer, uint16_t block)
-{
- uint8_t mask;
- buffer += block / 8;
- mask = 1 << (7 - (block % 8));
- return (*buffer & mask) ? 1 : 0;
-}
-
-
-
-static imgtoolerr_t prodos_alloc_block(imgtool::image &image, uint8_t *bitmap,
- uint16_t *block)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- prodos_diskinfo *di;
- uint16_t bitmap_blocks, i;
- uint8_t *alloc_bitmap = NULL;
-
- di = get_prodos_info(image);
- *block = 0;
- bitmap_blocks = (di->total_blocks + (BLOCK_SIZE * 8) - 1) / (BLOCK_SIZE * 8);
-
- if (!bitmap)
- {
- err = prodos_load_volume_bitmap(image, &alloc_bitmap);
- if (err)
- goto done;
- bitmap = alloc_bitmap;
- }
-
- for (i = (di->volume_bitmap_block + bitmap_blocks); i < di->total_blocks; i++)
- {
- if (!prodos_get_volume_bitmap_bit(bitmap, i))
- {
- prodos_set_volume_bitmap_bit(bitmap, i, 1);
- *block = i;
- break;
- }
- }
-
- if (*block > 0)
- {
- if (alloc_bitmap)
- {
- err = prodos_save_volume_bitmap(image, bitmap);
- if (err)
- goto done;
- }
- }
- else
- {
- err = IMGTOOLERR_NOSPACE;
- }
-
-done:
- if (err)
- *block = 0;
- if (alloc_bitmap)
- free(alloc_bitmap);
- return err;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_diskimage_create(imgtool::image &image, util::option_resolution *opts)
-{
- imgtoolerr_t err;
- uint32_t heads, tracks, sectors, sector_bytes;
- uint32_t dirent_size, volume_bitmap_block, i;
- uint32_t volume_bitmap_block_count, total_blocks;
- uint8_t buffer[BLOCK_SIZE];
-
- heads = opts->lookup_int('H');
- tracks = opts->lookup_int('T');
- sectors = opts->lookup_int('S');
- sector_bytes = opts->lookup_int('L');
-
- dirent_size = 39;
- volume_bitmap_block = 6;
- total_blocks = tracks * heads * sectors * sector_bytes / BLOCK_SIZE;
- volume_bitmap_block_count = (total_blocks + (BLOCK_SIZE * 8) - 1) / (BLOCK_SIZE * 8);
-
- /* prepare initial dir block */
- memset(buffer, 0, sizeof(buffer));
- place_integer_le(buffer, 4 + 0, 1, 0xF0);
- place_integer_le(buffer, 4 + 31, 1, dirent_size);
- place_integer_le(buffer, 4 + 32, 1, BLOCK_SIZE / dirent_size);
- place_integer_le(buffer, 4 + 35, 2, volume_bitmap_block);
- place_integer_le(buffer, 4 + 37, 2, total_blocks);
-
- err = prodos_save_block(image, ROOTDIR_BLOCK, buffer);
- if (err)
- return err;
-
- /* setup volume bitmap */
- memset(buffer, 0, sizeof(buffer));
- for (i = 0; i < (volume_bitmap_block + volume_bitmap_block_count); i++)
- prodos_set_volume_bitmap_bit(buffer, i, 1);
- prodos_save_block(image, volume_bitmap_block, buffer);
-
- /* and finally open the image */
- return prodos_diskimage_open(image);
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_create_525(imgtool::image &image, imgtool::stream::ptr &&dummy, util::option_resolution *opts)
-{
- prodos_setprocs_525(image);
- return prodos_diskimage_create(image, opts);
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_create_35(imgtool::image &image, imgtool::stream::ptr &&dummy, util::option_resolution *opts)
-{
- prodos_setprocs_35(image);
- return prodos_diskimage_create(image, opts);
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_enum_seek(imgtool::image &image,
- prodos_direnum *appleenum, uint32_t block, uint32_t index)
-{
- imgtoolerr_t err;
- uint8_t buffer[BLOCK_SIZE];
-
- if (appleenum->block != block)
- {
- if (block != 0)
- {
- err = prodos_load_block(image, block, buffer);
- if (err)
- return err;
- memcpy(appleenum->block_data, buffer, sizeof(buffer));
- }
- appleenum->block = block;
- }
-
- appleenum->index = index;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static uint8_t *next_info_block(uint8_t *buffer, size_t *position)
-{
- size_t side = *position & 0x100;
- size_t subpos = *position & 0x0FF;
- uint8_t *result;
-
- if (subpos < 8)
- {
- subpos = 8;
- *position = side + subpos;
- }
-
- while((buffer[side + subpos] == 0x00) || (subpos + buffer[side + subpos] > 0x100))
- {
- if (side)
- return NULL;
-
- side = 0x100;
- subpos = 8;
- }
-
- result = &buffer[side + subpos];
- subpos += *result;
- *position = side + subpos;
- return result;
-}
-
-
-
-static uint8_t *alloc_info_block(uint8_t *buffer, size_t block_size, uint8_t block_type)
-{
- size_t position = 0;
- size_t side;
- size_t subpos;
- uint8_t *result;
-
- while(next_info_block(buffer, &position))
- ;
-
- side = position & 0x100;
- subpos = position & 0x0FF;
-
- if ((subpos + block_size) > 0x100)
- return NULL;
-
- result = &buffer[side + subpos];
- *(result++) = (uint8_t) block_size;
- *(result++) = block_type;
- memset(result, 0, block_size - 2);
- return result;
-}
-
-
-
-static imgtoolerr_t prodos_get_next_dirent(imgtool::image &image,
- prodos_direnum *appleenum, prodos_dirent &ent)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- size_t finfo_offset;
- uint32_t next_block, next_index;
- uint32_t offset;
- uint8_t buffer[BLOCK_SIZE];
- const uint8_t *info_ptr;
- int fork_num;
-
- di = get_prodos_info(image);
- memset(&ent, 0, sizeof(ent));
-
- /* have we hit the end of the file? */
- if (appleenum->block == 0)
- return IMGTOOLERR_SUCCESS;
-
- /* populate the resulting dirent */
- offset = appleenum->index * di->dirent_size + 4;
- ent.storage_type = appleenum->block_data[offset + 0];
- memcpy(ent.filename, &appleenum->block_data[offset + 1], 15);
- ent.filename[15] = '\0';
- ent.creation_time = pick_integer_le(appleenum->block_data, offset + 24, 4);
- ent.lastmodified_time = pick_integer_le(appleenum->block_data, offset + 33, 4);
- ent.file_type = 0x3F3F3F3F;
- ent.file_creator = 0x3F3F3F3F;
- ent.finder_flags = 0;
- ent.coord_x = 0;
- ent.coord_y = 0;
- ent.finder_folder = 0;
- ent.icon_id = 0;
- ent.script_code = 0;
- ent.extended_flags = 0;
- ent.comment_id = 0;
- ent.putaway_directory = 0;
-
- if (is_extendedfile_storagetype(ent.storage_type))
- {
- /* this is a ProDOS extended file; we need to get the extended info
- * block */
- ent.extkey_pointer = pick_integer_le(appleenum->block_data, offset + 17, 2);
-
- err = prodos_load_block(image, ent.extkey_pointer, buffer);
- if (err)
- return err;
-
- for (fork_num = 0; fork_num <= 1; fork_num++)
- {
- ent.key_pointer[fork_num] = pick_integer_le(buffer, 1 + (fork_num * 256), 2);
- ent.filesize[fork_num] = pick_integer_le(buffer, 5 + (fork_num * 256), 3);
- ent.depth[fork_num] = buffer[fork_num * 256] & 0x0F;
- }
-
- finfo_offset = 0;
- while((info_ptr = next_info_block(buffer, &finfo_offset)) != NULL)
- {
- if (*(info_ptr++) == 18)
- {
- switch(*(info_ptr++))
- {
- case 1: /* FInfo */
- ent.file_type = pick_integer_be(info_ptr, 0, 4);
- ent.file_creator = pick_integer_be(info_ptr, 4, 4);
- ent.finder_flags = pick_integer_be(info_ptr, 8, 2);
- ent.coord_x = pick_integer_be(info_ptr, 10, 2);
- ent.coord_y = pick_integer_be(info_ptr, 12, 2);
- ent.finder_folder = pick_integer_be(info_ptr, 14, 4);
- break;
-
- case 2: /* xFInfo */
- ent.icon_id = pick_integer_be(info_ptr, 0, 2);
- ent.script_code = pick_integer_be(info_ptr, 8, 1);
- ent.extended_flags = pick_integer_be(info_ptr, 9, 1);
- ent.comment_id = pick_integer_be(info_ptr, 10, 2);
- ent.putaway_directory = pick_integer_be(info_ptr, 12, 4);
- break;
- }
- }
- }
- }
- else
- {
- /* normal ProDOS files have all of the info right here */
- ent.key_pointer[0] = pick_integer_le(appleenum->block_data, offset + 17, 2);
- ent.filesize[0] = pick_integer_le(appleenum->block_data, offset + 21, 3);
- ent.depth[0] = ent.storage_type >> 4;
- }
-
- /* identify next entry */
- next_block = appleenum->block;
- next_index = appleenum->index + 1;
- if (next_index >= di->dirents_per_block)
- {
- next_block = pick_integer_le(appleenum->block_data, 2, 2);
- next_index = 0;
- }
-
- /* seek next block */
- err = prodos_enum_seek(image, appleenum, next_block, next_index);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/* changes a normal file to a ProDOS extended file */
-static imgtoolerr_t prodos_promote_file(imgtool::image &image, uint8_t *bitmap, prodos_dirent *ent)
-{
- imgtoolerr_t err;
- uint16_t new_block;
- uint8_t buffer[BLOCK_SIZE];
-
- assert(is_normalfile_storagetype(ent->storage_type));
-
- err = prodos_alloc_block(image, bitmap, &new_block);
- if (err)
- return err;
-
- /* create raw extended info block */
- memset(buffer, 0, sizeof(buffer));
- err = prodos_save_block(image, new_block, buffer);
- if (err)
- return err;
-
- ent->storage_type = (ent->storage_type & 0x0F) | 0x50;
- ent->extkey_pointer = new_block;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_put_dirent(imgtool::image &image,
- prodos_direnum *appleenum, prodos_dirent *ent)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- uint32_t offset;
- size_t finfo_offset;
- uint8_t buffer[BLOCK_SIZE];
- int fork_num;
- int needs_finfo = false;
- int needs_xfinfo = false;
- uint8_t *info_ptr;
- uint8_t *finfo;
- uint8_t *xfinfo;
-
- di = get_prodos_info(image);
- offset = appleenum->index * di->dirent_size + 4;
-
- /* determine whether we need FInfo and/or xFInfo */
- if (is_normalfile_storagetype(ent->storage_type))
- {
- needs_finfo = (ent->file_type != 0x3F3F3F3F) ||
- (ent->file_creator != 0x3F3F3F3F) ||
- (ent->finder_flags != 0) ||
- (ent->coord_x != 0) ||
- (ent->coord_y != 0) ||
- (ent->finder_folder != 0);
-
- needs_xfinfo = (ent->icon_id != 0) ||
- (ent->script_code != 0) ||
- (ent->extended_flags != 0) ||
- (ent->comment_id != 0) ||
- (ent->putaway_directory != 0);
- }
-
- /* do we need to promote this file to an extended file? */
- if (!is_extendedfile_storagetype(ent->storage_type)
- && (needs_finfo || needs_xfinfo))
- {
- err = prodos_promote_file(image, NULL, ent);
- if (err)
- return err;
- }
-
- /* write out the storage type, filename, creation and lastmodified times */
- appleenum->block_data[offset + 0] = ent->storage_type;
- memcpy(&appleenum->block_data[offset + 1], ent->filename, 15);
- place_integer_le(appleenum->block_data, offset + 24, 4, ent->creation_time);
- place_integer_le(appleenum->block_data, offset + 33, 4, ent->lastmodified_time);
-
- if (is_extendedfile_storagetype(ent->storage_type))
- {
- /* ProDOS extended file */
- err = prodos_load_block(image, ent->extkey_pointer, buffer);
- if (err)
- return err;
-
- finfo = NULL;
- xfinfo = NULL;
-
- for (fork_num = 0; fork_num <= 1; fork_num++)
- {
- place_integer_le(buffer, 1 + (fork_num * 256), 2, ent->key_pointer[fork_num]);
- place_integer_le(buffer, 5 + (fork_num * 256), 3, ent->filesize[fork_num]);
- buffer[fork_num * 256] = ent->depth[fork_num];
- }
-
- finfo_offset = 0;
- while((info_ptr = next_info_block(buffer, &finfo_offset)) != NULL)
- {
- if (*(info_ptr++) == 18)
- {
- switch(*(info_ptr++))
- {
- case 1: /* FInfo */
- finfo = info_ptr;
- break;
-
- case 2: /* xFInfo */
- xfinfo = info_ptr;
- break;
- }
- }
- }
-
- /* allocate the finfo and/or xinfo blocks, if we need them */
- if (needs_finfo && !finfo)
- finfo = alloc_info_block(buffer, 18, 1);
- if (needs_xfinfo && !xfinfo)
- xfinfo = alloc_info_block(buffer, 18, 2);
-
- if (finfo)
- {
- place_integer_be(finfo, 0, 4, ent->file_type);
- place_integer_be(finfo, 4, 4, ent->file_creator);
- place_integer_be(finfo, 8, 2, ent->finder_flags);
- place_integer_be(finfo, 10, 2, ent->coord_x);
- place_integer_be(finfo, 12, 2, ent->coord_y);
- place_integer_be(finfo, 14, 4, ent->finder_folder);
- }
-
- if (xfinfo)
- {
- place_integer_be(xfinfo, 0, 2, ent->icon_id);
- place_integer_be(xfinfo, 8, 1, ent->script_code);
- place_integer_be(xfinfo, 9, 1, ent->extended_flags);
- place_integer_be(xfinfo, 10, 2, ent->comment_id);
- place_integer_be(xfinfo, 12, 4, ent->putaway_directory);
- }
-
- err = prodos_save_block(image, ent->extkey_pointer, buffer);
- if (err)
- return err;
-
- place_integer_le(appleenum->block_data, offset + 17, 2, ent->extkey_pointer);
- place_integer_le(appleenum->block_data, offset + 21, 3, BLOCK_SIZE);
- }
- else
- {
- /* normal file */
- place_integer_le(appleenum->block_data, offset + 17, 2, ent->key_pointer[0]);
- place_integer_le(appleenum->block_data, offset + 21, 3, ent->filesize[0]);
- }
-
- err = prodos_save_block(image, appleenum->block, appleenum->block_data);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_lookup_path(imgtool::image &image, const char *path,
- creation_policy_t create, prodos_direnum *direnum, prodos_dirent *ent)
-{
- imgtoolerr_t err;
- prodos_direnum my_direnum;
- uint32_t block = ROOTDIR_BLOCK;
- const char *old_path;
- uint16_t this_block;
- uint32_t this_index;
- uint16_t free_block = 0;
- uint32_t free_index = 0;
- uint16_t new_file_block;
- uint8_t buffer[BLOCK_SIZE];
-
- if (!direnum)
- direnum = &my_direnum;
-
- while(*path)
- {
- memset(direnum, 0, sizeof(*direnum));
- err = prodos_enum_seek(image, direnum, block, 0);
- if (err)
- goto done;
-
- do
- {
- this_block = direnum->block;
- this_index = direnum->index;
-
- err = prodos_get_next_dirent(image, direnum, *ent);
- if (err)
- goto done;
-
- /* if we need to create a file entry and this is free, track it */
- if (create && this_block && !free_block && !ent->storage_type)
- {
- free_block = this_block;
- free_index = this_index;
- }
- }
- while(direnum->block && (strcmp(path, ent->filename) || (
- !is_file_storagetype(ent->storage_type) &&
- !is_dir_storagetype(ent->storage_type))));
-
- old_path = path;
- path += strlen(path) + 1;
- if (*path)
- {
- /* we have found part of the path; we are not finished yet */
- if (!is_dir_storagetype(ent->storage_type))
- {
- err = IMGTOOLERR_FILENOTFOUND;
- goto done;
- }
- block = ent->key_pointer[0];
- }
- else if (!direnum->block)
- {
- /* did not find file; maybe we need to create it */
- if (create == CREATE_NONE)
- {
- err = IMGTOOLERR_FILENOTFOUND;
- goto done;
- }
-
- /* do we need to expand the directory? */
- if (!free_block)
- {
- if (this_block == 0)
- {
- err = IMGTOOLERR_CORRUPTFILE;
- goto done;
- }
-
- err = prodos_load_block(image, this_block, buffer);
- if (err)
- goto done;
-
- /* allocate a block */
- err = prodos_alloc_block(image, NULL, &free_block);
- if (err)
- goto done;
-
- /* clear out this new block */
- err = prodos_clear_block(image, free_block);
- if (err)
- goto done;
-
- /* save this link */
- place_integer_le(buffer, 2, 2, free_block);
- err = prodos_save_block(image, this_block, buffer);
- if (err)
- goto done;
-
- free_index = 0;
- }
-
- /* seek back to the free space */
- err = prodos_enum_seek(image, direnum, free_block, free_index);
- if (err)
- goto done;
-
- new_file_block = 0;
- if (create == CREATE_DIR)
- {
- /* if we are creating a directory, we need to create a new block */
- err = prodos_alloc_block(image, NULL, &new_file_block);
- if (err)
- goto done;
-
- err = prodos_clear_block(image, new_file_block);
- if (err)
- goto done;
- }
-
- /* prepare the dirent */
- memset(ent, 0, sizeof(*ent));
- ent->storage_type = (create == CREATE_DIR) ? 0xe0 : 0x10;
- ent->creation_time = ent->lastmodified_time = prodos_time_now();
- ent->key_pointer[0] = new_file_block;
- ent->file_type = 0x3F3F3F3F;
- ent->file_creator = 0x3F3F3F3F;
- strncpy(ent->filename, old_path, ARRAY_LENGTH(ent->filename));
-
- /* and place it */
- err = prodos_put_dirent(image, direnum, ent);
- if (err)
- goto done;
-
- this_block = free_block;
- this_index = free_index;
- }
- else
- {
- /* we've found the file; seek that dirent */
- err = prodos_enum_seek(image, direnum, this_block, this_index);
- if (err)
- goto done;
- }
- }
-
- err = IMGTOOLERR_SUCCESS;
-done:
- return err;
-}
-
-
-
-static imgtoolerr_t prodos_fill_file(imgtool::image &image, uint8_t *bitmap,
- uint16_t key_block, int key_block_allocated,
- int depth, uint32_t blockcount, uint32_t block_index)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- int dirty;
- int sub_block_allocated;
- uint16_t i, sub_block, new_sub_block;
- uint8_t buffer[BLOCK_SIZE];
-
- di = get_prodos_info(image);
-
- if (key_block_allocated)
- {
- /* we are on a recently allocated key block; start fresh */
- memset(buffer, 0, sizeof(buffer));
- dirty = true;
- }
- else
- {
- /* this is a preexisting key block */
- err = prodos_load_block(image, key_block, buffer);
- if (err)
- return err;
- dirty = false;
- }
-
- for (i = 0; i < 256; i++)
- {
- sub_block_allocated = false;
-
- sub_block = buffer[i + 256];
- sub_block <<= 8;
- sub_block += buffer[i + 0];
-
- new_sub_block = sub_block;
- if ((block_index < blockcount) && (sub_block == 0))
- {
- err = prodos_alloc_block(image, bitmap, &new_sub_block);
- if (err)
- return err;
- sub_block_allocated = true;
- }
- else if ((block_index >= blockcount) && (sub_block != 0))
- {
- new_sub_block = 0;
- if (sub_block < di->total_blocks)
- prodos_set_volume_bitmap_bit(bitmap, sub_block, 0);
- }
-
- /* did we change the block? */
- if (new_sub_block != sub_block)
- {
- dirty = true;
- buffer[i + 0] = new_sub_block >> 0;
- buffer[i + 256] = new_sub_block >> 8;
- if (sub_block == 0)
- sub_block = new_sub_block;
- }
-
- /* call recursive function */
- if (depth > 2)
- {
- err = prodos_fill_file(image, bitmap, sub_block, sub_block_allocated, depth - 1, blockcount, block_index);
- if (err)
- return err;
- }
-
- /* increment index */
- block_index += 1 << ((depth - 2) * 8);
- }
-
- /* if we changed anything, then save the block */
- if (dirty)
- {
- err = prodos_save_block(image, key_block, buffer);
- if (err)
- return err;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_set_file_block_count(imgtool::image &image, prodos_direnum *direnum,
- prodos_dirent *ent, uint8_t *bitmap, int fork_num, uint32_t new_blockcount)
-{
- imgtoolerr_t err;
- int depth, new_depth, i;
- uint16_t new_block, block;
- uint8_t buffer[BLOCK_SIZE];
- uint16_t key_pointer;
-
- if (fork_num && (new_blockcount > 0) && !is_extendedfile_storagetype(ent->storage_type))
- {
- /* need to change a normal file to an extended file */
- err = prodos_promote_file(image, bitmap, ent);
- if (err)
- return err;
- }
-
- key_pointer = ent->key_pointer[fork_num];
- depth = ent->depth[fork_num];
-
- /* determine the new tree depth */
- if (new_blockcount <= 1)
- new_depth = 1;
- else if (new_blockcount <= 256)
- new_depth = 2;
- else
- new_depth = 3;
-
- /* are we zero length, and do we have to create a block? */
- if ((new_blockcount >= 1) && (key_pointer == 0))
- {
- err = prodos_alloc_block(image, bitmap, &new_block);
- if (err)
- return err;
- key_pointer = new_block;
- }
-
- /* do we have to grow the tree? */
- while(new_depth > depth)
- {
- err = prodos_alloc_block(image, bitmap, &new_block);
- if (err)
- return err;
-
- /* create this new key block, with a link to the previous one */
- memset(buffer, 0, sizeof(buffer));
- buffer[0] = (uint8_t) (key_pointer >> 0);
- buffer[256] = (uint8_t) (key_pointer >> 8);
- err = prodos_save_block(image, new_block, buffer);
- if (err)
- return err;
-
- depth++;
- key_pointer = new_block;
- }
-
- /* do we have to shrink the tree? */
- while(new_depth < depth)
- {
- err = prodos_load_block(image, key_pointer, buffer);
- if (err)
- return err;
-
- for (i = 1; i < 256; i++)
- {
- block = buffer[i + 256];
- block <<= 8;
- block |= buffer[i + 0];
-
- if (block > 0)
- {
- if (depth > 2)
- {
- /* remove this block's children */
- err = prodos_fill_file(image, bitmap, block, false, depth - 1, 0, 0);
- if (err)
- return err;
- }
-
- /* and remove this block */
- prodos_set_volume_bitmap_bit(bitmap, block, 0);
- }
- }
-
- /* remove this key block */
- prodos_set_volume_bitmap_bit(bitmap, key_pointer, 0);
-
- /* set the new key pointer */
- block = buffer[256];
- block <<= 8;
- block |= buffer[0];
- key_pointer = block;
-
- depth--;
- }
-
- if (new_blockcount > 0)
- {
- /* fill out the file tree */
- err = prodos_fill_file(image, bitmap, key_pointer, false, depth, new_blockcount, 0);
- if (err)
- return err;
- }
- else if (key_pointer != 0)
- {
- /* we are now zero length, and don't need a key pointer */
- prodos_set_volume_bitmap_bit(bitmap, key_pointer, 0);
- key_pointer = 0;
- }
-
- /* change the depth if we are not an extended file */
- if (is_normalfile_storagetype(ent->storage_type))
- {
- ent->storage_type &= ~0xF0;
- ent->storage_type |= depth * 0x10;
- }
-
- ent->key_pointer[fork_num] = key_pointer;
- ent->depth[fork_num] = depth;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_set_file_size(imgtool::image &image, prodos_direnum *direnum,
- prodos_dirent *ent, int fork_num, uint32_t new_size)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- uint32_t blockcount, new_blockcount;
- uint8_t *bitmap = NULL;
-
- if (ent->filesize[fork_num] != new_size)
- {
- blockcount = (ent->filesize[fork_num] + BLOCK_SIZE - 1) / BLOCK_SIZE;
- new_blockcount = (new_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
-
- /* do we need to change the block chain? */
- if (new_blockcount != blockcount)
- {
- err = prodos_load_volume_bitmap(image, &bitmap);
- if (err)
- goto done;
-
- err = prodos_set_file_block_count(image, direnum, ent, bitmap, fork_num, new_blockcount);
- if (err)
- goto done;
-
- err = prodos_save_volume_bitmap(image, bitmap);
- if (err)
- goto done;
- }
-
- ent->filesize[fork_num] = new_size;
- err = prodos_put_dirent(image, direnum, ent);
- if (err)
- goto done;
- }
-
-done:
- if (bitmap)
- free(bitmap);
- return err;
-}
-
-
-
-static uint32_t prodos_get_storagetype_maxfilesize(uint8_t storage_type)
-{
- uint32_t max_filesize = 0;
- switch(storage_type & 0xF0)
- {
- case 0x10:
- max_filesize = BLOCK_SIZE * 1;
- break;
- case 0x20:
- max_filesize = BLOCK_SIZE * 256;
- break;
- case 0x30:
- case 0x50:
- max_filesize = BLOCK_SIZE * 32768;
- break;
- }
- return max_filesize;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_beginenum(imgtool::directory &enumeration, const char *path)
-{
- imgtoolerr_t err;
- imgtool::image &image(enumeration.image());
- prodos_direnum *appleenum;
- prodos_dirent ent;
- uint16_t block = ROOTDIR_BLOCK;
-
- appleenum = (prodos_direnum *) enumeration.extra_bytes();
-
- /* find subdirectory, if appropriate */
- if (*path)
- {
- err = prodos_lookup_path(image, path, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- /* only work on directories */
- if (!is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- block = ent.key_pointer[0];
- }
-
- /* seek initial block */
- err = prodos_enum_seek(image, appleenum, block, 0);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_nextenum(imgtool::directory &enumeration, imgtool_dirent &ent)
-{
- imgtoolerr_t err;
- imgtool::image &image(enumeration.image());
- prodos_direnum *appleenum;
- prodos_dirent pd_ent;
- uint32_t max_filesize;
-
- appleenum = (prodos_direnum *) enumeration.extra_bytes();
-
- do
- {
- err = prodos_get_next_dirent(image, appleenum, pd_ent);
- if (err)
- return err;
- }
- while(appleenum->block
- && !is_file_storagetype(pd_ent.storage_type)
- && !is_dir_storagetype(pd_ent.storage_type));
-
- /* end of file? */
- if (pd_ent.storage_type == 0x00)
- {
- ent.eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
-
- strcpy(ent.filename, pd_ent.filename);
- ent.directory = is_dir_storagetype(pd_ent.storage_type);
- ent.creation_time = prodos_crack_time(pd_ent.creation_time);
- ent.lastmodified_time = prodos_crack_time(pd_ent.lastmodified_time);
-
- if (!ent.directory)
- {
- ent.filesize = pd_ent.filesize[0];
-
- max_filesize = prodos_get_storagetype_maxfilesize(pd_ent.storage_type);
- if (ent.filesize > max_filesize)
- {
- ent.corrupt = 1;
- ent.filesize = max_filesize;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_read_file_tree(imgtool::image &image, uint32_t *filesize,
- uint32_t block, int nest_level, imgtool::stream &destf)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- uint8_t buffer[BLOCK_SIZE];
- uint16_t sub_block;
- size_t bytes_to_write;
- int i;
-
- /* check bounds */
- di = get_prodos_info(image);
- if (block >= di->total_blocks)
- return IMGTOOLERR_CORRUPTFILE;
-
- err = prodos_load_block(image, block, buffer);
- if (err)
- return err;
-
- if (nest_level > 0)
- {
- /* this is an index block */
- for (i = 0; i < 256; i++)
- {
- /* retrieve the block pointer; the two bytes are on either half
- * of the block */
- sub_block = buffer[i + 256];
- sub_block <<= 8;
- sub_block |= buffer[i + 0];
-
- if (sub_block != 0)
- {
- err = prodos_read_file_tree(image, filesize, sub_block, nest_level - 1, destf);
- if (err)
- return err;
- }
- }
- }
- else
- {
- /* this is a leaf block */
- bytes_to_write = std::min(size_t(*filesize), sizeof(buffer));
- destf.write(buffer, bytes_to_write);
- *filesize -= bytes_to_write;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_write_file_tree(imgtool::image &image, uint32_t *filesize,
- uint32_t block, int nest_level, imgtool::stream &sourcef)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- uint8_t buffer[BLOCK_SIZE];
- uint16_t sub_block;
- size_t bytes_to_read;
- int i;
-
- /* nothing more to read? bail */
- if (*filesize == 0)
- return IMGTOOLERR_SUCCESS;
-
- /* check bounds */
- di = get_prodos_info(image);
- if (block >= di->total_blocks)
- return IMGTOOLERR_CORRUPTFILE;
-
- err = prodos_load_block(image, block, buffer);
- if (err)
- return err;
-
- if (nest_level > 0)
- {
- for (i = 0; i < 256; i++)
- {
- sub_block = buffer[i + 256];
- sub_block <<= 8;
- sub_block |= buffer[i + 0];
-
- if (sub_block != 0)
- {
- err = prodos_write_file_tree(image, filesize, sub_block, nest_level - 1, sourcef);
- if (err)
- return err;
- }
- }
- }
- else
- {
- /* this is a leaf block */
- bytes_to_read = std::min(size_t(*filesize), sizeof(buffer));
- sourcef.read(buffer, bytes_to_read);
- *filesize -= bytes_to_read;
-
- err = prodos_save_block(image, block, buffer);
- if (err)
- return err;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_freespace(imgtool::partition &partition, uint64_t *size)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_diskinfo *di;
- uint8_t *bitmap = NULL;
- uint16_t i;
-
- di = get_prodos_info(image);
- *size = 0;
-
- err = prodos_load_volume_bitmap(image, &bitmap);
- if (err)
- goto done;
-
- for (i = 0; i < di->total_blocks; i++)
- {
- if (!prodos_get_volume_bitmap_bit(bitmap, i))
- *size += BLOCK_SIZE;
- }
-
-done:
- if (bitmap)
- free(bitmap);
- return err;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_readfile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &destf)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- uint16_t key_pointer;
- int nest_level;
- mac_fork_t fork_num;
-
- err = prodos_lookup_path(image, filename, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- if (is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- err = mac_identify_fork(fork, &fork_num);
- if (err)
- return err;
-
- key_pointer = ent.key_pointer[fork_num];
- nest_level = ent.depth[fork_num] - 1;
-
- if (key_pointer != 0)
- {
- err = prodos_read_file_tree(image, &ent.filesize[fork_num], key_pointer,
- nest_level, destf);
- if (err)
- return err;
- }
-
- /* have we not actually received the correct amount of bytes? if not, fill in the rest */
- if (ent.filesize[fork_num] > 0)
- destf.fill(0, ent.filesize[fork_num]);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_writefile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &sourcef, util::option_resolution *opts)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- prodos_direnum direnum;
- uint64_t file_size;
- mac_fork_t fork_num;
-
- file_size = sourcef.size();
-
- err = prodos_lookup_path(image, filename, CREATE_FILE, &direnum, &ent);
- if (err)
- return err;
-
- /* only work on files */
- if (is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- err = mac_identify_fork(fork, &fork_num);
- if (err)
- return err;
-
- /* set the file size */
- err = prodos_set_file_size(image, &direnum, &ent, fork_num, file_size);
- if (err)
- return err;
-
- err = prodos_write_file_tree(image, &ent.filesize[fork_num], ent.key_pointer[fork_num],
- ent.depth[fork_num] - 1, sourcef);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_deletefile(imgtool::partition &partition, const char *path)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- prodos_direnum direnum;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, &direnum, &ent);
- if (err)
- return err;
-
- /* only work on files */
- if (is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- /* empty out both forks */
- err = prodos_set_file_size(image, &direnum, &ent, 0, 0);
- if (err)
- return err;
- err = prodos_set_file_size(image, &direnum, &ent, 1, 0);
- if (err)
- return err;
-
- memset(&ent, 0, sizeof(ent));
- err = prodos_put_dirent(image, &direnum, &ent);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_listforks(imgtool::partition &partition, const char *path, std::vector<imgtool::fork_entry> &forks)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- prodos_direnum direnum;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, &direnum, &ent);
- if (err)
- return err;
-
- if (is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- // specify data fork
- forks.emplace_back(ent.filesize[0], imgtool::fork_entry::type_t::DATA);
-
- if (is_extendedfile_storagetype(ent.storage_type))
- {
- // specify the resource fork
- forks.emplace_back(ent.filesize[1], imgtool::fork_entry::type_t::RESOURCE);
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_createdir(imgtool::partition &partition, const char *path)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- prodos_direnum direnum;
-
- err = prodos_lookup_path(image, path, CREATE_DIR, &direnum, &ent);
- if (err)
- return err;
-
- /* only work on directories */
- if (!is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_free_directory(imgtool::image &image, uint8_t *volume_bitmap, uint16_t key_pointer)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- int i;
- uint16_t next_block;
- uint32_t offset;
- uint8_t buffer[BLOCK_SIZE];
-
- di = get_prodos_info(image);
-
- if (key_pointer != 0)
- {
- err = prodos_load_block(image, key_pointer, buffer);
- if (err)
- return err;
-
- for (i = 0; i < di->dirents_per_block; i++)
- {
- offset = i * di->dirent_size + 4;
-
- if (is_file_storagetype(buffer[offset]) || is_file_storagetype(buffer[offset]))
- return IMGTOOLERR_DIRNOTEMPTY;
- }
-
- next_block = pick_integer_le(buffer, 2, 2);
-
- err = prodos_free_directory(image, volume_bitmap, next_block);
- if (err)
- return err;
-
- prodos_set_volume_bitmap_bit(volume_bitmap, key_pointer, 0);
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_deletedir(imgtool::partition &partition, const char *path)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- prodos_direnum direnum;
- uint8_t *volume_bitmap = NULL;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, &direnum, &ent);
- if (err)
- goto done;
-
- /* only work on directories */
- if (!is_dir_storagetype(ent.storage_type))
- {
- err = IMGTOOLERR_FILENOTFOUND;
- goto done;
- }
-
- err = prodos_load_volume_bitmap(image, &volume_bitmap);
- if (err)
- goto done;
-
- err = prodos_free_directory(image, volume_bitmap, ent.key_pointer[0]);
- if (err)
- goto done;
-
- err = prodos_save_volume_bitmap(image, volume_bitmap);
- if (err)
- goto done;
-
- memset(&ent, 0, sizeof(ent));
- err = prodos_put_dirent(image, &direnum, &ent);
- if (err)
- goto done;
-
-done:
- if (volume_bitmap)
- free(volume_bitmap);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_get_file_tree(imgtool::image &image, imgtool_chainent *chain, size_t chain_size,
- size_t *chain_pos, uint16_t block, uint8_t total_depth, uint8_t cur_depth)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- int i;
- uint16_t sub_block;
- uint8_t buffer[BLOCK_SIZE];
-
- if (block == 0)
- return IMGTOOLERR_SUCCESS;
- if (*chain_pos >= chain_size)
- return IMGTOOLERR_SUCCESS;
-
- /* check bounds */
- di = get_prodos_info(image);
- if (block >= di->total_blocks)
- return IMGTOOLERR_CORRUPTFILE;
-
- chain[*chain_pos].level = cur_depth;
- chain[*chain_pos].block = block;
- (*chain_pos)++;
-
- /* must we recurse into the tree? */
- if (cur_depth < total_depth)
- {
- err = prodos_load_block(image, block, buffer);
- if (err)
- return err;
-
- for (i = 0; i < 256; i++)
- {
- sub_block = buffer[i + 256];
- sub_block <<= 8;
- sub_block |= buffer[i + 0];
-
- err = prodos_get_file_tree(image, chain, chain_size, chain_pos, sub_block, total_depth, cur_depth + 1);
- if (err)
- return err;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_getattrs(imgtool::partition &partition, const char *path, const uint32_t *attrs, imgtool_attribute *values)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- int i;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- for (i = 0; attrs[i]; i++)
- {
- switch(attrs[i])
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- values[i].i = ent.file_type;
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- values[i].i = ent.file_creator;
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- values[i].i = ent.finder_flags;
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- values[i].i = ent.coord_x;
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- values[i].i = ent.coord_y;
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- values[i].i = ent.finder_folder;
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- values[i].i = ent.icon_id;
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- values[i].i = ent.script_code;
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- values[i].i = ent.extended_flags;
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- values[i].i = ent.comment_id;
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- values[i].i = ent.putaway_directory;
- break;
-
- case IMGTOOLATTR_TIME_CREATED:
- values[i].t = prodos_crack_time(ent.creation_time).to_time_t();
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- values[i].t = prodos_crack_time(ent.lastmodified_time).to_time_t();
- break;
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_setattrs(imgtool::partition &partition, const char *path, const uint32_t *attrs, const imgtool_attribute *values)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- prodos_direnum direnum;
- int i;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, &direnum, &ent);
- if (err)
- return err;
-
- for (i = 0; attrs[i]; i++)
- {
- switch(attrs[i])
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- ent.file_type = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- ent.file_creator = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- ent.finder_flags = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- ent.coord_x = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- ent.coord_y = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- ent.finder_folder = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- ent.icon_id = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- ent.script_code = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- ent.extended_flags = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- ent.comment_id = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- ent.putaway_directory = values[i].i;
- break;
-
- case IMGTOOLATTR_TIME_CREATED:
- ent.creation_time = prodos_setup_time(values[i].t);
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- ent.lastmodified_time = prodos_setup_time(values[i].t);
- break;
- }
- }
-
- err = prodos_put_dirent(image, &direnum, &ent);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_suggesttransfer(imgtool::partition &partition, const char *path, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- mac_filecategory_t file_category = MAC_FILECATEGORY_DATA;
-
- if (path)
- {
- err = prodos_lookup_path(image, path, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- file_category = is_extendedfile_storagetype(ent.storage_type)
- ? MAC_FILECATEGORY_FORKED : MAC_FILECATEGORY_DATA;
- }
-
- mac_suggest_transfer(file_category, suggestions, suggestions_length);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_getchain(imgtool::partition &partition, const char *path, imgtool_chainent *chain, size_t chain_size)
-{
- imgtoolerr_t err;
- imgtool::image &image(partition.image());
- prodos_dirent ent;
- size_t chain_pos = 0;
- int fork_num;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- switch(ent.storage_type & 0xF0)
- {
- case 0x10:
- case 0x20:
- case 0x30:
- /* normal ProDOS file */
- err = prodos_get_file_tree(image, chain, chain_size, &chain_pos,
- ent.key_pointer[0], ent.depth[0] - 1, 0);
- if (err)
- return err;
- break;
-
- case 0x50:
- /* extended ProDOS file */
- chain[chain_pos].level = 0;
- chain[chain_pos].block = ent.extkey_pointer;
- chain_pos++;
-
- for (fork_num = 0; fork_num <= 1; fork_num++)
- {
- if (ent.key_pointer[fork_num])
- {
- err = prodos_get_file_tree(image, chain, chain_size, &chain_pos,
- ent.key_pointer[fork_num], ent.depth[fork_num] - 1, 1);
- if (err)
- return err;
- }
- }
- break;
-
- case 0xE0:
- /* directory */
- return IMGTOOLERR_UNIMPLEMENTED;
-
- default:
- return IMGTOOLERR_UNEXPECTED;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void generic_prodos_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case IMGTOOLINFO_INT_INITIAL_PATH_SEPARATOR: info->i = 1; break;
- case IMGTOOLINFO_INT_OPEN_IS_STRICT: info->i = 1; break;
- case IMGTOOLINFO_INT_SUPPORTS_CREATION_TIME: info->i = 1; break;
- case IMGTOOLINFO_INT_SUPPORTS_LASTMODIFIED_TIME: info->i = 1; break;
- case IMGTOOLINFO_INT_WRITING_UNTESTED: info->i = 1; break;
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(prodos_diskinfo); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(prodos_direnum); break;
- case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = '/'; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "ProDOS format"); break;
- case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_EOLN: strcpy(info->s = imgtool_temp_str(), "\r"); 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_BEGIN_ENUM: info->begin_enum = prodos_diskimage_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = prodos_diskimage_nextenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = prodos_diskimage_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = prodos_diskimage_readfile; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = prodos_diskimage_writefile; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = prodos_diskimage_deletefile; break;
- case IMGTOOLINFO_PTR_LIST_FORKS: info->list_forks = prodos_diskimage_listforks; break;
- case IMGTOOLINFO_PTR_CREATE_DIR: info->create_dir = prodos_diskimage_createdir; break;
- case IMGTOOLINFO_PTR_DELETE_DIR: info->delete_dir = prodos_diskimage_deletedir; break;
- case IMGTOOLINFO_PTR_GET_ATTRS: info->get_attrs = prodos_diskimage_getattrs; break;
- case IMGTOOLINFO_PTR_SET_ATTRS: info->set_attrs = prodos_diskimage_setattrs; break;
- case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = prodos_diskimage_suggesttransfer; break;
- case IMGTOOLINFO_PTR_GET_CHAIN: info->get_chain = prodos_diskimage_getchain; break;
- }
-}
-
-
-
-void prodos_525_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "prodos_525"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_FLOPPY_CREATE: info->create = prodos_diskimage_create_525; break;
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = prodos_diskimage_open_525; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_apple2; break;
-
- default: generic_prodos_get_info(imgclass, state, info); break;
- }
-}
-
-
-
-void prodos_35_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "prodos_35"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_FLOPPY_CREATE: info->create = prodos_diskimage_create_35; break;
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = prodos_diskimage_open_35; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_apple35_iigs; break;
-
- default: generic_prodos_get_info(imgclass, state, info); break;
- }
-}
diff --git a/src/tools/imgtool/modules/psion.cpp b/src/tools/imgtool/modules/psion.cpp
index 5759673349e..dba1130ddab 100644
--- a/src/tools/imgtool/modules/psion.cpp
+++ b/src/tools/imgtool/modules/psion.cpp
@@ -24,6 +24,11 @@
#include "imgtool.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <cstdio>
+
#define MAXFILES 256
struct psion_file
@@ -54,24 +59,23 @@ static psion_pack *get_psion_pack(imgtool::image &image)
return (psion_pack*)image.extra_bytes();
}
-uint16_t head_checksum(uint8_t* data)
+uint16_t head_checksum(const uint8_t* data)
{
uint16_t checksum = 0;
for (int i=0; i<6; i+=2)
- checksum += (data[i]<<8 | data[i+1]);
+ checksum += get_u16be(&data[i]);
return checksum;
}
uint16_t get_long_rec_size(imgtool::stream &stream)
{
- uint8_t size_h, size_l;
+ uint8_t size[2];
- stream.read(&size_h, 1);
- stream.read(&size_l, 1);
+ stream.read(size, 2);
- return (size_h<<8) | size_l;
+ return get_u16be(size);
}
uint32_t update_pack_index(psion_pack *pack)
@@ -245,6 +249,7 @@ char *stream_getline(imgtool::stream &source, uint16_t max_len)
source.read(&data, 1);
if (data != '\n')
source.seek(-1, SEEK_CUR);
+ [[fallthrough]];
case '\n':
return line;
default:
@@ -483,7 +488,7 @@ static imgtoolerr_t datapack_next_enum(imgtool::directory &enumeration, imgtool_
return IMGTOOLERR_SUCCESS;
}
memcpy(ent.filename, pack->pack_index[iter->index].filename, 8);
- sprintf(ent.attr, "Type: %02x ID: %02x", pack->pack_index[iter->index].type, pack->pack_index[iter->index].id);
+ snprintf(ent.attr, std::size(ent.attr), "Type: %02x ID: %02x", pack->pack_index[iter->index].type, pack->pack_index[iter->index].id);
if (pack->pack_index[iter->index].data_rec)
{
diff --git a/src/tools/imgtool/modules/rsdos.cpp b/src/tools/imgtool/modules/rsdos.cpp
index 4bcde9444ab..b4924338309 100644
--- a/src/tools/imgtool/modules/rsdos.cpp
+++ b/src/tools/imgtool/modules/rsdos.cpp
@@ -8,13 +8,18 @@
****************************************************************************/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
#include "imgtool.h"
-#include "formats/coco_dsk.h"
+#include "filter.h"
#include "iflopimg.h"
+#include "formats/coco_dsk.h"
+#include "corestr.h"
+#include "opresolv.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
/* this structure mirrors the structure of an RS-DOS directory entry on disk */
struct rsdos_dirent
{
@@ -103,7 +108,7 @@ static imgtoolerr_t lookup_rsdos_file(imgtool::image &f, const char *fname, rsdo
if (ent.filename[0] != -1)
fnamebuf = get_dirent_fname(ent);
}
- while((ent.filename[0] != -1) && core_stricmp(fnamebuf.c_str(), fname));
+ while((ent.filename[0] != -1) && core_stricmp(fnamebuf, fname));
if (ent.filename[0] == -1)
return IMGTOOLERR_FILENOTFOUND;
@@ -320,7 +325,7 @@ eof:
}
else
{
- /* Not the end of file */
+ /* Note the end of file */
err = process_rsdos_file(&rsent, image, nullptr, filesize);
if (err)
return err;
@@ -340,8 +345,8 @@ eof:
std::string fname = get_dirent_fname(rsent);
- snprintf(ent.filename, ARRAY_LENGTH(ent.filename), "%s", fname.c_str());
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "%d %c", (int) rsent.ftype, (char) (rsent.asciiflag + 'B'));
+ snprintf(ent.filename, std::size(ent.filename), "%s", fname.c_str());
+ snprintf(ent.attr, std::size(ent.attr), "%d %c", (int) rsent.ftype, (char) (rsent.asciiflag + 'B'));
}
return IMGTOOLERR_SUCCESS;
}
@@ -568,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());
@@ -584,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;
}
@@ -640,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/rt11.cpp b/src/tools/imgtool/modules/rt11.cpp
index 01ab8741dd6..cc425adbdb6 100644
--- a/src/tools/imgtool/modules/rt11.cpp
+++ b/src/tools/imgtool/modules/rt11.cpp
@@ -72,12 +72,13 @@
****************************************************************************/
#include "imgtool.h"
-#include "formats/imageutl.h"
#include "iflopimg.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include "multibyte.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
namespace
@@ -384,17 +385,17 @@ static imgtoolerr_t rt11_image_open(imgtool::image &image, imgtool::stream::ptr
if (err)
return err;
- di->directory_start = pick_integer_le(buffer, 0724, 2);
+ di->directory_start = get_u16le(&buffer[0724]);
// real-world images seem to never have a valid checksum, but directory_start is always 6
#if 0
uint16_t tmp, cksum;
tmp = 0;
- cksum = pick_integer_le(buffer, 0776, 2);
+ cksum = get_u16le(&buffer[0776]);
for (int i = 0; i < 510; i+=2)
{
- tmp += pick_integer_le(buffer, i, 2);
+ tmp += get_u16le(&buffer[i]);
}
/* sanity check these values */
@@ -414,9 +415,9 @@ static imgtoolerr_t rt11_image_open(imgtool::image &image, imgtool::stream::ptr
if (err)
return err;
- di->total_segments = pick_integer_le(buffer, 0, 2);
- di->last_segment = pick_integer_le(buffer, 4, 2);
- di->dirent_size = (pick_integer_le(buffer, 6, 2) + 7) * 2;
+ di->total_segments = get_u16le(&buffer[0]);
+ di->last_segment = get_u16le(&buffer[4]);
+ di->dirent_size = (get_u16le(&buffer[6]) + 7) * 2;
di->dirents_per_block = (2 * BLOCK_SIZE - 10) / di->dirent_size;
return IMGTOOLERR_SUCCESS;
@@ -465,7 +466,7 @@ static imgtoolerr_t rt11_enum_seek(imgtool::image &image,
return err;
memcpy(&rt11enum->segment_data[BLOCK_SIZE], buffer, sizeof(buffer));
- rt11enum->data = pick_integer_le(rt11enum->segment_data, 8, 2);
+ rt11enum->data = get_u16le(&rt11enum->segment_data[8]);
}
rt11enum->segment = segment;
}
@@ -490,19 +491,19 @@ static imgtoolerr_t rt11_get_next_dirent(imgtool::image &image,
/* populate the resulting dirent */
offset = (rt11enum->index * di->dirent_size) + 10;
- rt_ent.status = pick_integer_le(rt11enum->segment_data, offset, 2);
+ rt_ent.status = get_u16le(&rt11enum->segment_data[offset]);
memcpy(rt_ent.filename, &rt11enum->segment_data[offset + 2], 6);
- rt_ent.filesize = pick_integer_le(rt11enum->segment_data, offset + 8, 2) * BLOCK_SIZE;
+ rt_ent.filesize = get_u16le(&rt11enum->segment_data[offset + 8]) * BLOCK_SIZE;
rt_ent.data = rt11enum->data;
- rt_ent.time = pick_integer_le(rt11enum->segment_data, offset + 12, 2);
- rt11enum->data += pick_integer_le(rt11enum->segment_data, offset + 8, 2);
+ rt_ent.time = get_u16le(&rt11enum->segment_data[offset + 12]);
+ rt11enum->data += get_u16le(&rt11enum->segment_data[offset + 8]);
/* identify next entry */
next_segment = rt11enum->segment;
next_index = rt11enum->index + 1;
if (next_index >= di->dirents_per_block || (rt_ent.status & E_EOS))
{
- next_segment = pick_integer_le(rt11enum->segment_data, 2, 2);
+ next_segment = get_u16le(&rt11enum->segment_data[2]);
next_index = 0;
}
diff --git a/src/tools/imgtool/modules/thomson.cpp b/src/tools/imgtool/modules/thomson.cpp
index f122bc00520..1978e3720ba 100644
--- a/src/tools/imgtool/modules/thomson.cpp
+++ b/src/tools/imgtool/modules/thomson.cpp
@@ -112,10 +112,15 @@
*/
#include "imgtool.h"
+#include "filter.h"
#include "iflopimg.h"
-#include "formats/imageutl.h"
-#include <time.h>
+#include "corestr.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <cstdio>
+#include <ctime>
#define MAXSIZE 80*16*256*2 /* room for two faces, double-density, 80 tracks */
@@ -590,14 +595,14 @@ static int thom_find_dirent(thom_floppy* f, unsigned head,
{
int n = 0;
while ( 1 ) {
- thom_get_dirent( f, head, n, d );
- if ( d->type == THOM_DIRENT_END ) return 0;
- if ( d->type == THOM_DIRENT_FILE ) {
- char buf[13];
- sprintf( buf, "%s.%s", d->name, d->ext );
- if ( ! strcmp( buf, name ) ) return 1;
- }
- n++;
+ thom_get_dirent( f, head, n, d );
+ if ( d->type == THOM_DIRENT_END ) return 0;
+ if ( d->type == THOM_DIRENT_FILE ) {
+ char buf[13];
+ snprintf( buf, std::size(buf), "%s.%s", d->name, d->ext );
+ if ( ! strcmp( buf, name ) ) return 1;
+ }
+ n++;
}
}
@@ -952,7 +957,7 @@ static imgtoolerr_t thom_read_file(imgtool::partition &part,
/* convert filename */
thom_conv_filename( filename, name, ext );
- sprintf( fname, "%s.%s", name, ext );
+ snprintf( fname, std::size(fname), "%s.%s", name, ext );
if ( ! thom_find_dirent( f, head, fname, &d ) )
return IMGTOOLERR_FILENOTFOUND;
@@ -973,7 +978,7 @@ static imgtoolerr_t thom_delete_file(imgtool::partition &part,
/* convert filename */
thom_conv_filename( filename, name, ext );
- sprintf( fname, "%s.%s", name, ext );
+ snprintf( fname, std::size(fname), "%s.%s", name, ext );
if ( ! thom_find_dirent( f, head, fname, &d ) )
return IMGTOOLERR_FILENOTFOUND;
@@ -1002,7 +1007,7 @@ static imgtoolerr_t thom_write_file(imgtool::partition &part,
/* convert filename */
thom_conv_filename( filename, name, ext );
- sprintf( fname, "%s.%s", name, ext );
+ snprintf( fname, std::size(fname), "%s.%s", name, ext );
/* check available space & find dir entry */
if ( thom_find_dirent( f, head, fname, &d ) ) {
@@ -1067,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());
@@ -1081,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;
@@ -1206,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", "@",
@@ -1224,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 */
@@ -1368,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:
@@ -1596,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)))
{
@@ -1740,7 +1744,7 @@ static imgtoolerr_t thom_basic_write_file(imgtool::partition &partition,
if ((c == '\r') || (c == '\n'))
break;
- if (pos <= ARRAY_LENGTH(buf) - 1)
+ if (pos <= std::size(buf) - 1)
{
buf[pos++] = c;
}
@@ -1765,8 +1769,8 @@ static imgtoolerr_t thom_basic_write_file(imgtool::partition &partition,
/* set up line header */
memset(&line_header, 0, sizeof(line_header));
/* linelength or offset (2-bytes) will be rewritten */
- place_integer_be(line_header, 0, 2, 0xffff);
- place_integer_be(line_header, 2, 2, line_number);
+ put_u16be(&line_header[0], 0xffff);
+ put_u16be(&line_header[2], line_number);
/* emit line header */
line_header_loc = mem_stream->tell();
@@ -1841,7 +1845,7 @@ static imgtoolerr_t thom_basic_write_file(imgtool::partition &partition,
/* rewrite the line length */
end_line_loc = mem_stream->tell();
mem_stream->seek(line_header_loc, SEEK_SET);
- place_integer_be(line_header, 0, 2, end_line_loc - line_header_loc);
+ put_u16be(&line_header[0], end_line_loc - line_header_loc);
mem_stream->write(line_header, sizeof(line_header));
mem_stream->seek(end_line_loc, SEEK_SET);
}
@@ -1854,8 +1858,8 @@ static imgtoolerr_t thom_basic_write_file(imgtool::partition &partition,
mem_stream->seek(0, SEEK_SET);
/* Write file header */
- place_integer_be(file_header, 0, 1, 0xFF);
- place_integer_be(file_header, 1, 2, mem_stream->size());
+ file_header[0] = 0xFF;
+ put_u16be(&file_header[1], mem_stream->size());
mem_stream->write(file_header, 3);
mem_stream->seek(0, SEEK_SET);
@@ -1870,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; \
} \
}
@@ -1941,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;
}
}
@@ -2001,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 );
}
}
@@ -2025,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 );
}
}
@@ -2049,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/ti99.cpp b/src/tools/imgtool/modules/ti99.cpp
index 04881c7b5ef..3f57f91db7c 100644
--- a/src/tools/imgtool/modules/ti99.cpp
+++ b/src/tools/imgtool/modules/ti99.cpp
@@ -18,15 +18,18 @@
- check allocation bitmap against corruption when an image is opened
*/
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
#include "imgtool.h"
#include "harddisk.h"
#include "imghd.h"
+#include "opresolv.h"
+
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+
/*
Concepts shared by both disk structures:
----------------------------------------
@@ -166,7 +169,7 @@
The DSK disk structure is used for floppy disks, and a few RAMDISKs as
well. It supports 1600 AUs and 16 MBytes at most (the 16 MByte value is a
- theorical maximum, as I doubt anyone has ever created so big a DSK volume).
+ theoretical maximum, as I doubt anyone has ever created so big a DSK volume).
The disk sector size is always 256 bytes (the only potential exceptions are
the SCSI floppy disk units and the TI-99 simulator on TI-990, but I don't
@@ -524,7 +527,7 @@ struct dsk_vib
/* the allocation unit associated with that */
/* bit has been allocated. */
/* Bits corresponding to system reserved AUs, */
- /* non-existant AUs, and bad AUs, are set to one, too. */
+ /* non-existent AUs, and bad AUs, are set to one, too. */
/* (AU 0 is associated to LSBit of byte 0, */
/* AU 7 to MSBit of byte 0, AU 8 to LSBit */
/* of byte 1, etc.) */
@@ -976,17 +979,15 @@ static imgtoolerr_t open_image_lvl1(imgtool::stream::ptr &&file_handle, ti99_img
if (img_format == if_harddisk)
{
- const hard_disk_info *info;
-
err = imghd_open(*file_handle, &l1_img->harddisk_handle);
if (err)
return err;
- info = imghd_get_header(&l1_img->harddisk_handle);
- l1_img->geometry.cylinders = info->cylinders;
- l1_img->geometry.heads = info->heads;
- l1_img->geometry.secspertrack = info->sectors;
- if (info->sectorbytes != 256)
+ const auto &info = imghd_get_header(&l1_img->harddisk_handle);
+ l1_img->geometry.cylinders = info.cylinders;
+ l1_img->geometry.heads = info.heads;
+ l1_img->geometry.secspertrack = info.sectors;
+ if (info.sectorbytes != 256)
{
imghd_close(&l1_img->harddisk_handle);
return IMGTOOLERR_CORRUPTIMAGE; /* TODO: support 512-byte sectors */
@@ -1300,15 +1301,13 @@ static void dsk_aphysrec_to_sector_address(int aphysrec, const ti99_geometry *ge
geometry (I): disk image geometry
address (O): physical sector address
*/
-#ifdef UNUSED_FUNCTION
-static void win_aphysrec_to_sector_address(int aphysrec, const ti99_geometry *geometry, ti99_sector_address *address)
+[[maybe_unused]] static void win_aphysrec_to_sector_address(int aphysrec, const ti99_geometry &geometry, ti99_sector_address &address)
{
- address.sector = aphysrec % l1_img->geometry.secspertrack;
- aphysrec /= l1_img->geometry.secspertrack;
- address.side = aphysrec % l1_img->geometry.heads;
- address.cylinder = aphysrec / l1_img->geometry.heads;
+ address.sector = aphysrec % geometry.secspertrack;
+ aphysrec /= geometry.secspertrack;
+ address.side = aphysrec % geometry.heads;
+ address.cylinder = aphysrec / geometry.heads;
}
-#endif
/*
Read one 256-byte physical record from a disk image
@@ -1327,7 +1326,7 @@ static int read_absolute_physrec(ti99_lvl1_imgref *l1_img, unsigned aphysrec, vo
if (l1_img->img_format == if_harddisk)
{
#if 0
- win_aphysrec_to_sector_address(aphysrec, & l1_img->geometry, & address);
+ win_aphysrec_to_sector_address(aphysrec, l1_img->geometry, address);
return read_sector(l1_img, & address, dest);
#endif
@@ -1563,7 +1562,7 @@ struct dsk_fdr
UINT16BE xreclen; /* extended record len: if record len is >= 256, */
/* reclen is set to 0 and the actual reclen is */
/* stored here (Myarc HFDC only). TI reserved */
- /* this field for data chain pointer extension, */
+ /* this field for data chain pointer extension, */
/* but this was never implemented. */
uint8_t flags; /* file status flags (see enum above) */
uint8_t recsperphysrec; /* logical records per physrec */
@@ -1579,9 +1578,9 @@ struct dsk_fdr
/* implementation is regarded as a bug because */
/* program files do not define the fixrecs field */
/* field, so program field saved by the HFDC */
- /* DSR may be larger whan they should. */
+ /* DSR may be larger than they should. */
uint8_t eof; /* EOF offset in last physrec for variable length */
- /* record files and program files (0->256)*/
+ /* record files and program files (0->256) */
uint8_t reclen; /* logical record size in bytes ([1,255] 0->256) */
/* Maximum allowable record size for variable */
/* length record files. Reserved for program */
@@ -1625,7 +1624,7 @@ struct win_fdr
/* implementation is regarded as a bug because */
/* program files do not define the fixrecs field */
/* field, so program field saved by the HFDC */
- /* DSR may be larger whan they should. */
+ /* DSR may be larger than they should. */
/* other sibling FDRs: index of the first file */
/* physrec in this particular sibling FDR */
uint8_t eof; /* EOF offset in last physrec for variable length */
@@ -1837,7 +1836,7 @@ static int dsk_read_catalog(struct ti99_lvl2_imgref *l2_img, int aphysrec, ti99_
|| ((dest->files[i].fdr_ptr && dest->files[i+1].fdr_ptr) && (memcmp(dest->files[i].name, dest->files[i+1].name, 10) >= 0)))
{
/* if the catalog is not sorted, we repair it */
- qsort(dest->files, ARRAY_LENGTH(dest->files), sizeof(dest->files[0]),
+ qsort(dest->files, std::size(dest->files), sizeof(dest->files[0]),
cat_file_compare_qsort);
break;
}
@@ -3304,8 +3303,7 @@ static int write_file_physrec(struct ti99_lvl2_fileref *l2_file, unsigned fphysr
/*
Write a field in every fdr record associated to a file
*/
-#ifdef UNUSED_FUNCTION
-static int set_win_fdr_field(struct ti99_lvl2_fileref *l2_file, size_t offset, size_t size, void *data)
+[[maybe_unused]] static int set_win_fdr_field(struct ti99_lvl2_fileref *l2_file, size_t offset, size_t size, void *data)
{
win_fdr fdr_buf;
unsigned fdr_aphysrec;
@@ -3313,7 +3311,7 @@ static int set_win_fdr_field(struct ti99_lvl2_fileref *l2_file, size_t offset, s
for (fdr_aphysrec = l2_file->win.eldestfdr_aphysrec;
fdr_aphysrec && ((errorcode = (read_absolute_physrec(&l2_file->win.l2_img->l1_img, fdr_aphysrec, &fdr_buf) ? IMGTOOLERR_READERROR : 0)) == 0);
- fdr_aphysrec = get_win_fdr_nextsibFDR_physrec(l2_file->win.l2_img, &fdr_buf))
+ fdr_aphysrec = get_win_fdr_nextsibFDR_aphysrec(l2_file->win.l2_img, &fdr_buf))
{
memcpy(((uint8_t *) &fdr_buf) + offset, data, size);
if (write_absolute_physrec(&l2_file->win.l2_img->l1_img, fdr_aphysrec, &fdr_buf))
@@ -3325,7 +3323,6 @@ static int set_win_fdr_field(struct ti99_lvl2_fileref *l2_file, size_t offset, s
return errorcode;
}
-#endif
static uint8_t get_file_flags(struct ti99_lvl2_fileref *l2_file)
{
@@ -3675,11 +3672,10 @@ static void set_file_update_date(struct ti99_lvl2_fileref *l2_file, ti99_date_ti
}
}
-#ifdef UNUSED_FUNCTION
-static void current_date_time(ti99_date_time *reply)
+[[maybe_unused]] static void current_date_time(ti99_date_time *reply)
{
/* All these functions should be ANSI */
- time_t cur_time = time(NULL);
+ time_t cur_time = time(nullptr);
struct tm expanded_time = *localtime(& cur_time);
reply->time_MSB = (expanded_time.tm_hour << 3) | (expanded_time.tm_min >> 3);
@@ -3687,7 +3683,6 @@ static void current_date_time(ti99_date_time *reply)
reply->date_MSB = ((expanded_time.tm_year % 100) << 1) | ((expanded_time.tm_mon+1) >> 3);
reply->date_LSB = ((expanded_time.tm_mon+1) << 5) | expanded_time.tm_mday;
}
-#endif
#if 0
#pragma mark -
@@ -3712,14 +3707,13 @@ struct ti99_lvl3_fileref
int cur_pos_in_phys_rec;
};
-#ifdef UNUSED_FUNCTION
/*
Open a file on level 3.
To open a file on level 3, you must open (or create) the file on level 2,
then pass the file reference to open_file_lvl3.
*/
-static int open_file_lvl3(ti99_lvl3_fileref *l3_file)
+[[maybe_unused]] static int open_file_lvl3(ti99_lvl3_fileref *l3_file)
{
l3_file->cur_log_rec = 0;
l3_file->cur_phys_rec = 0;
@@ -3754,7 +3748,7 @@ static int is_eof(ti99_lvl3_fileref *l3_file)
/*
Read next record from a file
*/
-static int read_next_record(ti99_lvl3_fileref *l3_file, void *dest, int *out_reclen)
+[[maybe_unused]] static int read_next_record(ti99_lvl3_fileref *l3_file, void *dest, int *out_reclen)
{
int errorcode;
uint8_t physrec_buf[256];
@@ -3824,7 +3818,6 @@ static int read_next_record(ti99_lvl3_fileref *l3_file, void *dest, int *out_rec
return 0;
}
-#endif
#if 0
#pragma mark -
@@ -4275,10 +4268,10 @@ static imgtoolerr_t dsk_image_nextenum(imgtool::directory &enumeration, imgtool_
{
if (iter->listing_subdirs)
{
- fname_to_str(ent.filename, iter->image->dsk.catalogs[0].subdirs[iter->index[iter->level]].name, ARRAY_LENGTH(ent.filename));
+ fname_to_str(ent.filename, iter->image->dsk.catalogs[0].subdirs[iter->index[iter->level]].name, std::size(ent.filename));
/* set type of DIR */
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "DIR");
+ snprintf(ent.attr, std::size(ent.attr), "DIR");
/* len in physrecs */
/* @BN@ return length in bytes */
@@ -4299,7 +4292,7 @@ static imgtoolerr_t dsk_image_nextenum(imgtool::directory &enumeration, imgtool_
if (reply)
return IMGTOOLERR_READERROR;
#if 0
- fname_to_str(ent.filename, fdr.name, ARRAY_LENGTH(ent.filename));
+ fname_to_str(ent.filename, fdr.name, std::size(ent.filename));
#else
{
char buf[11];
@@ -4307,19 +4300,19 @@ static imgtoolerr_t dsk_image_nextenum(imgtool::directory &enumeration, imgtool_
ent.filename[0] = '\0';
if (iter->level)
{
- fname_to_str(ent.filename, iter->image->dsk.catalogs[0].subdirs[iter->index[0]].name, ARRAY_LENGTH(ent.filename));
- strncat(ent.filename, ".", ARRAY_LENGTH(ent.filename) - 1);
+ fname_to_str(ent.filename, iter->image->dsk.catalogs[0].subdirs[iter->index[0]].name, std::size(ent.filename));
+ strncat(ent.filename, ".", std::size(ent.filename) - 1);
}
fname_to_str(buf, fdr.name, 11);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
}
#endif
/* parse flags */
if (fdr.flags & fdr99_f_program)
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "PGM%s",
+ snprintf(ent.attr, std::size(ent.attr), "PGM%s",
(fdr.flags & fdr99_f_wp) ? " R/O" : "");
else
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "%c/%c %d%s",
+ snprintf(ent.attr, std::size(ent.attr), "%c/%c %d%s",
(fdr.flags & fdr99_f_int) ? 'I' : 'D',
(fdr.flags & fdr99_f_var) ? 'V' : 'F',
fdr.reclen,
@@ -4399,7 +4392,7 @@ static imgtoolerr_t win_image_nextenum(imgtool::directory &enumeration, imgtool_
if (iter->listing_subdirs)
{
#if 0
- fname_to_str(ent.filename, iter->catalog[iter->level].subdirs[iter->index[iter->level]].name, ARRAY_LENGTH(ent.filename));
+ fname_to_str(ent.filename, iter->catalog[iter->level].subdirs[iter->index[iter->level]].name, std::size(ent.filename));
#else
{
char buf[11];
@@ -4408,16 +4401,16 @@ static imgtoolerr_t win_image_nextenum(imgtool::directory &enumeration, imgtool_
for (i=0; i<iter->level; i++)
{
fname_to_str(buf, iter->catalog[i].subdirs[iter->index[i]].name, 11);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
- strncat(ent.filename, ".", ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
+ strncat(ent.filename, ".", std::size(ent.filename) - 1);
}
fname_to_str(buf, iter->catalog[iter->level].subdirs[iter->index[iter->level]].name, 11);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
}
#endif
/* set type of DIR */
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "DIR");
+ snprintf(ent.attr, std::size(ent.attr), "DIR");
/* len in physrecs */
/* @BN@ return length in bytes */
@@ -4442,7 +4435,7 @@ static imgtoolerr_t win_image_nextenum(imgtool::directory &enumeration, imgtool_
if (reply)
return IMGTOOLERR_READERROR;
#if 0
- fname_to_str(ent.filename, iter->catalog[iter->level].files[iter->index[iter->level]].name, ARRAY_LENGTH(ent.filename));
+ fname_to_str(ent.filename, iter->catalog[iter->level].files[iter->index[iter->level]].name, std::size(ent.filename));
#else
{
char buf[11];
@@ -4451,19 +4444,19 @@ static imgtoolerr_t win_image_nextenum(imgtool::directory &enumeration, imgtool_
for (i=0; i<iter->level; i++)
{
fname_to_str(buf, iter->catalog[i].subdirs[iter->index[i]].name, 11);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
- strncat(ent.filename, ".", ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
+ strncat(ent.filename, ".", std::size(ent.filename) - 1);
}
fname_to_str(buf, iter->catalog[iter->level].files[iter->index[iter->level]].name, 11);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
}
#endif
/* parse flags */
if (fdr.flags & fdr99_f_program)
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "PGM%s",
+ snprintf(ent.attr, std::size(ent.attr), "PGM%s",
(fdr.flags & fdr99_f_wp) ? " R/O" : "");
else
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "%c/%c %d%s",
+ snprintf(ent.attr, std::size(ent.attr), "%c/%c %d%s",
(fdr.flags & fdr99_f_int) ? 'I' : 'D',
(fdr.flags & fdr99_f_var) ? 'V' : 'F',
fdr.reclen,
@@ -4948,7 +4941,7 @@ static imgtoolerr_t dsk_image_deletefile(imgtool::partition &partition, const ch
/* free data AUs */
// fphysrecs =
- get_UINT16BE(fdr.fphysrecs);
+ get_UINT16BE(fdr.fphysrecs);
i = 0;
cluster_index = 0;
@@ -5090,7 +5083,7 @@ static imgtoolerr_t win_image_deletefile(imgtool::partition &partition, const ch
/* check integrity of FDR sibling chain, and go to last sibling */
/* note that as we check that the back chain is consistent with the forward
chain, we will also detect any cycle in the sibling chain, so we do not
- need to check against them explicitely */
+ need to check against them explicitly */
{
int pastendoflist_flag;
unsigned prevfdr_aphysrec;
diff --git a/src/tools/imgtool/modules/ti990hd.cpp b/src/tools/imgtool/modules/ti990hd.cpp
index 8edaeaf3fb6..a78589ff5aa 100644
--- a/src/tools/imgtool/modules/ti990hd.cpp
+++ b/src/tools/imgtool/modules/ti990hd.cpp
@@ -8,12 +8,15 @@
Raphael Nabet, 2003
*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
#include "imgtool.h"
+#include "opresolv.h"
+
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
/* Max sector length is bytes. Generally 256, except for a few older disk
units which use 288-byte-long sectors, and SCSI units which generally use
standard 512-byte-long sectors. */
@@ -96,7 +99,7 @@ enum
Track 1 Sector 0 through N-2: optional disk program image loader
Track 1 Sector N-1: copy of Track 0 Sector 0
Track 1 Sector N: copy of Track 0 Sector 1
- Last cylinder has disagnostic information (reported as .S$DIAG)
+ Last cylinder has diagnostic information (reported as .S$DIAG)
Remaining sectors are used for fdr and data.
*/
@@ -214,7 +217,7 @@ struct ti990_fdr
UINT16BE hkc; /* hask key count: the number of file descriptor records that are present in the directory that hashed to this record number */
UINT16BE hkv; /* hask key value: the result of the hash algorithm for the file name actually covered in this record */
char fnm[8]; /* file name */
- uint8_t rsv[2]; /* reserved */
+ uint8_t rsv[2]; /* reserved */
UINT16BE fl1; /* flags word 1 */
UINT16BE flg; /* flags word 2 */
UINT16BE prs; /* physical record size */
@@ -227,31 +230,31 @@ struct ti990_fdr
UINT32BE eom; /* end of medium record number */
UINT32BE bkm; /* end of medium block number */
UINT16BE ofm; /* end of medium offset / */
- /* prelog number for KIF */
+ /* prelog number for KIF */
UINT32BE fbq; /* free block queue head */
UINT16BE btr; /* B-tree roots block # */
UINT32BE ebq; /* empty block queue head */
UINT16BE kdr; /* key descriptions record # */
- uint8_t ud[6]; /* last update date */
- uint8_t cd[6]; /* creation date */
- uint8_t apb; /* ADU's per block */
- uint8_t bpa; /* blocks per ADU */
- UINT16BE mrs; /* minimumu KIF record size */
- uint8_t sat[64]; /* secondary allocation table: 16 2-word entries. The first word of an entry contains the size, in ADUs, of the secondary allocation. The second word contains the starting ADU of the allocation. */
+ uint8_t ud[6]; /* last update date */
+ uint8_t cd[6]; /* creation date */
+ uint8_t apb; /* ADU's per block */
+ uint8_t bpa; /* blocks per ADU */
+ UINT16BE mrs; /* minimum KIF record size */
+ uint8_t sat[64]; /* secondary allocation table: 16 2-word entries. The first word of an entry contains the size, in ADUs, of the secondary allocation. The second word contains the starting ADU of the allocation. */
/* bytes >86 to >100 are optional */
- uint8_t res[10]; /* reserved: seem to be actually meaningful (at least under DX10 3.6.x) */
+ uint8_t res[10]; /* reserved: seem to be actually meaningful (at least under DX10 3.6.x) */
char uid[8]; /* user id of file creator */
UINT16BE psa; /* public security attribute */
ti990_ace ace[9]; /* 9 access control entries */
- uint8_t fil[2]; /* not used */
+ uint8_t fil[2]; /* not used */
};
/*
ADR record: variant of FDR for Aliases
The fields marked here with *** are in the ADR template to maintain
- compatability with the FDR template.
+ compatibility with the FDR template.
*/
struct ti990_adr
{
@@ -284,19 +287,19 @@ struct ti990_cdr
UINT16BE fill00; /* reserved */
UINT16BE fill01; /* reserved */
UINT16BE fdf; /* flags (same as fdr.flg) */
- uint8_t flg; /* channel flzgs */
- uint8_t iid; /* owner task installed ID */
- uint8_t typ; /* default resource type */
- uint8_t tf; /* resource type flags */
+ uint8_t flg; /* channel flzgs */
+ uint8_t iid; /* owner task installed ID */
+ uint8_t typ; /* default resource type */
+ uint8_t tf; /* resource type flags */
UINT16BE mxl; /* maximum message length */
- uint8_t fill04[6]; /* reserved (and, no, I don't know where fill02 and fill03 have gone) */
+ uint8_t fill04[6]; /* reserved (and, no, I don't know where fill02 and fill03 have gone) */
UINT16BE rna; /* record number of next CDR or ADR */
UINT16BE raf; /* record # of actual FDR */
- uint8_t fill05[110]; /* reserved */
+ uint8_t fill05[110]; /* reserved */
char uid[8]; /* user ID of channel creator */
UINT16BE psa; /* public security attribute */
- uint8_t scg[94]; /* "SDT with 9 control groups" (whatever it means - and, no, 94 is not dividable by 9) */
- uint8_t fill06[8]; /* reserved */
+ uint8_t scg[94]; /* "SDT with 9 control groups" (whatever it means - and, no, 94 is not dividable by 9) */
+ uint8_t fill06[8]; /* reserved */
};
/*
@@ -321,19 +324,18 @@ union directory_entry
*/
struct tifile_header
{
- char tifiles[8]; /* always '\7TIFILES' */
- uint8_t secsused_MSB; /* file length in sectors (big-endian) */
- uint8_t secsused_LSB;
- uint8_t flags; /* see enum above */
- uint8_t recspersec; /* records per sector */
- uint8_t eof; /* current position of eof in last sector (0->255)*/
- uint8_t reclen; /* bytes per record ([1,255] 0->256) */
- uint8_t fixrecs_MSB; /* file length in records (big-endian) */
- uint8_t fixrecs_LSB;
- uint8_t res[128-16]; /* reserved */
+ char tifiles[8]; /* always '\7TIFILES' */
+ uint8_t secsused_MSB; /* file length in sectors (big-endian) */
+ uint8_t secsused_LSB;
+ uint8_t flags; /* see enum above */
+ uint8_t recspersec; /* records per sector */
+ uint8_t eof; /* current position of eof in last sector (0->255)*/
+ uint8_t reclen; /* bytes per record ([1,255] 0->256) */
+ uint8_t fixrecs_MSB; /* file length in records (big-endian) */
+ uint8_t fixrecs_LSB;
+ uint8_t res[128-16]; /* reserved */
};
-
/*
catalog entry (used for in-memory catalog)
*/
@@ -398,11 +400,9 @@ static imgtoolerr_t ti990_image_beginenum(imgtool::directory &enumeration, const
static imgtoolerr_t ti990_image_nextenum(imgtool::directory &enumeration, imgtool_dirent &ent);
static void ti990_image_closeenum(imgtool::directory &enumeration);
static imgtoolerr_t ti990_image_freespace(imgtool::partition &partition, uint64_t *size);
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t ti990_image_readfile(imgtool::partition &partition, const char *fpath, imgtool::stream *destf);
-static imgtoolerr_t ti990_image_writefile(imgtool::partition &partition, const char *fpath, imgtool::stream *sourcef, util::option_resolution *writeoptions);
-static imgtoolerr_t ti990_image_deletefile(imgtool::partition &partition, const char *fpath);
-#endif
+[[maybe_unused]] static imgtoolerr_t ti990_image_readfile(imgtool::partition &partition, const char *fpath, imgtool::stream *destf);
+[[maybe_unused]] static imgtoolerr_t ti990_image_writefile(imgtool::partition &partition, const char *fpath, imgtool::stream *sourcef, util::option_resolution *writeoptions);
+[[maybe_unused]] static imgtoolerr_t ti990_image_deletefile(imgtool::partition &partition, const char *fpath);
static imgtoolerr_t ti990_image_create(imgtool::image &image, imgtool::stream::ptr &&stream, util::option_resolution *createoptions);
enum
@@ -452,11 +452,10 @@ void ti990_get_info(const imgtool_class *imgclass, uint32_t state, union imgtool
}
}
-#ifdef UNUSED_FUNCTION
/*
Convert a C string to a 8-character file name (padded with spaces if necessary)
*/
-static void str_to_fname(char dst[8], const char *src)
+[[maybe_unused]] static void str_to_fname(char dst[8], const char *src)
{
int i;
@@ -478,7 +477,6 @@ static void str_to_fname(char dst[8], const char *src)
i++;
}
}
-#endif
/*
Convert a 8-character file name to a C string (removing trailing spaces if necessary)
@@ -555,7 +553,6 @@ static int read_sector_physical_len(imgtool::stream &file_handle, const ti990_ph
return 0;
}
-#ifdef UNUSED_FUNCTION
/*
Read one sector from a disk image
@@ -564,11 +561,10 @@ static int read_sector_physical_len(imgtool::stream &file_handle, const ti990_ph
geometry: disk geometry (sectors per track, tracks per side, sides)
dest: pointer to a destination buffer of geometry->bytes_per_sector bytes
*/
-static int read_sector_physical(imgtool::stream *file_handle, const ti990_phys_sec_address *address, const ti990_geometry *geometry, void *dest)
+[[maybe_unused]] static int read_sector_physical(imgtool::stream &file_handle, const ti990_phys_sec_address *address, const ti990_geometry *geometry, void *dest)
{
return read_sector_physical_len(file_handle, address, geometry, dest, geometry->bytes_per_sector);
}
-#endif
/*
Write one sector to a disk image
@@ -606,7 +602,6 @@ static int write_sector_physical_len(imgtool::stream &file_handle, const ti990_p
return 0;
}
-#ifdef UNUSED_FUNCTION
/*
Write one sector to a disk image
@@ -615,11 +610,10 @@ static int write_sector_physical_len(imgtool::stream &file_handle, const ti990_p
geometry: disk geometry (sectors per track, tracks per side, sides)
dest: pointer to a source buffer of geometry->bytes_per_sector bytes
*/
-static int write_sector_physical(imgtool::stream *file_handle, const ti990_phys_sec_address *address, const ti990_geometry *geometry, const void *src)
+[[maybe_unused]] static int write_sector_physical(imgtool::stream &file_handle, const ti990_phys_sec_address *address, const ti990_geometry *geometry, const void *src)
{
return write_sector_physical_len(file_handle, address, geometry, src, geometry->bytes_per_sector);
}
-#endif
/*
Convert logical sector address to physical sector address
@@ -651,7 +645,6 @@ static int read_sector_logical_len(imgtool::stream &file_handle, int secnum, con
return read_sector_physical_len(file_handle, &address, geometry, dest, len);
}
-#ifdef UNUSED_FUNCTION
/*
Read one sector from a disk image
@@ -660,11 +653,10 @@ static int read_sector_logical_len(imgtool::stream &file_handle, int secnum, con
geometry: disk geometry (sectors per track, tracks per side, sides)
dest: pointer to a destination buffer of geometry->bytes_per_sector bytes
*/
-static int read_sector_logical(imgtool::stream *file_handle, int secnum, const ti990_geometry *geometry, void *dest)
+[[maybe_unused]] static int read_sector_logical(imgtool::stream &file_handle, int secnum, const ti990_geometry *geometry, void *dest)
{
return read_sector_logical_len(file_handle, secnum, geometry, dest, geometry->bytes_per_sector);
}
-#endif
/*
Write one sector to a disk image
@@ -703,7 +695,6 @@ static int write_sector_logical(imgtool::stream &file_handle, int secnum, const
#pragma mark CATALOG FILE ROUTINES
#endif
-#ifdef UNUSED_FUNCTION
/*
Find the catalog entry and fdr record associated with a file name
@@ -715,7 +706,7 @@ static int write_sector_logical(imgtool::stream &file_handle, int secnum, const
out_parent_fdr_secnum: on output, sector offset of the fdr for the parent
directory fdr (-1 if root) (may be NULL)
*/
-static int find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *catalog_index, int *out_fdr_secnum, int *out_parent_fdr_secnum)
+static imgtoolerr_t find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *catalog_index, int *out_fdr_secnum, int *out_parent_fdr_secnum)
{
int fdr_secnum = -1, parent_fdr_secnum;
int i;
@@ -737,7 +728,7 @@ static int find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *c
do
{
/* read directory header */
- reply = read_sector_logical_len(image->file_handle, base, & image->geometry, &dor, sizeof(dor));
+ reply = read_sector_logical_len(*image->file_handle, base, & image->geometry, &dor, sizeof(dor));
if (reply)
return IMGTOOLERR_READERROR;
@@ -765,7 +756,7 @@ static int find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *c
i = hash_key;
while (1)
{
- reply = read_sector_logical_len(image->file_handle, base + i, & image->geometry,
+ reply = read_sector_logical_len(*image->file_handle, base + i, & image->geometry,
& xdr, 0x86);
if (reply)
return IMGTOOLERR_READERROR;
@@ -800,7 +791,7 @@ static int find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *c
if (flag & fdr_flg_ali)
{
/* read original fdr */
- reply = read_sector_logical_len(image->file_handle, base + get_UINT16BE(xdr.adr.raf),
+ reply = read_sector_logical_len(*image->file_handle, base + get_UINT16BE(xdr.adr.raf),
& image->geometry, & xdr, 0x86);
flag = get_UINT16BE(xdr.fdr.flg);
@@ -835,9 +826,8 @@ static int find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *c
if (out_parent_fdr_secnum)
*out_parent_fdr_secnum = parent_fdr_secnum;
- return 0;
+ return IMGTOOLERR_SUCCESS;
}
-#endif
#if 0
/*
@@ -1251,7 +1241,7 @@ static imgtoolerr_t ti990_image_nextenum(imgtool::directory &enumeration, imgtoo
else
{
#if 0
- fname_to_str(ent.filename, iter->xdr[iter->level].fdr.fnm, ARRAY_LENGTH(ent.filename));
+ fname_to_str(ent.filename, iter->xdr[iter->level].fdr.fnm, std::size(ent.filename));
#else
{
int i;
@@ -1261,11 +1251,11 @@ static imgtoolerr_t ti990_image_nextenum(imgtool::directory &enumeration, imgtoo
for (i=0; i<iter->level; i++)
{
fname_to_str(buf, iter->xdr[i].fdr.fnm, 9);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
- strncat(ent.filename, ".", ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
+ strncat(ent.filename, ".", std::size(ent.filename) - 1);
}
fname_to_str(buf, iter->xdr[iter->level].fdr.fnm, 9);
- strncat(ent.filename, buf, ARRAY_LENGTH(ent.filename) - 1);
+ strncat(ent.filename, buf, std::size(ent.filename) - 1);
}
#endif
@@ -1273,7 +1263,7 @@ static imgtoolerr_t ti990_image_nextenum(imgtool::directory &enumeration, imgtoo
flag = get_UINT16BE(iter->xdr[iter->level].fdr.flg);
if (flag & fdr_flg_cdr)
{
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "CHANNEL");
+ snprintf(ent.attr, std::size(ent.attr), "CHANNEL");
ent.filesize = 0;
}
@@ -1291,7 +1281,7 @@ static imgtoolerr_t ti990_image_nextenum(imgtool::directory &enumeration, imgtoo
fname_to_str(buf, target_fdr.fnm, 9);
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "ALIAS OF %s", buf);
+ snprintf(ent.attr, std::size(ent.attr), "ALIAS OF %s", buf);
ent.filesize = 0;
}
@@ -1341,7 +1331,7 @@ static imgtoolerr_t ti990_image_nextenum(imgtool::directory &enumeration, imgtoo
}
break;
}
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr),
+ snprintf(ent.attr, std::size(ent.attr),
"%s %c %s%s%s%s%s", fmt, (flag & fdr_flg_all) ? 'N' : 'C', type,
(flag & fdr_flg_blb) ? "" : " BLK",
(flag & fdr_flg_tmp) ? " TMP" : "",
@@ -1455,14 +1445,12 @@ static imgtoolerr_t ti990_image_freespace(imgtool::partition &partition, uint64_
return IMGTOOLERR_SUCCESS;
}
-#ifdef UNUSED_FUNCTION
/*
Extract a file from a ti990_image.
*/
static imgtoolerr_t ti990_image_readfile(imgtool::partition &partition, const char *fpath, imgtool::stream *destf)
{
- imgtool::image *img = &partition->image();
- ti990_image *image = get_ti990_image(img);
+ ti990_image *image = get_ti990_image(partition.image());
int catalog_index, fdr_secnum, parent_fdr_secnum;
imgtoolerr_t reply;
@@ -1473,7 +1461,7 @@ static imgtoolerr_t ti990_image_readfile(imgtool::partition &partition, const ch
/* ... */
- return 0;
+ return IMGTOOLERR_SUCCESS;
#if 0
ti99_image *image = (ti99_image*) img;
@@ -1549,7 +1537,7 @@ static imgtoolerr_t ti990_image_readfile(imgtool::partition &partition, const ch
lnks_index++;
}
- return 0;
+ return IMGTOOLERR_SUCCESS;
#endif
}
@@ -1558,8 +1546,7 @@ static imgtoolerr_t ti990_image_readfile(imgtool::partition &partition, const ch
*/
static imgtoolerr_t ti990_image_writefile(imgtool::partition &partition, const char *fpath, imgtool::stream *sourcef, util::option_resolution *writeoptions)
{
- imgtool::image *img = &partition->image();
- ti990_image *image = get_ti990_image(img);
+ ti990_image *image = get_ti990_image(partition.image());
int catalog_index, fdr_secnum, parent_fdr_secnum;
imgtoolerr_t reply;
@@ -1571,7 +1558,7 @@ static imgtoolerr_t ti990_image_writefile(imgtool::partition &partition, const c
/* ... */
- return 0;
+ return IMGTOOLERR_SUCCESS;
#if 0
ti99_image *image = (ti99_image*) img;
@@ -1673,7 +1660,7 @@ static imgtoolerr_t ti990_image_writefile(imgtool::partition &partition, const c
if (write_sector_logical(image->file_handle, 0, & image->geometry, &image->sec0))
return IMGTOOLERR_WRITEERROR;
- return 0;
+ return IMGTOOLERR_SUCCESS;
#endif
}
@@ -1682,8 +1669,7 @@ static imgtoolerr_t ti990_image_writefile(imgtool::partition &partition, const c
*/
static imgtoolerr_t ti990_image_deletefile(imgtool::partition &partition, const char *fpath)
{
- imgtool::image *img = &partition->image();
- ti990_image *image = get_ti990_image(img);
+ ti990_image *image = get_ti990_image(partition.image());
int catalog_index, fdr_secnum, parent_fdr_secnum;
imgtoolerr_t reply;
@@ -1694,7 +1680,7 @@ static imgtoolerr_t ti990_image_deletefile(imgtool::partition &partition, const
/* ... */
- return 0;
+ return IMGTOOLERR_SUCCESS;
#if 0
ti99_image *image = (ti99_image*) img;
@@ -1762,10 +1748,9 @@ static imgtoolerr_t ti990_image_deletefile(imgtool::partition &partition, const
if (write_sector_logical(image->file_handle, 0, & image->geometry, &image->sec0))
return IMGTOOLERR_WRITEERROR;
- return 0;
+ return IMGTOOLERR_SUCCESS;
#endif
}
-#endif
/*
Create a blank ti990_image.
diff --git a/src/tools/imgtool/modules/vzdos.cpp b/src/tools/imgtool/modules/vzdos.cpp
index bf46863bb28..b7dee751434 100644
--- a/src/tools/imgtool/modules/vzdos.cpp
+++ b/src/tools/imgtool/modules/vzdos.cpp
@@ -1,4 +1,4 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Dirk Best
/****************************************************************************
@@ -8,15 +8,23 @@
****************************************************************************/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "formats/vt_dsk.h"
+#include "filter.h"
#include "iflopimg.h"
+#include "formats/vt_dsk_legacy.h"
+
+#include "corestr.h"
+#include "hashing.h"
+#include "multibyte.h"
+#include "opresolv.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
/*
sector format
@@ -44,13 +52,22 @@ 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() :
+ start_track(0), start_sector(0),
+ start_address(0), end_address(0)
+ {
+ memset(&node, 0, sizeof(node));
+ }
};
struct vz_iterator
@@ -80,18 +97,6 @@ static int vzdos_get_fname_len(const char *fname)
return len;
}
-/* calculate checksum-16 of buffer */
-static uint16_t chksum16(uint8_t *buffer, int len)
-{
- int i;
- uint16_t sum = 0;
-
- for (i = 0; i < len; i++)
- sum += buffer[i];
-
- return sum;
-}
-
/* returns the offset where the actual sector data starts */
static imgtoolerr_t vzdos_get_data_start(imgtool::image &img, int track, int sector, int *start)
{
@@ -127,7 +132,7 @@ static imgtoolerr_t vzdos_read_sector_data(imgtool::image &img, int track, int s
if (ret) return (imgtoolerr_t)ret;
/* verify sector checksums */
- if (pick_integer_le(buffer, DATA_SIZE + 2, 2) != chksum16(buffer, DATA_SIZE + 2))
+ if (get_u16le(&buffer[DATA_SIZE + 2]) != util::sum16_creator::simple(buffer, DATA_SIZE + 2))
return IMGTOOLERR_CORRUPTFILE;
memcpy(data, &buffer, DATA_SIZE + 2);
@@ -145,7 +150,7 @@ static imgtoolerr_t vzdos_write_sector_data(imgtool::image &img, int track, int
if (ret) return (imgtoolerr_t)ret;
memcpy(buffer, data, DATA_SIZE + 2);
- place_integer_le(buffer, DATA_SIZE + 2, 2, chksum16(data, DATA_SIZE + 2));
+ put_u16le(&buffer[DATA_SIZE + 2], util::sum16_creator::simple(data, DATA_SIZE + 2));
ret = floppy_write_sector(imgtool_floppy(img), 0, track, sector_order[sector], data_start, buffer, sizeof(buffer), 0); /* TODO: pass ddam argument from imgtool */
if (ret) return (imgtoolerr_t)ret;
@@ -157,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);
}
@@ -166,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);
- ent->start_track = pick_integer_le(&buffer[entry], 10, 1);
- ent->start_sector = pick_integer_le(&buffer[entry], 11, 1);
- ent->start_address = pick_integer_le(&buffer[entry], 12, 2);
- ent->end_address = pick_integer_le(&buffer[entry], 14, 2);
+ 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 */
@@ -206,10 +210,10 @@ static imgtoolerr_t vzdos_set_dirent(imgtool::image &img, int index, vzdos_diren
entry = ((index % 8) * sizeof(vzdos_dirent));
memcpy(&buffer[entry], &ent, 10);
- place_integer_le(buffer, entry + 10, 1, ent.start_track);
- place_integer_le(buffer, entry + 11, 1, ent.start_sector);
- place_integer_le(buffer, entry + 12, 2, ent.start_address);
- place_integer_le(buffer, entry + 14, 2, ent.end_address);
+ buffer[entry + 10] = ent.start_track;
+ buffer[entry + 11] = ent.start_sector;
+ put_u16le(&buffer[entry + 12], ent.start_address);
+ put_u16le(&buffer[entry + 14], ent.end_address);
/* save new sector */
ret = vzdos_write_sector_data(img, 0, (int) index / 8, buffer);
@@ -221,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];
@@ -246,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)
@@ -359,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] = {
@@ -368,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;
}
@@ -424,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;
@@ -445,7 +441,7 @@ static imgtoolerr_t vzdos_diskimage_nextenum(imgtool::directory &enumeration, im
default: type = "Unknown";
}
- snprintf(ent.attr, ARRAY_LENGTH(ent.attr), "%s", type);
+ snprintf(ent.attr, std::size(ent.attr), "%s", type);
iter->index++;
}
@@ -500,12 +496,12 @@ static imgtoolerr_t vzdos_diskimage_readfile(imgtool::partition &partition, cons
if (ret) return ret;
/* detect sectors pointing to themselfs */
- if ((track == (int)pick_integer_le(buffer, DATA_SIZE, 1)) && (sector == (int)pick_integer_le(buffer, DATA_SIZE + 1, 1)))
+ if ((track == (int)buffer[DATA_SIZE]) && (sector == (int)buffer[DATA_SIZE + 1]))
return IMGTOOLERR_CORRUPTIMAGE;
/* load next track and sector values */
- track = pick_integer_le(buffer, DATA_SIZE, 1);
- sector = pick_integer_le(buffer, DATA_SIZE + 1, 1);
+ track = buffer[DATA_SIZE];
+ sector = buffer[DATA_SIZE + 1];
/* track 0 is invalid */
if ((track == 0) && (filesize > DATA_SIZE))
@@ -581,8 +577,8 @@ static imgtoolerr_t vzdos_diskimage_deletefile(imgtool::partition &partition, co
if (ret) return ret;
/* load next track and sector values */
- next_track = pick_integer_le(buffer, DATA_SIZE, 1);
- next_sector = pick_integer_le(buffer, DATA_SIZE + 1, 1);
+ next_track = buffer[DATA_SIZE];
+ next_sector = buffer[DATA_SIZE + 1];
/* overwrite sector with default values */
ret = vzdos_clear_sector(img, track, sector);
@@ -617,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 */
@@ -702,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 */
@@ -711,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());
@@ -751,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";
}
@@ -824,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;
@@ -839,8 +830,8 @@ 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);
- place_integer_le(header, 22, 2, entry.start_address);
+ 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 */
destf.write(header, sizeof(header));
@@ -863,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 = pick_integer_le(header, 22, 2);
+ 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 */
@@ -887,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)
{
@@ -936,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 9a29180c9da..f68f8b4eac6 100644
--- a/src/tools/imgtool/stream.cpp
+++ b/src/tools/imgtool/stream.cpp
@@ -8,20 +8,180 @@
***************************************************************************/
-#include <stdio.h>
-#include <string.h>
-#include <zlib.h>
+#include "stream.h"
-#include "unzip.h"
-#include "osdcore.h"
#include "imgtool.h"
+#include "corefile.h"
+#include "ioprocs.h"
+#include "path.h"
+#include "unzip.h"
+
+#include <cassert>
+#include <cstdarg>
+#include <cstdio>
+#include <cstring>
+#include <tuple>
+
+
+
+namespace imgtool {
+
+namespace {
+
+class stream_read_wrapper : public virtual util::random_read
+{
+public:
+ stream_read_wrapper(stream::ptr &&stream, std::uint8_t filler) noexcept
+ : m_stream(stream.release())
+ , m_filler(filler)
+ , m_close(true)
+ {
+ assert(m_stream);
+ }
+
+ stream_read_wrapper(stream &stream, std::uint8_t filler) noexcept
+ : m_stream(&stream)
+ , m_filler(filler)
+ , m_close(false)
+ {
+ }
+
+ virtual ~stream_read_wrapper()
+ {
+ if (m_close)
+ delete m_stream;
+ }
+
+ virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override
+ {
+ m_stream->seek(offset, whence);
+ return std::error_condition();
+ }
+
+ virtual std::error_condition tell(std::uint64_t &result) noexcept override
+ {
+ result = m_stream->tell();
+ return std::error_condition();
+ }
+
+ virtual std::error_condition length(std::uint64_t &result) noexcept override
+ {
+ result = m_stream->size();
+ return std::error_condition();
+ }
+
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ actual = m_stream->read(buffer, length);
+ if (actual < length)
+ std::memset(reinterpret_cast<std::uint8_t *>(buffer) + actual, m_filler, length - actual);
+ return std::error_condition();
+ }
+
+ 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);
+ actual = m_stream->read(buffer, length);
+ m_stream->seek(pos, SEEK_SET);
+ if (actual < length)
+ std::memset(reinterpret_cast<std::uint8_t *>(buffer) + actual, m_filler, length - actual);
+ return std::error_condition();
+ }
+
+protected:
+ stream *const m_stream;
+ std::uint8_t m_filler;
+ bool const m_close;
+};
+
+
+class stream_read_write_wrapper : public stream_read_wrapper, public util::random_read_write
+{
+public:
+ using stream_read_wrapper::stream_read_wrapper;
+
+ virtual std::error_condition finalize() noexcept override
+ {
+ return std::error_condition();
+ }
+
+ virtual std::error_condition flush() noexcept override
+ {
+ return std::error_condition();
+ }
+
+ virtual std::error_condition write_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();
+ if (size < pos)
+ {
+ m_stream->seek(size, SEEK_SET);
+ size += m_stream->fill(m_filler, pos - size);
+ }
+ actual = (size >= pos) ? m_stream->write(buffer, length) : 0U;
+ return (actual == length) ? std::error_condition() : std::errc::io_error;
+ }
+
+ virtual std::error_condition write_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();
+ if (offset > size)
+ {
+ m_stream->seek(size, SEEK_SET);
+ size += m_stream->fill(m_filler, offset - size);
+ }
+ else
+ {
+ m_stream->seek(offset, SEEK_SET);
+ }
+ actual = (size >= offset) ? m_stream->write(buffer, length) : 0U;
+ m_stream->seek(pos, SEEK_SET);
+ return (actual == length) ? std::error_condition() : std::errc::io_error;
+ }
+};
+
+} // anonymous namespace
+
+
+util::random_read::ptr stream_read(stream::ptr &&s, std::uint8_t filler) noexcept
+{
+ util::random_read::ptr result;
+ if (s)
+ result.reset(new (std::nothrow) stream_read_wrapper(std::move(s), filler));
+ return result;
+}
+
+util::random_read::ptr stream_read(stream &s, std::uint8_t filler) noexcept
+{
+ util::random_read::ptr result(new (std::nothrow) stream_read_wrapper(s, filler));
+ return result;
+}
+
+util::random_read_write::ptr stream_read_write(stream::ptr &&s, std::uint8_t filler) noexcept
+{
+ util::random_read_write::ptr result;
+ if (s)
+ result.reset(new (std::nothrow) stream_read_write_wrapper(std::move(s), filler));
+ return result;
+}
+
+util::random_read_write::ptr stream_read_write(stream &s, std::uint8_t filler) noexcept
+{
+ util::random_read_write::ptr result(new (std::nothrow) stream_read_write_wrapper(s, filler));
+ return result;
+}
+
+
//-------------------------------------------------
// ctor
//-------------------------------------------------
-imgtool::stream::stream(bool wp)
+stream::stream(bool wp)
: imgtype(IMG_FILE)
, write_protect(wp)
, position(0)
@@ -36,14 +196,15 @@ imgtool::stream::stream(bool wp)
// ctor
//-------------------------------------------------
-imgtool::stream::stream(bool wp, util::core_file::ptr &&f)
+stream::stream(bool wp, util::core_file::ptr &&f)
: imgtype(IMG_FILE)
, write_protect(wp)
, position(0)
- , filesize(f->size())
+ , filesize(0)
, file(std::move(f))
, buffer(nullptr)
{
+ file->length(filesize); // FIXME: check error return
}
@@ -51,7 +212,7 @@ imgtool::stream::stream(bool wp, util::core_file::ptr &&f)
// ctor
//-------------------------------------------------
-imgtool::stream::stream(bool wp, std::size_t size)
+stream::stream(bool wp, std::size_t size)
: imgtype(IMG_MEM)
, write_protect(wp)
, position(0)
@@ -66,7 +227,7 @@ imgtool::stream::stream(bool wp, std::size_t size)
// ctor
//-------------------------------------------------
-imgtool::stream::stream(bool wp, std::size_t size, void *buf)
+stream::stream(bool wp, std::size_t size, void *buf)
: imgtype(IMG_MEM)
, write_protect(wp)
, position(0)
@@ -81,7 +242,7 @@ imgtool::stream::stream(bool wp, std::size_t size, void *buf)
// dtor
//-------------------------------------------------
-imgtool::stream::~stream()
+stream::~stream()
{
if (buffer)
free(buffer);
@@ -92,39 +253,39 @@ imgtool::stream::~stream()
// open_zip
//-------------------------------------------------
-imgtool::stream::ptr imgtool::stream::open_zip(const std::string &zipname, const char *subname, int read_or_write)
+stream::ptr stream::open_zip(const std::string &zipname, const char *subname, int read_or_write)
{
if (read_or_write)
- return imgtool::stream::ptr();
+ return stream::ptr();
/* check to see if the file exists */
FILE *f = fopen(zipname.c_str(), "r");
if (!f)
- return imgtool::stream::ptr();
+ return stream::ptr();
fclose(f);
- imgtool::stream::ptr imgfile(new imgtool::stream(true));
+ stream::ptr imgfile(new stream(true));
imgfile->imgtype = IMG_MEM;
util::archive_file::ptr z;
util::archive_file::open_zip(zipname, z);
if (!z)
- return imgtool::stream::ptr();
+ return stream::ptr();
int zipent = z->first_file();
while ((zipent >= 0) && subname && strcmp(subname, z->current_name().c_str()))
zipent = z->next_file();
if (zipent < 0)
- return imgtool::stream::ptr();
+ return stream::ptr();
imgfile->filesize = z->current_uncompressed_length();
imgfile->buffer = reinterpret_cast<std::uint8_t *>(malloc(z->current_uncompressed_length()));
if (!imgfile->buffer)
- return imgtool::stream::ptr();
+ return stream::ptr();
- if (z->decompress(imgfile->buffer, z->current_uncompressed_length()) != util::archive_file::error::NONE)
- return imgtool::stream::ptr();
+ if (z->decompress(imgfile->buffer, z->current_uncompressed_length()))
+ return stream::ptr();
return imgfile;
}
@@ -135,7 +296,7 @@ imgtool::stream::ptr imgtool::stream::open_zip(const std::string &zipname, const
// open
//-------------------------------------------------
-imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read_or_write)
+stream::ptr stream::open(const std::string &filename, int read_or_write)
{
static const uint32_t write_modes[] =
{
@@ -144,23 +305,22 @@ imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read
OPEN_FLAG_READ | OPEN_FLAG_WRITE,
OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE
};
- imgtool::stream::ptr s;
+ stream::ptr s;
char c;
// maybe we are just a ZIP?
- std::string ext = core_filename_extract_extension(filename);
- if (!core_stricmp(ext.c_str(), ".zip"))
+ if (core_filename_ends_with(filename, ".zip"))
return open_zip(filename, nullptr, read_or_write);
util::core_file::ptr f = nullptr;
auto const filerr = util::core_file::open(filename, write_modes[read_or_write], f);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
if (!read_or_write)
{
int const len = filename.size();
- /* can't open the file; try opening ZIP files with other names */
+ // can't open the file; try opening ZIP files with other names
std::vector<char> buf(len + 1);
strcpy(&buf[0], filename.c_str());
@@ -179,11 +339,11 @@ imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read
return s;
}
- /* ah well, it was worth a shot */
- return imgtool::stream::ptr();
+ // ah well, it was worth a shot
+ return stream::ptr();
}
- imgtool::stream::ptr imgfile(new imgtool::stream(read_or_write ? false : true, std::move(f)));
+ stream::ptr imgfile(new stream(read_or_write ? false : true, std::move(f)));
// normal file
return imgfile;
@@ -194,11 +354,11 @@ imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read
// open_write_stream
//-------------------------------------------------
-imgtool::stream::ptr imgtool::stream::open_write_stream(int size)
+stream::ptr stream::open_write_stream(int size)
{
- imgtool::stream::ptr imgfile(new imgtool::stream(false, size));
+ stream::ptr imgfile(new stream(false, size));
if (!imgfile->buffer)
- return imgtool::stream::ptr();
+ return stream::ptr();
return imgfile;
}
@@ -208,9 +368,9 @@ imgtool::stream::ptr imgtool::stream::open_write_stream(int size)
// open_mem
//-------------------------------------------------
-imgtool::stream::ptr imgtool::stream::open_mem(void *buf, size_t sz)
+stream::ptr stream::open_mem(void *buf, size_t sz)
{
- imgtool::stream::ptr imgfile(new imgtool::stream(false, sz, buf));
+ stream::ptr imgfile(new stream(false, sz, buf));
return imgfile;
}
@@ -220,7 +380,7 @@ imgtool::stream::ptr imgtool::stream::open_mem(void *buf, size_t sz)
// core_file
//-------------------------------------------------
-util::core_file *imgtool::stream::core_file()
+util::core_file *stream::core_file()
{
return (imgtype == IMG_FILE) ? file.get() : nullptr;
}
@@ -230,22 +390,22 @@ util::core_file *imgtool::stream::core_file()
// read
//-------------------------------------------------
-uint32_t imgtool::stream::read(void *buf, uint32_t sz)
+uint32_t stream::read(void *buf, uint32_t sz)
{
- uint32_t result = 0;
+ std::error_condition err;
+ size_t result = 0;
switch(imgtype)
{
case IMG_FILE:
- assert(sz == (uint32_t) sz);
- file->seek(position, SEEK_SET);
- result = file->read(buf, (uint32_t) sz);
+ if (!file->seek(position, SEEK_SET))
+ std::tie(err, result) = util::read(*file, buf, sz); // FIXME: check error return
break;
case IMG_MEM:
- /* do we have to limit sz? */
+ // do we have to limit sz?
if (sz > (filesize - position))
- sz = (uint32_t) (filesize - position);
+ sz = uint32_t(filesize - position);
memcpy(buf, buffer + position, sz);
result = sz;
@@ -264,31 +424,32 @@ uint32_t imgtool::stream::read(void *buf, uint32_t sz)
// write
//-------------------------------------------------
-uint32_t imgtool::stream::write(const void *buf, uint32_t sz)
+uint32_t stream::write(const void *buf, uint32_t sz)
{
- void *new_buffer;
- uint32_t result = 0;
+ std::error_condition err;
+ size_t result = 0;
switch(imgtype)
{
case IMG_MEM:
if (!write_protect)
{
- /* do we have to expand the buffer? */
- if (filesize < position + sz)
+ // do we have to expand the buffer?
+ const uint64_t end = position + sz;
+ if ((filesize < end) && (size_t(end) == end))
{
- /* try to expand the buffer */
- new_buffer = realloc(buffer , position + sz);
+ // try to expand the buffer
+ void *const new_buffer = realloc(buffer, size_t(end));
if (new_buffer)
{
- buffer = (uint8_t*)new_buffer;
- filesize = position + sz;
+ buffer = reinterpret_cast<uint8_t *>(new_buffer);
+ filesize = end;
}
}
- /* do we have to limit sz? */
+ // do we have to limit sz?
if (sz > (filesize - position))
- sz = (uint32_t) (filesize - position);
+ sz = uint32_t(filesize - position);
memcpy(buffer + position, buf, sz);
result = sz;
@@ -296,8 +457,8 @@ uint32_t imgtool::stream::write(const void *buf, uint32_t sz)
break;
case IMG_FILE:
- file->seek(position, SEEK_SET);
- result = file->write(buf, sz);
+ if (!file->seek(position, SEEK_SET))
+ std::tie(err, result) = util::write(*file, buf, sz); // FIXME: check error return
break;
default:
@@ -305,10 +466,10 @@ uint32_t imgtool::stream::write(const void *buf, uint32_t sz)
break;
}
- /* advance the file pointer */
+ // advance the file pointer
position += result;
- /* did we grow the file */
+ // did we grow the file
if (position > filesize)
filesize = position;
return result;
@@ -319,39 +480,17 @@ uint32_t imgtool::stream::write(const void *buf, uint32_t sz)
// size
//-------------------------------------------------
-uint64_t imgtool::stream::size() const
+uint64_t stream::size() const
{
return filesize;
}
//-------------------------------------------------
-// getptr
-//-------------------------------------------------
-
-void *imgtool::stream::getptr()
-{
- void *ptr;
-
- switch(imgtype)
- {
- case IMG_MEM:
- ptr = buffer;
- break;
-
- default:
- ptr = nullptr;
- break;
- }
- return ptr;
-}
-
-
-//-------------------------------------------------
// seek
//-------------------------------------------------
-int imgtool::stream::seek(int64_t pos, int where)
+int stream::seek(int64_t pos, int where)
{
switch(where)
{
@@ -379,7 +518,7 @@ int imgtool::stream::seek(int64_t pos, int where)
// tell
//-------------------------------------------------
-uint64_t imgtool::stream::tell()
+uint64_t stream::tell()
{
return position;
}
@@ -389,7 +528,7 @@ uint64_t imgtool::stream::tell()
// transfer
//-------------------------------------------------
-uint64_t imgtool::stream::transfer(imgtool::stream &dest, imgtool::stream &source, uint64_t sz)
+uint64_t stream::transfer(stream &dest, stream &source, uint64_t sz)
{
uint64_t result = 0;
uint64_t readsz;
@@ -409,69 +548,17 @@ uint64_t imgtool::stream::transfer(imgtool::stream &dest, imgtool::stream &sourc
// transfer_all
//-------------------------------------------------
-uint64_t imgtool::stream::transfer_all(imgtool::stream &dest, imgtool::stream &source)
+uint64_t stream::transfer_all(stream &dest, stream &source)
{
return transfer(dest, source, source.size());
}
//-------------------------------------------------
-// crc
-//-------------------------------------------------
-
-int imgtool::stream::crc(unsigned long *result)
-{
- size_t sz;
- void *ptr;
-
- switch(imgtype)
- {
- case IMG_MEM:
- *result = crc32(0, (unsigned char *) buffer, (size_t) filesize);
- break;
-
- default:
- sz = size();
- ptr = malloc(sz);
- if (!ptr)
- return IMGTOOLERR_OUTOFMEMORY;
- seek(0, SEEK_SET);
- if (read(ptr, sz) != sz)
- {
- free(ptr);
- return IMGTOOLERR_READERROR;
- }
- *result = crc32(0, (const Bytef*)ptr, sz);
- free(ptr);
- break;
- }
- return 0;
-}
-
-
-//-------------------------------------------------
-// file_crc
-//-------------------------------------------------
-
-int imgtool::stream::file_crc(const char *fname, unsigned long *result)
-{
- int err;
- imgtool::stream::ptr f;
-
- f = imgtool::stream::open(fname, OSD_FOPEN_READ);
- if (!f)
- return IMGTOOLERR_FILENOTFOUND;
-
- err = f->crc(result);
- return err;
-}
-
-
-//-------------------------------------------------
// fill
//-------------------------------------------------
-uint64_t imgtool::stream::fill(unsigned char b, uint64_t sz)
+uint64_t stream::fill(unsigned char b, uint64_t sz)
{
uint64_t outsz;
char buf[1024];
@@ -492,7 +579,7 @@ uint64_t imgtool::stream::fill(unsigned char b, uint64_t sz)
// is_read_only
//-------------------------------------------------
-bool imgtool::stream::is_read_only()
+bool stream::is_read_only()
{
return write_protect;
}
@@ -502,7 +589,7 @@ bool imgtool::stream::is_read_only()
// putc
//-------------------------------------------------
-uint32_t imgtool::stream::putc(char c)
+uint32_t stream::putc(char c)
{
return write(&c, 1);
}
@@ -512,7 +599,7 @@ uint32_t imgtool::stream::putc(char c)
// puts
//-------------------------------------------------
-uint32_t imgtool::stream::puts(const char *s)
+uint32_t stream::puts(const char *s)
{
return write(s, strlen(s));
}
@@ -522,7 +609,7 @@ uint32_t imgtool::stream::puts(const char *s)
// printf
//-------------------------------------------------
-uint32_t imgtool::stream::printf(const char *fmt, ...)
+uint32_t stream::printf(const char *fmt, ...)
{
va_list va;
char buf[256];
@@ -533,3 +620,5 @@ uint32_t imgtool::stream::printf(const char *fmt, ...)
return puts(buf);
}
+
+} // namespace imgtool
diff --git a/src/tools/imgtool/stream.h b/src/tools/imgtool/stream.h
index 2b7afbacd5e..8083dbac9d9 100644
--- a/src/tools/imgtool/stream.h
+++ b/src/tools/imgtool/stream.h
@@ -7,77 +7,84 @@
Code for implementing Imgtool streams
***************************************************************************/
+#ifndef MAME_TOOLS_IMGTOOL_STREAM_H
+#define MAME_TOOLS_IMGTOOL_STREAM_H
-#ifndef STREAM_H
-#define STREAM_H
+#pragma once
-#include "imgterrs.h"
-#include "corefile.h"
+#include "utilfwd.h"
-namespace imgtool
+#include "osdcomm.h"
+
+#include <cstdint>
+#include <memory>
+#include <string>
+
+
+namespace imgtool {
+
+class stream
{
- class stream
+public:
+ typedef std::unique_ptr<stream> ptr;
+
+ ~stream();
+
+ static imgtool::stream::ptr open(const std::string &filename, int read_or_write); /* similar params to mame_fopen */
+ static imgtool::stream::ptr open_write_stream(int filesize);
+ static imgtool::stream::ptr open_mem(void *buf, size_t sz);
+
+ util::core_file *core_file();
+ uint32_t read(void *buf, uint32_t sz);
+ uint32_t write(const void *buf, uint32_t sz);
+ uint64_t size() const;
+ int seek(int64_t pos, int where);
+ uint64_t tell();
+ uint32_t putc(char c);
+ uint32_t puts(const char *s);
+ uint32_t printf(const char *fmt, ...) ATTR_PRINTF(2, 3);
+
+ // transfers sz bytes from source to dest
+ static uint64_t transfer(imgtool::stream &dest, imgtool::stream &source, uint64_t sz);
+ static uint64_t transfer_all(imgtool::stream &dest, imgtool::stream &source);
+
+ // fills sz bytes with b
+ uint64_t fill(unsigned char b, uint64_t sz);
+
+ // returns whether a stream is read only or not
+ bool is_read_only();
+
+private:
+ enum imgtype_t
{
- public:
- typedef std::unique_ptr<stream> ptr;
-
- ~stream();
-
- static imgtool::stream::ptr open(const std::string &filename, int read_or_write); /* similar params to mame_fopen */
- static imgtool::stream::ptr open_write_stream(int filesize);
- static imgtool::stream::ptr open_mem(void *buf, size_t sz);
-
- util::core_file *core_file();
- uint32_t read(void *buf, uint32_t sz);
- uint32_t write(const void *buf, uint32_t sz);
- uint64_t size() const;
- int seek(int64_t pos, int where);
- uint64_t tell();
- void *getptr();
- uint32_t putc(char c);
- uint32_t puts(const char *s);
- uint32_t printf(const char *fmt, ...) ATTR_PRINTF(2, 3);
-
- // transfers sz bytes from source to dest
- static uint64_t transfer(imgtool::stream &dest, imgtool::stream &source, uint64_t sz);
- static uint64_t transfer_all(imgtool::stream &dest, imgtool::stream &source);
-
- // fills sz bytes with b
- uint64_t fill(unsigned char b, uint64_t sz);
-
- // returns the CRC of a file
- int crc(unsigned long *result);
- static int file_crc(const char *fname, unsigned long *result);
-
- // returns whether a stream is read only or not
- bool is_read_only();
-
- private:
- enum imgtype_t
- {
- IMG_FILE,
- IMG_MEM
- };
-
- imgtype_t imgtype;
- bool write_protect;
- std::uint64_t position;
- std::uint64_t filesize;
-
- util::core_file::ptr file;
- std::uint8_t *buffer;
-
- // ctors
- stream(bool wp);
- stream(bool wp, util::core_file::ptr &&f);
- stream(bool wp, std::size_t size);
- stream(bool wp, std::size_t size, void *buf);
-
- // private methods
- static stream::ptr open_zip(const std::string &zipname, const char *subname, int read_or_write);
+ IMG_FILE,
+ IMG_MEM
};
-}
+ imgtype_t imgtype;
+ bool write_protect;
+ std::uint64_t position;
+ std::uint64_t filesize;
+
+ std::unique_ptr<util::core_file> file;
+ std::uint8_t *buffer;
+
+ // ctors
+ stream(bool wp);
+ stream(bool wp, std::unique_ptr<util::core_file> &&f);
+ stream(bool wp, std::size_t size);
+ stream(bool wp, std::size_t size, void *buf);
+
+ // private methods
+ static stream::ptr open_zip(const std::string &zipname, const char *subname, int read_or_write);
+};
+
+
+std::unique_ptr<util::random_read> stream_read(stream::ptr &&s, std::uint8_t filler) noexcept;
+std::unique_ptr<util::random_read> stream_read(stream &s, std::uint8_t filler) noexcept;
+std::unique_ptr<util::random_read_write> stream_read_write(stream::ptr &&s, std::uint8_t filler) noexcept;
+std::unique_ptr<util::random_read_write> stream_read_write(stream &s, std::uint8_t filler) noexcept;
+} // namespace imgtool
-#endif /* STREAM_H */
+#endif // MAME_TOOLS_IMGTOOL_STREAM_H
diff --git a/src/tools/jedutil.cpp b/src/tools/jedutil.cpp
index d1c49ec7a79..f9f57ff8fed 100644
--- a/src/tools/jedutil.cpp
+++ b/src/tools/jedutil.cpp
@@ -54,11 +54,19 @@
PAL16V8R = QP20 QF2194
PALCE16V8 = QP20 QF2194
GAL16V8A = QP20 QF2194
+ ATF16V8B = QP20 QF2194
18CV8 = QP20 QF2696
AMPAL18P8 = QP20 QF2600
+ 5C032 = QP20
+
+ PLUS16L8 = QP20
+ PLUS16R4 = QP20
+ PLUS16R6 = QP20
+ PLUS16R8 = QP20
+
EPL10P8 = QP20
EPL12P6 = QP20
EPL14P4 = QP20
@@ -68,6 +76,9 @@
EPL16RP6 = QP20
EPL16RP4 = QP20
+ PAL16A4 = QP20
+ PAL16X4 = QP20
+
24-pin devices:
PAL6L16 = QP24 QF0192
PAL8L14 = QP24 QF0224
@@ -94,10 +105,22 @@
PAL20X8 = QP24 QF1600
PAL20X10 = QP24 QF1600
- PAL22V10 = QP24 QF5828?
-
GAL20V8A = QP24 QF2706
+ PALCE20V8 = QP24 QF2706
+ ATF20V10B = QP24 QF2706
+
GAL22V10 = QP24 QF5892
+ ATF22V10C = QP24 QF5892 (GAL Mode)
+
+ PALCE22V10 = QP24 QF5828
+ PAL22V10 = QP24 QF5828
+ ATF22V10C = QP24 QF5828 (PAL Mode)
+
+ ATF22V10C = QP24 QF5893 (Power Down Mode)
+
+ PLS173 = QP24
+
+ GAL6001 = QP24
28-pin devices:
PLS100 = QP28 QF1928 (Tri-State)
@@ -112,11 +135,17 @@
***************************************************************************/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cctype>
+
+#include <set>
+#include <vector>
+
#include "corestr.h"
+#include "ioprocs.h"
#include "jedparse.h"
#include "plaparse.h"
@@ -259,6 +288,11 @@ struct _pin_output_config
};
+
+typedef std::vector<const pal_data*> pal_data_vector;
+
+
+
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
@@ -276,7 +310,6 @@ static void print_pal16l8_product_terms(const pal_data* pal, const jed_data* jed
static void print_pal16r4_product_terms(const pal_data* pal, const jed_data* jed);
static void print_pal16r6_product_terms(const pal_data* pal, const jed_data* jed);
static void print_pal16r8_product_terms(const pal_data* pal, const jed_data* jed);
-static void print_palce16v8_product_terms(const pal_data* pal, const jed_data* jed);
static void print_gal16v8_product_terms(const pal_data* pal, const jed_data* jed);
static void print_peel18cv8_product_terms(const pal_data* pal, const jed_data* jed);
static void print_ampal18p8_product_terms(const pal_data* pal, const jed_data* jed);
@@ -290,6 +323,10 @@ static void print_pal20ra10_product_terms(const pal_data* pal, const jed_data* j
static void print_pal20x4_product_terms(const pal_data* pal, const jed_data* jed);
static void print_pal20x8_product_terms(const pal_data* pal, const jed_data* jed);
static void print_pal20x10_product_terms(const pal_data* pal, const jed_data* jed);
+static void print_gal20v8_product_terms(const pal_data* pal, const jed_data* jed);
+static void print_palce22v10_pal22v10_product_terms(const pal_data* pal, const jed_data* jed);
+static void print_gal22v10_product_terms(const pal_data* pal, const jed_data* jed);
+static void print_atf22v10_power_down_mode_product_terms(const pal_data* pal, const jed_data* jed);
static void print_82s153_pls153_product_terms(const pal_data* pal, const jed_data* jed);
static void print_ck2605_product_terms(const pal_data* pal, const jed_data* jed);
#if defined(ricoh_pals)
@@ -339,7 +376,6 @@ static void config_pal16l8_pins(const pal_data* pal, const jed_data* jed);
static void config_pal16r4_pins(const pal_data* pal, const jed_data* jed);
static void config_pal16r6_pins(const pal_data* pal, const jed_data* jed);
static void config_pal16r8_pins(const pal_data* pal, const jed_data* jed);
-static void config_palce16v8_pins(const pal_data* pal, const jed_data* jed);
static void config_gal16v8_pins(const pal_data* pal, const jed_data* jed);
static void config_peel18cv8_pins(const pal_data* pal, const jed_data* jed);
static void config_ampal18p8_pins(const pal_data* pal, const jed_data* jed);
@@ -353,6 +389,10 @@ static void config_pal20ra10_pins(const pal_data* pal, const jed_data* jed);
static void config_pal20x4_pins(const pal_data* pal, const jed_data* jed);
static void config_pal20x8_pins(const pal_data* pal, const jed_data* jed);
static void config_pal20x10_pins(const pal_data* pal, const jed_data* jed);
+static void config_gal20v8_pins(const pal_data* pal, const jed_data* jed);
+static void config_palce22v10_pal22v10_pins(const pal_data* pal, const jed_data* jed);
+static void config_gal22v10_pins(const pal_data* pal, const jed_data* jed);
+static void config_atf22v10_power_down_mode_pins(const pal_data* pal, const jed_data* jed);
static void config_82s153_pls153_pins(const pal_data* pal, const jed_data* jed);
static void config_ck2605_pins(const pal_data* pal, const jed_data* jed);
#if defined(ricoh_pals)
@@ -393,6 +433,10 @@ static int is_gal16v8_product_term_enabled(const pal_data* pal, const jed_data*
+static int is_gal20v8_product_term_enabled(const pal_data* pal, const jed_data* jed, uint16_t fuserow);
+
+
+
static uint16_t get_peel18cv8_pin_fuse_state(const pal_data* pal, const jed_data* jed, uint16_t pin, uint16_t fuserow);
@@ -401,9 +445,6 @@ static uint16_t get_peel18cv8_pin_fuse_state(const pal_data* pal, const jed_data
GLOBAL VARIABLES
***************************************************************************/
-static uint8_t *srcbuf;
-static size_t srcbuflen;
-
static uint8_t *dstbuf;
static size_t dstbuflen;
@@ -513,16 +554,6 @@ static pin_fuse_rows pal16r8pinfuserows[] = {
{18, NO_OUTPUT_ENABLE_FUSE_ROW, 256, 480}, /* Registered Output */
{19, NO_OUTPUT_ENABLE_FUSE_ROW, 0, 224}}; /* Registered Output */
-static pin_fuse_rows palce16v8pinfuserows[] = {
- {12, 0, 0, 0},
- {13, 0, 0, 0},
- {14, 0, 0, 0},
- {15, 0, 0, 0},
- {16, 0, 0, 0},
- {17, 0, 0, 0},
- {18, 0, 0, 0},
- {19, 0, 0, 0}};
-
static pin_fuse_rows gal16v8pinfuserows[] = {
{12, 0, 0, 0},
{13, 0, 0, 0},
@@ -665,6 +696,52 @@ static pin_fuse_rows pal20x10pinfuserows[] = {
{22, NO_OUTPUT_ENABLE_FUSE_ROW, 160, 280}, /* Registered Output */
{23, NO_OUTPUT_ENABLE_FUSE_ROW, 0, 120}}; /* Registered Output */
+static pin_fuse_rows gal20v8pinfuserows[] = {
+ {15, 0, 0, 0},
+ {16, 0, 0, 0},
+ {17, 0, 0, 0},
+ {18, 0, 0, 0},
+ {19, 0, 0, 0},
+ {20, 0, 0, 0},
+ {21, 0, 0, 0},
+ {22, 0, 0, 0}};
+
+static pin_fuse_rows palce22v10_pal22v10pinfuserows[] = {
+ {14, 5368, 5412, 5720},
+ {15, 4884, 4928, 5324},
+ {16, 4312, 4356, 4840},
+ {17, 3652, 3696, 4268},
+ {18, 2904, 2948, 3608},
+ {19, 2156, 2200, 2860},
+ {20, 1496, 1540, 2112},
+ {21, 924, 968, 1452},
+ {22, 440, 484, 880},
+ {23, 44, 88, 396}};
+
+static pin_fuse_rows gal22v10pinfuserows[] = {
+ {14, 5368, 5412, 5720},
+ {15, 4884, 4928, 5324},
+ {16, 4312, 4356, 4840},
+ {17, 3652, 3696, 4268},
+ {18, 2904, 2948, 3608},
+ {19, 2156, 2200, 2860},
+ {20, 1496, 1540, 2112},
+ {21, 924, 968, 1452},
+ {22, 440, 484, 880},
+ {23, 44, 88, 396}};
+
+static pin_fuse_rows atf22v10powerdownmodepinfuserows[] = {
+ {14, 5368, 5412, 5720},
+ {15, 4884, 4928, 5324},
+ {16, 4312, 4356, 4840},
+ {17, 3652, 3696, 4268},
+ {18, 2904, 2948, 3608},
+ {19, 2156, 2200, 2860},
+ {20, 1496, 1540, 2112},
+ {21, 924, 968, 1452},
+ {22, 440, 484, 880},
+ {23, 44, 88, 396}};
+
static pin_fuse_rows _82s153_pls153pinfuserows[] = {
{9, 1472, 0, 0},
{11, 1508, 0, 0},
@@ -1161,24 +1238,6 @@ static pin_fuse_columns pal16r8pinfusecolumns[] = {
{18, 7, 6}, /* Registered Output */
{19, 3, 2}}; /* Registered Output */
-static pin_fuse_columns palce16v8pinfusecolumns[] = {
- {2, 1, 0},
- {3, 5, 4},
- {4, 9, 8},
- {5, 13, 12},
- {6, 17, 16},
- {7, 21, 20},
- {8, 25, 24},
- {9, 29, 28},
- {12, 31, 30},
- {13, 27, 26},
- {14, 23, 22},
- {15, 19, 18},
- {16, 15, 14},
- {17, 11, 10},
- {18, 7, 6},
- {19, 3, 2}};
-
static pin_fuse_columns gal16v8pinfusecolumns[] = {
{0, 0, 0},
{0, 0, 0},
@@ -1456,6 +1515,100 @@ static pin_fuse_columns pal20x10pinfusecolumns[] = {
{23, 3, 2}
};
+static pin_fuse_columns gal20v8pinfusecolumns[] = {
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0}};
+
+static pin_fuse_columns palce22v10_pal22v10pinfusecolumns[] = {
+ {1, 1, 0},
+ {2, 5, 4},
+ {3, 9, 8},
+ {4, 13, 12},
+ {5, 17, 16},
+ {6, 21, 20},
+ {7, 25, 24},
+ {8, 29, 28},
+ {9, 33, 32},
+ {10, 37, 36},
+ {11, 41, 40},
+ {13, 43, 42},
+ {14, 39, 38},
+ {15, 35, 34},
+ {16, 31, 30},
+ {17, 27, 26},
+ {18, 23, 22},
+ {19, 19, 18},
+ {20, 15, 14},
+ {21, 11, 10},
+ {22, 7, 6},
+ {23, 3, 2}};
+
+static pin_fuse_columns gal22v10pinfusecolumns[] = {
+ {1, 1, 0},
+ {2, 5, 4},
+ {3, 9, 8},
+ {4, 13, 12},
+ {5, 17, 16},
+ {6, 21, 20},
+ {7, 25, 24},
+ {8, 29, 28},
+ {9 , 33, 32},
+ {10, 37, 36},
+ {11, 41, 40},
+ {13, 43, 42},
+ {14, 39, 38},
+ {15, 35, 34},
+ {16, 31, 30},
+ {17, 27, 26},
+ {18, 23, 22},
+ {19, 19, 18},
+ {20, 15, 14},
+ {21, 11, 10},
+ {22, 7, 6},
+ {23, 3, 2}};
+
+static pin_fuse_columns atf22v10powerdownmodepinfusecolumns[] = {
+ {1, 1, 0},
+ {2, 5, 4},
+ {3, 9, 8},
+ {4, 13, 12},
+ {5, 17, 16},
+ {6, 21, 20},
+ {7, 25, 24},
+ {8, 29, 28},
+ {9 , 33, 32},
+ {10, 37, 36},
+ {11, 41, 40},
+ {13, 43, 42},
+ {14, 39, 38},
+ {15, 35, 34},
+ {16, 31, 30},
+ {17, 27, 26},
+ {18, 23, 22},
+ {19, 19, 18},
+ {20, 15, 14},
+ {21, 11, 10},
+ {22, 7, 6},
+ {23, 3, 2}};
+
static pin_fuse_columns _82s153_pls153pinfusecolumns[] = {
{1, 1, 0},
{2, 3, 2},
@@ -1976,443 +2129,510 @@ static pin_fuse_columns _82s100_pls100_pinfusecolumns[] = {
static pal_data paldata[] = {
{"PAL10L8", 320,
- pal10l8pinfuserows, ARRAY_LENGTH(pal10l8pinfuserows),
- pal10l8pinfusecolumns, ARRAY_LENGTH(pal10l8pinfusecolumns),
+ pal10l8pinfuserows, std::size(pal10l8pinfuserows),
+ pal10l8pinfusecolumns, std::size(pal10l8pinfusecolumns),
print_pal10l8_product_terms,
config_pal10l8_pins,
nullptr,
nullptr},
{"PAL10H8", 320,
- pal10h8pinfuserows, ARRAY_LENGTH(pal10h8pinfuserows),
- pal10h8pinfusecolumns, ARRAY_LENGTH(pal10h8pinfusecolumns),
+ pal10h8pinfuserows, std::size(pal10h8pinfuserows),
+ pal10h8pinfusecolumns, std::size(pal10h8pinfusecolumns),
print_pal10h8_product_terms,
config_pal10h8_pins,
nullptr,
nullptr},
{"PAL12H6", 384,
- pal12h6pinfuserows, ARRAY_LENGTH(pal12h6pinfuserows),
- pal12h6pinfusecolumns, ARRAY_LENGTH(pal12h6pinfusecolumns),
+ pal12h6pinfuserows, std::size(pal12h6pinfuserows),
+ pal12h6pinfusecolumns, std::size(pal12h6pinfusecolumns),
print_pal12h6_product_terms,
config_pal12h6_pins,
nullptr,
nullptr},
{"PAL14H4", 448,
- pal14h4pinfuserows, ARRAY_LENGTH(pal14h4pinfuserows),
- pal14h4pinfusecolumns, ARRAY_LENGTH(pal14h4pinfusecolumns),
+ pal14h4pinfuserows, std::size(pal14h4pinfuserows),
+ pal14h4pinfusecolumns, std::size(pal14h4pinfusecolumns),
print_pal14h4_product_terms,
config_pal14h4_pins,
nullptr,
nullptr},
{"PAL16H2", 512,
- pal16h2pinfuserows, ARRAY_LENGTH(pal16h2pinfuserows),
- pal16h2pinfusecolumns, ARRAY_LENGTH(pal16h2pinfusecolumns),
+ pal16h2pinfuserows, std::size(pal16h2pinfuserows),
+ pal16h2pinfusecolumns, std::size(pal16h2pinfusecolumns),
print_pal16h2_product_terms,
config_pal16h2_pins,
nullptr,
nullptr},
{"PAL16C1", 512,
- pal16c1pinfuserows, ARRAY_LENGTH(pal16c1pinfuserows),
- pal16c1pinfusecolumns, ARRAY_LENGTH(pal16c1pinfusecolumns),
+ pal16c1pinfuserows, std::size(pal16c1pinfuserows),
+ pal16c1pinfusecolumns, std::size(pal16c1pinfusecolumns),
print_pal16c1_product_terms,
config_pal16c1_pins,
nullptr,
nullptr},
{"PAL12L6", 384,
- pal12l6pinfuserows, ARRAY_LENGTH(pal12l6pinfuserows),
- pal12l6pinfusecolumns, ARRAY_LENGTH(pal12l6pinfusecolumns),
+ pal12l6pinfuserows, std::size(pal12l6pinfuserows),
+ pal12l6pinfusecolumns, std::size(pal12l6pinfusecolumns),
print_pal12l6_product_terms,
config_pal12l6_pins,
nullptr,
nullptr},
{"PAL14L4", 448,
- pal14l4pinfuserows, ARRAY_LENGTH(pal14l4pinfuserows),
- pal14l4pinfusecolumns, ARRAY_LENGTH(pal14l4pinfusecolumns),
+ pal14l4pinfuserows, std::size(pal14l4pinfuserows),
+ pal14l4pinfusecolumns, std::size(pal14l4pinfusecolumns),
print_pal14l4_product_terms,
config_pal14l4_pins,
nullptr,
nullptr},
{"PAL16L2", 512,
- pal16l2pinfuserows, ARRAY_LENGTH(pal16l2pinfuserows),
- pal16l2pinfusecolumns, ARRAY_LENGTH(pal16l2pinfusecolumns),
+ pal16l2pinfuserows, std::size(pal16l2pinfuserows),
+ pal16l2pinfusecolumns, std::size(pal16l2pinfusecolumns),
print_pal16l2_product_terms,
config_pal16l2_pins,
nullptr,
nullptr},
/*{"15S8", 0, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL},*/
{"PAL16L8", 2048,
- pal16l8pinfuserows, ARRAY_LENGTH(pal16l8pinfuserows),
- pal16l8pinfusecolumns, ARRAY_LENGTH(pal16l8pinfusecolumns),
+ pal16l8pinfuserows, std::size(pal16l8pinfuserows),
+ pal16l8pinfusecolumns, std::size(pal16l8pinfusecolumns),
print_pal16l8_product_terms,
config_pal16l8_pins,
nullptr,
nullptr},
{"PAL16R4", 2048,
- pal16r4pinfuserows, ARRAY_LENGTH(pal16r4pinfuserows),
- pal16r4pinfusecolumns, ARRAY_LENGTH(pal16r4pinfusecolumns),
+ pal16r4pinfuserows, std::size(pal16r4pinfuserows),
+ pal16r4pinfusecolumns, std::size(pal16r4pinfusecolumns),
print_pal16r4_product_terms,
config_pal16r4_pins,
nullptr,
nullptr},
{"PAL16R6", 2048,
- pal16r6pinfuserows, ARRAY_LENGTH(pal16r6pinfuserows),
- pal16r6pinfusecolumns, ARRAY_LENGTH(pal16r6pinfusecolumns),
+ pal16r6pinfuserows, std::size(pal16r6pinfuserows),
+ pal16r6pinfusecolumns, std::size(pal16r6pinfusecolumns),
print_pal16r6_product_terms,
config_pal16r6_pins,
nullptr,
nullptr},
{"PAL16R8", 2048,
- pal16r8pinfuserows, ARRAY_LENGTH(pal16r8pinfuserows),
- pal16r8pinfusecolumns, ARRAY_LENGTH(pal16r8pinfusecolumns),
+ pal16r8pinfuserows, std::size(pal16r8pinfuserows),
+ pal16r8pinfusecolumns, std::size(pal16r8pinfusecolumns),
print_pal16r8_product_terms,
config_pal16r8_pins,
nullptr,
nullptr},
/*{"PAL16RA8", 0, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL},
- {"PAL16V8R", 0, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL},*/
+ {"PAL16V8R", 0, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL},*/ // PAL16V8 same fusemap as GAL16V8?
{"PALCE16V8", 2194,
- palce16v8pinfuserows, ARRAY_LENGTH(palce16v8pinfuserows),
- palce16v8pinfusecolumns, ARRAY_LENGTH(palce16v8pinfusecolumns),
- print_palce16v8_product_terms,
- config_palce16v8_pins,
+ gal16v8pinfuserows, std::size(gal16v8pinfuserows),
+ gal16v8pinfusecolumns, std::size(gal16v8pinfusecolumns),
+ print_gal16v8_product_terms,
+ config_gal16v8_pins,
nullptr,
nullptr},
{"GAL16V8", 2194,
- gal16v8pinfuserows, ARRAY_LENGTH(gal16v8pinfuserows),
- gal16v8pinfusecolumns, ARRAY_LENGTH(gal16v8pinfusecolumns),
+ gal16v8pinfuserows, std::size(gal16v8pinfuserows),
+ gal16v8pinfusecolumns, std::size(gal16v8pinfusecolumns),
+ print_gal16v8_product_terms,
+ config_gal16v8_pins,
+ is_gal16v8_product_term_enabled,
+ nullptr},
+ {"ATF16V8", 2194,
+ gal16v8pinfuserows, std::size(gal16v8pinfuserows),
+ gal16v8pinfusecolumns, std::size(gal16v8pinfusecolumns),
print_gal16v8_product_terms,
config_gal16v8_pins,
is_gal16v8_product_term_enabled,
nullptr},
{"18CV8", 2696,
- peel18cv8pinfuserows, ARRAY_LENGTH(peel18cv8pinfuserows),
- peel18cv8pinfusecolumns, ARRAY_LENGTH(peel18cv8pinfusecolumns),
+ peel18cv8pinfuserows, std::size(peel18cv8pinfuserows),
+ peel18cv8pinfusecolumns, std::size(peel18cv8pinfusecolumns),
print_peel18cv8_product_terms,
config_peel18cv8_pins,
nullptr,
get_peel18cv8_pin_fuse_state},
{"AMPAL18P8", 2600,
- ampal18p8pinfuserows, ARRAY_LENGTH(ampal18p8pinfuserows),
- ampal18p8pinfusecolumns, ARRAY_LENGTH(ampal18p8pinfusecolumns),
+ ampal18p8pinfuserows, std::size(ampal18p8pinfuserows),
+ ampal18p8pinfusecolumns, std::size(ampal18p8pinfusecolumns),
print_ampal18p8_product_terms,
config_ampal18p8_pins,
nullptr,
nullptr},
{"GAL18V10", 3540,
- gal18v10pinfuserows, ARRAY_LENGTH(gal18v10pinfuserows),
- gal18v10pinfusecolumns, ARRAY_LENGTH(gal18v10pinfusecolumns),
+ gal18v10pinfuserows, std::size(gal18v10pinfuserows),
+ gal18v10pinfusecolumns, std::size(gal18v10pinfusecolumns),
print_gal18v10_product_terms,
config_gal18v10_pins,
nullptr,
nullptr},
{"PAL20L8", 2560,
- pal20l8pinfuserows, ARRAY_LENGTH(pal20l8pinfuserows),
- pal20l8pinfusecolumns, ARRAY_LENGTH(pal20l8pinfusecolumns),
+ pal20l8pinfuserows, std::size(pal20l8pinfuserows),
+ pal20l8pinfusecolumns, std::size(pal20l8pinfusecolumns),
print_pal20l8_product_terms,
config_pal20l8_pins,
nullptr,
nullptr},
{"PAL20L10", 1600,
- pal20l10pinfuserows, ARRAY_LENGTH(pal20l10pinfuserows),
- pal20l10pinfusecolumns, ARRAY_LENGTH(pal20l10pinfusecolumns),
+ pal20l10pinfuserows, std::size(pal20l10pinfuserows),
+ pal20l10pinfusecolumns, std::size(pal20l10pinfusecolumns),
print_pal20l10_product_terms,
config_pal20l10_pins,
nullptr,
nullptr},
{"PAL20R4", 2560,
- pal20r4pinfuserows, ARRAY_LENGTH(pal20r4pinfuserows),
- pal20r4pinfusecolumns, ARRAY_LENGTH(pal20r4pinfusecolumns),
+ pal20r4pinfuserows, std::size(pal20r4pinfuserows),
+ pal20r4pinfusecolumns, std::size(pal20r4pinfusecolumns),
print_pal20r4_product_terms,
config_pal20r4_pins,
nullptr,
nullptr},
{"PAL20R6", 2560,
- pal20r6pinfuserows, ARRAY_LENGTH(pal20r6pinfuserows),
- pal20r6pinfusecolumns, ARRAY_LENGTH(pal20r6pinfusecolumns),
+ pal20r6pinfuserows, std::size(pal20r6pinfuserows),
+ pal20r6pinfusecolumns, std::size(pal20r6pinfusecolumns),
print_pal20r6_product_terms,
config_pal20r6_pins,
nullptr,
nullptr},
{"PAL20R8", 2560,
- pal20r8pinfuserows, ARRAY_LENGTH(pal20r8pinfuserows),
- pal20r8pinfusecolumns, ARRAY_LENGTH(pal20r8pinfusecolumns),
+ pal20r8pinfuserows, std::size(pal20r8pinfuserows),
+ pal20r8pinfusecolumns, std::size(pal20r8pinfusecolumns),
print_pal20r8_product_terms,
config_pal20r8_pins,
nullptr,
nullptr},
{"PAL20RA10", 3210,
- pal20ra10pinfuserows, ARRAY_LENGTH(pal20ra10pinfuserows),
- pal20ra10pinfusecolumns, ARRAY_LENGTH(pal20ra10pinfusecolumns),
+ pal20ra10pinfuserows, std::size(pal20ra10pinfuserows),
+ pal20ra10pinfusecolumns, std::size(pal20ra10pinfusecolumns),
print_pal20ra10_product_terms,
config_pal20ra10_pins,
nullptr,
nullptr },
{"PAL20X4", 1600,
- pal20x4pinfuserows, ARRAY_LENGTH(pal20x4pinfuserows),
- pal20x4pinfusecolumns, ARRAY_LENGTH(pal20x4pinfusecolumns),
+ pal20x4pinfuserows, std::size(pal20x4pinfuserows),
+ pal20x4pinfusecolumns, std::size(pal20x4pinfusecolumns),
print_pal20x4_product_terms,
config_pal20x4_pins,
nullptr,
nullptr},
{"PAL20X8", 1600,
- pal20x8pinfuserows, ARRAY_LENGTH(pal20x8pinfuserows),
- pal20x8pinfusecolumns, ARRAY_LENGTH(pal20x8pinfusecolumns),
+ pal20x8pinfuserows, std::size(pal20x8pinfuserows),
+ pal20x8pinfusecolumns, std::size(pal20x8pinfusecolumns),
print_pal20x8_product_terms,
config_pal20x8_pins,
nullptr,
nullptr},
{"PAL20X10", 1600,
- pal20x10pinfuserows, ARRAY_LENGTH(pal20x10pinfuserows),
- pal20x10pinfusecolumns, ARRAY_LENGTH(pal20x10pinfusecolumns),
+ pal20x10pinfuserows, std::size(pal20x10pinfuserows),
+ pal20x10pinfusecolumns, std::size(pal20x10pinfusecolumns),
print_pal20x10_product_terms,
config_pal20x10_pins,
nullptr,
nullptr},
- /*{"PAL22V10", 0, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL},
- {"GAL20V8A", 0, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL},
- {"GAL22V10", 0, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL},*/
+ {"GAL20V8", 2706,
+ gal20v8pinfuserows, std::size(gal20v8pinfuserows),
+ gal20v8pinfusecolumns, std::size(gal20v8pinfusecolumns),
+ print_gal20v8_product_terms,
+ config_gal20v8_pins,
+ is_gal20v8_product_term_enabled,
+ nullptr},
+ {"PALCE20V8", 2706,
+ gal20v8pinfuserows, std::size(gal20v8pinfuserows),
+ gal20v8pinfusecolumns, std::size(gal20v8pinfusecolumns),
+ print_gal20v8_product_terms,
+ config_gal20v8_pins,
+ is_gal20v8_product_term_enabled,
+ nullptr},
+ {"ATF20V10", 2706,
+ gal20v8pinfuserows, std::size(gal20v8pinfuserows),
+ gal20v8pinfusecolumns, std::size(gal20v8pinfusecolumns),
+ print_gal20v8_product_terms,
+ config_gal20v8_pins,
+ is_gal20v8_product_term_enabled,
+ nullptr},
+ {"PAL22V10", 5828,
+ palce22v10_pal22v10pinfuserows, std::size(palce22v10_pal22v10pinfuserows),
+ palce22v10_pal22v10pinfusecolumns, std::size(palce22v10_pal22v10pinfusecolumns),
+ print_palce22v10_pal22v10_product_terms,
+ config_palce22v10_pal22v10_pins,
+ nullptr,
+ nullptr},
+ {"PALCE22V10", 5828,
+ palce22v10_pal22v10pinfuserows, std::size(palce22v10_pal22v10pinfuserows),
+ palce22v10_pal22v10pinfusecolumns, std::size(palce22v10_pal22v10pinfusecolumns),
+ print_palce22v10_pal22v10_product_terms,
+ config_palce22v10_pal22v10_pins,
+ nullptr,
+ nullptr},
+ {"ATF22V10", 5828,
+ palce22v10_pal22v10pinfuserows, std::size(palce22v10_pal22v10pinfuserows),
+ palce22v10_pal22v10pinfusecolumns, std::size(palce22v10_pal22v10pinfusecolumns),
+ print_palce22v10_pal22v10_product_terms,
+ config_palce22v10_pal22v10_pins,
+ nullptr,
+ nullptr},
+ {"GAL22V10", 5892,
+ gal22v10pinfuserows, std::size(gal22v10pinfuserows),
+ gal22v10pinfusecolumns, std::size(gal22v10pinfusecolumns),
+ print_gal22v10_product_terms,
+ config_gal22v10_pins,
+ nullptr,
+ nullptr},
+ {"ATF22V10", 5892,
+ gal22v10pinfuserows, std::size(gal22v10pinfuserows),
+ gal22v10pinfusecolumns, std::size(gal22v10pinfusecolumns),
+ print_gal22v10_product_terms,
+ config_gal22v10_pins,
+ nullptr,
+ nullptr},
+ {"ATF22V10", 5893,
+ atf22v10powerdownmodepinfuserows, std::size(atf22v10powerdownmodepinfuserows),
+ atf22v10powerdownmodepinfusecolumns, std::size(atf22v10powerdownmodepinfusecolumns),
+ print_atf22v10_power_down_mode_product_terms,
+ config_atf22v10_power_down_mode_pins,
+ nullptr,
+ nullptr},
{"82S153", 1842,
- _82s153_pls153pinfuserows, ARRAY_LENGTH(_82s153_pls153pinfuserows),
- _82s153_pls153pinfusecolumns, ARRAY_LENGTH(_82s153_pls153pinfusecolumns),
+ _82s153_pls153pinfuserows, std::size(_82s153_pls153pinfuserows),
+ _82s153_pls153pinfusecolumns, std::size(_82s153_pls153pinfusecolumns),
print_82s153_pls153_product_terms,
config_82s153_pls153_pins,
nullptr,
nullptr},
{"PLS153", 1842,
- _82s153_pls153pinfuserows, ARRAY_LENGTH(_82s153_pls153pinfuserows),
- _82s153_pls153pinfusecolumns, ARRAY_LENGTH(_82s153_pls153pinfusecolumns),
+ _82s153_pls153pinfuserows, std::size(_82s153_pls153pinfuserows),
+ _82s153_pls153pinfusecolumns, std::size(_82s153_pls153pinfusecolumns),
print_82s153_pls153_product_terms,
config_82s153_pls153_pins,
nullptr,
nullptr},
{"CK2605", 1106,
- ck2605pinfuserows, ARRAY_LENGTH(ck2605pinfuserows),
- ck2605pinfusecolumns, ARRAY_LENGTH(ck2605pinfusecolumns),
+ ck2605pinfuserows, std::size(ck2605pinfuserows),
+ ck2605pinfusecolumns, std::size(ck2605pinfusecolumns),
print_ck2605_product_terms,
config_ck2605_pins,
nullptr,
nullptr},
#if defined(ricoh_pals)
{"EPL10P8", 664,
- epl10p8pinfuserows, ARRAY_LENGTH(epl10p8pinfuserows),
- epl10p8pinfusecolumns, ARRAY_LENGTH(epl10p8pinfusecolumns),
+ epl10p8pinfuserows, std::size(epl10p8pinfuserows),
+ epl10p8pinfusecolumns, std::size(epl10p8pinfusecolumns),
print_epl10p8_product_terms,
config_epl10p8_pins,
nullptr,
nullptr},
{"EPL12P6", 786,
- epl12p6pinfuserows, ARRAY_LENGTH(epl12p6pinfuserows),
- epl12p6pinfusecolumns, ARRAY_LENGTH(epl12p6pinfusecolumns),
+ epl12p6pinfuserows, std::size(epl12p6pinfuserows),
+ epl12p6pinfusecolumns, std::size(epl12p6pinfusecolumns),
print_epl12p6_product_terms,
config_epl12p6_pins,
nullptr,
nullptr},
{"EPL14P4", 908,
- epl14p4pinfuserows, ARRAY_LENGTH(epl14p4pinfuserows),
- epl14p4pinfusecolumns, ARRAY_LENGTH(epl14p4pinfusecolumns),
+ epl14p4pinfuserows, std::size(epl14p4pinfuserows),
+ epl14p4pinfusecolumns, std::size(epl14p4pinfusecolumns),
print_epl14p4_product_terms,
config_epl14p4_pins,
nullptr,
nullptr},
{"EPL16P2", 1030,
- epl16p2pinfuserows, ARRAY_LENGTH(epl16p2pinfuserows),
- epl16p2pinfusecolumns, ARRAY_LENGTH(epl16p2pinfusecolumns),
+ epl16p2pinfuserows, std::size(epl16p2pinfuserows),
+ epl16p2pinfusecolumns, std::size(epl16p2pinfusecolumns),
print_epl16p2_product_terms,
config_epl16p2_pins,
nullptr,
nullptr},
{"EPL16P8", 2072,
- epl16p8pinfuserows, ARRAY_LENGTH(epl16p8pinfuserows),
- epl16p8pinfusecolumns, ARRAY_LENGTH(epl16p8pinfusecolumns),
+ epl16p8pinfuserows, std::size(epl16p8pinfuserows),
+ epl16p8pinfusecolumns, std::size(epl16p8pinfusecolumns),
print_epl16p8_product_terms,
config_epl16p8_pins,
nullptr,
nullptr},
{"EPL16RP8", 2072,
- epl16rp8pinfuserows, ARRAY_LENGTH(epl16rp8pinfuserows),
- epl16rp8pinfusecolumns, ARRAY_LENGTH(epl16rp8pinfusecolumns),
+ epl16rp8pinfuserows, std::size(epl16rp8pinfuserows),
+ epl16rp8pinfusecolumns, std::size(epl16rp8pinfusecolumns),
print_epl16rp8_product_terms,
config_epl16rp8_pins,
nullptr,
nullptr},
{"EPL16RP6", 2072,
- epl16rp6pinfuserows, ARRAY_LENGTH(epl16rp6pinfuserows),
- epl16rp6pinfusecolumns, ARRAY_LENGTH(epl16rp6pinfusecolumns),
+ epl16rp6pinfuserows, std::size(epl16rp6pinfuserows),
+ epl16rp6pinfusecolumns, std::size(epl16rp6pinfusecolumns),
print_epl16rp6_product_terms,
config_epl16rp6_pins,
nullptr,
nullptr},
{"EPL16RP4", 2072,
- epl16rp4pinfuserows, ARRAY_LENGTH(epl16rp4pinfuserows),
- epl16rp4pinfusecolumns, ARRAY_LENGTH(epl16rp4pinfusecolumns),
+ epl16rp4pinfuserows, std::size(epl16rp4pinfuserows),
+ epl16rp4pinfusecolumns, std::size(epl16rp4pinfusecolumns),
print_epl16rp4_product_terms,
config_epl16rp4_pins,
nullptr,
nullptr},
#endif
{"PAL10P8", 328,
- pal10p8pinfuserows, ARRAY_LENGTH(pal10p8pinfuserows),
- pal10p8pinfusecolumns, ARRAY_LENGTH(pal10p8pinfusecolumns),
+ pal10p8pinfuserows, std::size(pal10p8pinfuserows),
+ pal10p8pinfusecolumns, std::size(pal10p8pinfusecolumns),
print_pal10p8_product_terms,
config_pal10p8_pins,
nullptr,
nullptr},
{"PAL12P6", 390,
- pal12p6pinfuserows, ARRAY_LENGTH(pal12p6pinfuserows),
- pal12p6pinfusecolumns, ARRAY_LENGTH(pal12p6pinfusecolumns),
+ pal12p6pinfuserows, std::size(pal12p6pinfuserows),
+ pal12p6pinfusecolumns, std::size(pal12p6pinfusecolumns),
print_pal12p6_product_terms,
config_pal12p6_pins,
nullptr,
nullptr},
{"PAL14P4", 452,
- pal14p4pinfuserows, ARRAY_LENGTH(pal14p4pinfuserows),
- pal14p4pinfusecolumns, ARRAY_LENGTH(pal14p4pinfusecolumns),
+ pal14p4pinfuserows, std::size(pal14p4pinfuserows),
+ pal14p4pinfusecolumns, std::size(pal14p4pinfusecolumns),
print_pal14p4_product_terms,
config_pal14p4_pins,
nullptr,
nullptr},
{"PAL16P2", 514,
- pal16p2pinfuserows, ARRAY_LENGTH(pal16p2pinfuserows),
- pal16p2pinfusecolumns, ARRAY_LENGTH(pal16p2pinfusecolumns),
+ pal16p2pinfuserows, std::size(pal16p2pinfuserows),
+ pal16p2pinfusecolumns, std::size(pal16p2pinfusecolumns),
print_pal16p2_product_terms,
config_pal16p2_pins,
nullptr,
nullptr},
{"PAL16P8", 2056,
- pal16p8pinfuserows, ARRAY_LENGTH(pal16p8pinfuserows),
- pal16p8pinfusecolumns, ARRAY_LENGTH(pal16p8pinfusecolumns),
+ pal16p8pinfuserows, std::size(pal16p8pinfuserows),
+ pal16p8pinfusecolumns, std::size(pal16p8pinfusecolumns),
print_pal16p8_product_terms,
config_pal16p8_pins,
nullptr,
nullptr},
{"PAL16RP4", 2056,
- pal16rp4pinfuserows, ARRAY_LENGTH(pal16rp4pinfuserows),
- pal16rp4pinfusecolumns, ARRAY_LENGTH(pal16rp4pinfusecolumns),
+ pal16rp4pinfuserows, std::size(pal16rp4pinfuserows),
+ pal16rp4pinfusecolumns, std::size(pal16rp4pinfusecolumns),
print_pal16rp4_product_terms,
config_pal16rp4_pins,
nullptr,
nullptr},
{"PAL16RP6", 2056,
- pal16rp6pinfuserows, ARRAY_LENGTH(pal16rp6pinfuserows),
- pal16rp6pinfusecolumns, ARRAY_LENGTH(pal16rp6pinfusecolumns),
+ pal16rp6pinfuserows, std::size(pal16rp6pinfuserows),
+ pal16rp6pinfusecolumns, std::size(pal16rp6pinfusecolumns),
print_pal16rp6_product_terms,
config_pal16rp6_pins,
nullptr,
nullptr},
{"PAL16RP8", 2056,
- pal16rp8pinfuserows, ARRAY_LENGTH(pal16rp8pinfuserows),
- pal16rp8pinfusecolumns, ARRAY_LENGTH(pal16rp8pinfusecolumns),
+ pal16rp8pinfuserows, std::size(pal16rp8pinfuserows),
+ pal16rp8pinfusecolumns, std::size(pal16rp8pinfusecolumns),
print_pal16rp8_product_terms,
config_pal16rp8_pins,
nullptr,
nullptr},
{"PAL6L16", 192,
- pal6l16pinfuserows, ARRAY_LENGTH(pal6l16pinfuserows),
- pal6l16pinfusecolumns, ARRAY_LENGTH(pal6l16pinfusecolumns),
+ pal6l16pinfuserows, std::size(pal6l16pinfuserows),
+ pal6l16pinfusecolumns, std::size(pal6l16pinfusecolumns),
print_pal6l16_product_terms,
config_pal6l16_pins,
nullptr,
nullptr},
{"PAL8L14", 224,
- pal8l14pinfuserows, ARRAY_LENGTH(pal8l14pinfuserows),
- pal8l14pinfusecolumns, ARRAY_LENGTH(pal8l14pinfusecolumns),
+ pal8l14pinfuserows, std::size(pal8l14pinfuserows),
+ pal8l14pinfusecolumns, std::size(pal8l14pinfusecolumns),
print_pal8l14_product_terms,
config_pal8l14_pins,
nullptr,
nullptr},
{"PAL12H10", 480,
- pal12h10pinfuserows, ARRAY_LENGTH(pal12h10pinfuserows),
- pal12h10pinfusecolumns, ARRAY_LENGTH(pal12h10pinfusecolumns),
+ pal12h10pinfuserows, std::size(pal12h10pinfuserows),
+ pal12h10pinfusecolumns, std::size(pal12h10pinfusecolumns),
print_pal12h10_product_terms,
config_pal12h10_pins,
nullptr,
nullptr},
{"PAL12L10", 480,
- pal12l10pinfuserows, ARRAY_LENGTH(pal12l10pinfuserows),
- pal12l10pinfusecolumns, ARRAY_LENGTH(pal12l10pinfusecolumns),
+ pal12l10pinfuserows, std::size(pal12l10pinfuserows),
+ pal12l10pinfusecolumns, std::size(pal12l10pinfusecolumns),
print_pal12l10_product_terms,
config_pal12l10_pins,
nullptr,
nullptr},
{"PAL14H8", 560,
- pal14h8pinfuserows, ARRAY_LENGTH(pal14h8pinfuserows),
- pal14h8pinfusecolumns, ARRAY_LENGTH(pal14h8pinfusecolumns),
+ pal14h8pinfuserows, std::size(pal14h8pinfuserows),
+ pal14h8pinfusecolumns, std::size(pal14h8pinfusecolumns),
print_pal14h8_product_terms,
config_pal14h8_pins,
nullptr,
nullptr},
{"PAL14L8", 560,
- pal14l8pinfuserows, ARRAY_LENGTH(pal14l8pinfuserows),
- pal14l8pinfusecolumns, ARRAY_LENGTH(pal14l8pinfusecolumns),
+ pal14l8pinfuserows, std::size(pal14l8pinfuserows),
+ pal14l8pinfusecolumns, std::size(pal14l8pinfusecolumns),
print_pal14l8_product_terms,
config_pal14l8_pins,
nullptr,
nullptr},
{"PAL16H6", 640,
- pal16h6pinfuserows, ARRAY_LENGTH(pal16h6pinfuserows),
- pal16h6pinfusecolumns, ARRAY_LENGTH(pal16h6pinfusecolumns),
+ pal16h6pinfuserows, std::size(pal16h6pinfuserows),
+ pal16h6pinfusecolumns, std::size(pal16h6pinfusecolumns),
print_pal16h6_product_terms,
config_pal16h6_pins,
nullptr,
nullptr},
{"PAL16L6", 640,
- pal16l6pinfuserows, ARRAY_LENGTH(pal16l6pinfuserows),
- pal16l6pinfusecolumns, ARRAY_LENGTH(pal16l6pinfusecolumns),
+ pal16l6pinfuserows, std::size(pal16l6pinfuserows),
+ pal16l6pinfusecolumns, std::size(pal16l6pinfusecolumns),
print_pal16l6_product_terms,
config_pal16l6_pins,
nullptr,
nullptr},
{"PAL18H4", 720,
- pal18h4pinfuserows, ARRAY_LENGTH(pal18h4pinfuserows),
- pal18h4pinfusecolumns, ARRAY_LENGTH(pal18h4pinfusecolumns),
+ pal18h4pinfuserows, std::size(pal18h4pinfuserows),
+ pal18h4pinfusecolumns, std::size(pal18h4pinfusecolumns),
print_pal18h4_product_terms,
config_pal18h4_pins,
nullptr,
nullptr},
{"PAL18L4", 720,
- pal18l4pinfuserows, ARRAY_LENGTH(pal18l4pinfuserows),
- pal18l4pinfusecolumns, ARRAY_LENGTH(pal18l4pinfusecolumns),
+ pal18l4pinfuserows, std::size(pal18l4pinfuserows),
+ pal18l4pinfusecolumns, std::size(pal18l4pinfusecolumns),
print_pal18l4_product_terms,
config_pal18l4_pins,
nullptr,
nullptr},
{"PAL20C1", 640,
- pal20c1pinfuserows, ARRAY_LENGTH(pal20c1pinfuserows),
- pal20c1pinfusecolumns, ARRAY_LENGTH(pal20c1pinfusecolumns),
+ pal20c1pinfuserows, std::size(pal20c1pinfuserows),
+ pal20c1pinfusecolumns, std::size(pal20c1pinfusecolumns),
print_pal20c1_product_terms,
config_pal20c1_pins,
nullptr,
nullptr},
{"PAL20L2", 640,
- pal20l2pinfuserows, ARRAY_LENGTH(pal20l2pinfuserows),
- pal20l2pinfusecolumns, ARRAY_LENGTH(pal20l2pinfusecolumns),
+ pal20l2pinfuserows, std::size(pal20l2pinfuserows),
+ pal20l2pinfusecolumns, std::size(pal20l2pinfusecolumns),
print_pal20l2_product_terms,
config_pal20l2_pins,
nullptr,
nullptr},
{"82S100", 1928,
- _82s100_pls100_pinfuserows, ARRAY_LENGTH(_82s100_pls100_pinfuserows),
- _82s100_pls100_pinfusecolumns, ARRAY_LENGTH(_82s100_pls100_pinfusecolumns),
+ _82s100_pls100_pinfuserows, std::size(_82s100_pls100_pinfuserows),
+ _82s100_pls100_pinfusecolumns, std::size(_82s100_pls100_pinfusecolumns),
print_82s100_pls100_product_terms,
config_82s100_pls100_pins,
nullptr,
nullptr},
{"PLS100", 1928,
- _82s100_pls100_pinfuserows, ARRAY_LENGTH(_82s100_pls100_pinfuserows),
- _82s100_pls100_pinfusecolumns, ARRAY_LENGTH(_82s100_pls100_pinfusecolumns),
+ _82s100_pls100_pinfuserows, std::size(_82s100_pls100_pinfuserows),
+ _82s100_pls100_pinfusecolumns, std::size(_82s100_pls100_pinfusecolumns),
print_82s100_pls100_product_terms,
config_82s100_pls100_pins,
nullptr,
nullptr},
{"82S101", 1928,
- _82s100_pls100_pinfuserows, ARRAY_LENGTH(_82s100_pls100_pinfuserows),
- _82s100_pls100_pinfusecolumns, ARRAY_LENGTH(_82s100_pls100_pinfusecolumns),
+ _82s100_pls100_pinfuserows, std::size(_82s100_pls100_pinfuserows),
+ _82s100_pls100_pinfusecolumns, std::size(_82s100_pls100_pinfusecolumns),
print_82s100_pls100_product_terms,
config_82s100_pls100_pins,
nullptr,
nullptr},
{"PLS101", 1928,
- _82s100_pls100_pinfuserows, ARRAY_LENGTH(_82s100_pls100_pinfuserows),
- _82s100_pls100_pinfusecolumns, ARRAY_LENGTH(_82s100_pls100_pinfusecolumns),
+ _82s100_pls100_pinfuserows, std::size(_82s100_pls100_pinfuserows),
+ _82s100_pls100_pinfusecolumns, std::size(_82s100_pls100_pinfusecolumns),
print_82s100_pls100_product_terms,
config_82s100_pls100_pins,
nullptr,
@@ -2467,19 +2687,17 @@ static int is_pla_file(const char *file)
with a pal name
-------------------------------------------------*/
-static const pal_data* find_pal_data(const char *name)
+static void find_pal_data(const char *name, pal_data_vector& pal_data_vector)
{
int index;
- for (index = 0; index < ARRAY_LENGTH(paldata); ++index)
+ for (index = 0; index < std::size(paldata); ++index)
{
if (!core_stricmp(name, paldata[index].name))
{
- return &paldata[index];
+ pal_data_vector.push_back(&paldata[index]);
}
}
-
- return nullptr;
}
@@ -2781,7 +2999,7 @@ static void generate_product_terms(const pal_data* pal, const jed_data* jed, uin
if (!is_output_pin(pin))
{
- sprintf(tmpbuffer, LOW_SYMBOL INPUT_SYMBOL "%d", pin);
+ snprintf(tmpbuffer, 20, LOW_SYMBOL INPUT_SYMBOL "%d", pin);
strcat(buffer, tmpbuffer);
}
else
@@ -2792,11 +3010,11 @@ static void generate_product_terms(const pal_data* pal, const jed_data* jed, uin
{
if (flags & OUTPUT_COMBINATORIAL)
{
- sprintf(tmpbuffer, LOW_SYMBOL OUTPUT_SYMBOL "%d", pin);
+ snprintf(tmpbuffer, 20, LOW_SYMBOL OUTPUT_SYMBOL "%d", pin);
}
else if (flags & OUTPUT_REGISTERED)
{
- sprintf(tmpbuffer, LOW_SYMBOL REGISTERED_FEEDBACK_OUTPUT_SYMBOL "%d", pin);
+ snprintf(tmpbuffer, 20, LOW_SYMBOL REGISTERED_FEEDBACK_OUTPUT_SYMBOL "%d", pin);
}
else
{
@@ -2807,11 +3025,11 @@ static void generate_product_terms(const pal_data* pal, const jed_data* jed, uin
}
else if (flags & OUTPUT_FEEDBACK_COMBINATORIAL)
{
- sprintf(tmpbuffer, LOW_SYMBOL OUTPUT_FEEDBACK_SYMBOL "%d", pin);
+ snprintf(tmpbuffer, 20, LOW_SYMBOL OUTPUT_FEEDBACK_SYMBOL "%d", pin);
}
else if (flags & OUTPUT_FEEDBACK_REGISTERED)
{
- sprintf(tmpbuffer, LOW_SYMBOL REGISTERED_FEEDBACK_SYMBOL "%d", pin);
+ snprintf(tmpbuffer, 20, LOW_SYMBOL REGISTERED_FEEDBACK_SYMBOL "%d", pin);
}
else
{
@@ -2835,7 +3053,7 @@ static void generate_product_terms(const pal_data* pal, const jed_data* jed, uin
if (!is_output_pin(pin))
{
- sprintf(tmpbuffer, INPUT_SYMBOL "%d", pin);
+ snprintf(tmpbuffer, 20, INPUT_SYMBOL "%d", pin);
strcat(buffer, tmpbuffer);
}
else
@@ -2846,11 +3064,11 @@ static void generate_product_terms(const pal_data* pal, const jed_data* jed, uin
{
if (flags & OUTPUT_COMBINATORIAL)
{
- sprintf(tmpbuffer, OUTPUT_SYMBOL "%d", pin);
+ snprintf(tmpbuffer, 20, OUTPUT_SYMBOL "%d", pin);
}
else if (flags & OUTPUT_REGISTERED)
{
- sprintf(tmpbuffer, REGISTERED_FEEDBACK_OUTPUT_SYMBOL "%d", pin);
+ snprintf(tmpbuffer, 20, REGISTERED_FEEDBACK_OUTPUT_SYMBOL "%d", pin);
}
else
{
@@ -2861,11 +3079,11 @@ static void generate_product_terms(const pal_data* pal, const jed_data* jed, uin
}
else if (flags & OUTPUT_FEEDBACK_COMBINATORIAL)
{
- sprintf(tmpbuffer, OUTPUT_FEEDBACK_SYMBOL "%d", pin);
+ snprintf(tmpbuffer, 20, OUTPUT_FEEDBACK_SYMBOL "%d", pin);
}
else if (flags & OUTPUT_FEEDBACK_REGISTERED)
{
- sprintf(tmpbuffer, REGISTERED_FEEDBACK_SYMBOL "%d", pin);
+ snprintf(tmpbuffer, 20, REGISTERED_FEEDBACK_SYMBOL "%d", pin);
}
else
{
@@ -3014,11 +3232,11 @@ static void print_product_terms(const pal_data* pal, const jed_data* jed)
if (flags & OUTPUT_COMBINATORIAL)
{
- sprintf(buffer, OUTPUT_SYMBOL "%d " COMBINATORIAL_ASSIGNMENT " ", outputpins[index].pin);
+ snprintf(buffer, 200, OUTPUT_SYMBOL "%d " COMBINATORIAL_ASSIGNMENT " ", outputpins[index].pin);
}
else if (flags & OUTPUT_REGISTERED)
{
- sprintf(buffer, REGISTERED_FEEDBACK_SYMBOL "%d " REGISTERED_ASSIGNMENT " ", outputpins[index].pin);
+ snprintf(buffer, 200, REGISTERED_FEEDBACK_SYMBOL "%d " REGISTERED_ASSIGNMENT " ", outputpins[index].pin);
}
else
{
@@ -3113,74 +3331,6 @@ static void print_product_terms(const pal_data* pal, const jed_data* jed)
/*-------------------------------------------------
- config_palce16v8_pin_as_7_product_terms_and_oe_term - configures
- the fuse rows of a PALCE16V8 pin with seven
- product terms and one output enable product term.
--------------------------------------------------*/
-
-static void config_palce16v8_pin_as_7_product_terms_and_oe_term(uint16_t pin)
-{
- static pin_fuse_rows pinfuserows[] = {
- {12, 1792, 1824, 2016},
- {13, 1536, 1568, 1760},
- {14, 1280, 1312, 1504},
- {15, 1024, 1056, 1248},
- {16, 768, 800, 992},
- {17, 512, 544, 736},
- {18, 256, 288, 480},
- {19, 0, 32, 224}};
- uint16_t index;
-
- for (index = 0; index < ARRAY_LENGTH(pinfuserows); ++index)
- {
- if (pinfuserows[index].pin == pin)
- {
- palce16v8pinfuserows[index].fuserowoutputenable = pinfuserows[index].fuserowoutputenable;
- palce16v8pinfuserows[index].fuserowtermstart = pinfuserows[index].fuserowtermstart;
- palce16v8pinfuserows[index].fuserowtermend = pinfuserows[index].fuserowtermend;
-
- break;
- }
- }
-}
-
-
-
-/*-------------------------------------------------
- config_palce16v8_pin_as_8_product_terms - configures
- the fuse rows of a PALCE16V8 pin with eight
- product terms and no output enable product term.
--------------------------------------------------*/
-
-static void config_palce16v8_pin_as_8_product_terms(uint16_t pin)
-{
- static pin_fuse_rows pinfuserows[] = {
- {12, NO_OUTPUT_ENABLE_FUSE_ROW, 1792, 2016},
- {13, NO_OUTPUT_ENABLE_FUSE_ROW, 1536, 1760},
- {14, NO_OUTPUT_ENABLE_FUSE_ROW, 1280, 1504},
- {15, NO_OUTPUT_ENABLE_FUSE_ROW, 1024, 1248},
- {16, NO_OUTPUT_ENABLE_FUSE_ROW, 768, 992},
- {17, NO_OUTPUT_ENABLE_FUSE_ROW, 512, 736},
- {18, NO_OUTPUT_ENABLE_FUSE_ROW, 256, 480},
- {19, NO_OUTPUT_ENABLE_FUSE_ROW, 0, 224}};
- uint16_t index;
-
- for (index = 0; index < ARRAY_LENGTH(pinfuserows); ++index)
- {
- if (pinfuserows[index].pin == pin)
- {
- palce16v8pinfuserows[index].fuserowoutputenable = pinfuserows[index].fuserowoutputenable;
- palce16v8pinfuserows[index].fuserowtermstart = pinfuserows[index].fuserowtermstart;
- palce16v8pinfuserows[index].fuserowtermend = pinfuserows[index].fuserowtermend;
-
- break;
- }
- }
-}
-
-
-
-/*-------------------------------------------------
print_pal20xxx_product_terms - prints the product
terms for a PAL20X4, PAL20X8 and PAL20X10
-------------------------------------------------*/
@@ -3207,7 +3357,7 @@ static void print_pal20xxx_product_terms(const pal_data* pal, const jed_data* je
if (flags & OUTPUT_COMBINATORIAL)
{
- sprintf(buffer, LOW_SYMBOL OUTPUT_SYMBOL "%d " COMBINATORIAL_ASSIGNMENT " ", outputpins[index].pin);
+ snprintf(buffer, 200, LOW_SYMBOL OUTPUT_SYMBOL "%d " COMBINATORIAL_ASSIGNMENT " ", outputpins[index].pin);
printf("%s", buffer);
@@ -3262,7 +3412,7 @@ static void print_pal20xxx_product_terms(const pal_data* pal, const jed_data* je
}
else if (flags & OUTPUT_REGISTERED)
{
- sprintf(buffer, LOW_SYMBOL REGISTERED_FEEDBACK_SYMBOL "%d " REGISTERED_ASSIGNMENT " ", outputpins[index].pin);
+ snprintf(buffer, 200, LOW_SYMBOL REGISTERED_FEEDBACK_SYMBOL "%d " REGISTERED_ASSIGNMENT " ", outputpins[index].pin);
printf("%s", buffer);
@@ -3495,18 +3645,6 @@ static void print_pal16r8_product_terms(const pal_data* pal, const jed_data* jed
/*-------------------------------------------------
- print_palce16v8_product_terms - prints the product
- terms for a PALCE16V8
--------------------------------------------------*/
-
-static void print_palce16v8_product_terms(const pal_data* pal, const jed_data* jed)
-{
- print_product_terms(pal, jed);
-}
-
-
-
-/*-------------------------------------------------
print_gal16v8_product_terms - prints the product
terms for a GAL16V8
-------------------------------------------------*/
@@ -3576,13 +3714,13 @@ static void print_gal18v10_product_terms(const pal_data* pal, const jed_data* je
print_product_terms(pal, jed);
- /* Synchronous Reset */
+ /* Synchronous Preset */
generate_product_terms(pal, jed, 3420, buffer);
if (strlen(buffer))
{
- printf("Synchronous Reset:\n\n");
+ printf("Synchronous Preset:\n\n");
printf("%s\n", buffer);
printf("\n");
}
@@ -3710,6 +3848,129 @@ static void print_pal20x10_product_terms(const pal_data* pal, const jed_data* je
/*-------------------------------------------------
+ print_gal20v8_product_terms - prints the product
+ terms for a GAL20V8
+-------------------------------------------------*/
+
+static void print_gal20v8_product_terms(const pal_data* pal, const jed_data* jed)
+{
+ print_product_terms(pal, jed);
+}
+
+
+
+/*-------------------------------------------------
+ print_palce22v10_pal22v10_product_terms - prints the product
+ terms for a PALCE22V10 and PAL22V10
+-------------------------------------------------*/
+
+static void print_palce22v10_pal22v10_product_terms(const pal_data* pal, const jed_data* jed)
+{
+ char buffer[200];
+
+ print_product_terms(pal, jed);
+
+ /* Synchronous Preset */
+
+ generate_product_terms(pal, jed, 5764, buffer);
+
+ if (strlen(buffer))
+ {
+ printf("Synchronous Preset:\n\n");
+ printf("%s\n", buffer);
+ printf("\n");
+ }
+
+ /* Asynchronous Reset */
+
+ generate_product_terms(pal, jed, 0, buffer);
+
+ if (strlen(buffer))
+ {
+ printf("Asynchronous Reset:\n\n");
+ printf("%s\n", buffer);
+ printf("\n");
+ }
+}
+
+
+
+/*-------------------------------------------------
+ print_gal22v10_product_terms - prints the product
+ terms for a GAL22V10
+-------------------------------------------------*/
+
+static void print_gal22v10_product_terms(const pal_data* pal, const jed_data* jed)
+{
+ char buffer[200];
+
+ print_product_terms(pal, jed);
+
+ /* Synchronous Preset */
+
+ generate_product_terms(pal, jed, 5764, buffer);
+
+ if (strlen(buffer))
+ {
+ printf("Synchronous Preset:\n\n");
+ printf("%s\n", buffer);
+ printf("\n");
+ }
+
+ /* Asynchronous Reset */
+
+ generate_product_terms(pal, jed, 0, buffer);
+
+ if (strlen(buffer))
+ {
+ printf("Asynchronous Reset:\n\n");
+ printf("%s\n", buffer);
+ printf("\n");
+ }
+}
+
+/*-------------------------------------------------
+ print_atf22v10_power_down_mode_product_terms - prints the product
+ terms for a ATF22V10 configured in power-down mode
+-------------------------------------------------*/
+
+static void print_atf22v10_power_down_mode_product_terms(const pal_data* pal, const jed_data* jed)
+{
+ char buffer[200];
+
+ print_product_terms(pal, jed);
+
+ /* Synchronous Preset */
+
+ generate_product_terms(pal, jed, 5764, buffer);
+
+ if (strlen(buffer))
+ {
+ printf("Synchronous Preset:\n\n");
+ printf("%s\n", buffer);
+ printf("\n");
+ }
+
+ /* Asynchronous Reset */
+
+ generate_product_terms(pal, jed, 0, buffer);
+
+ if (strlen(buffer))
+ {
+ printf("Asynchronous Reset:\n\n");
+ printf("%s\n", buffer);
+ printf("\n");
+ }
+
+ /* Pin 4 (DIP/SOIC package) and Pin 5 (PLCC package) controls power down mode */
+
+ printf("Pin 4 (DIP/SOIC package) and Pin 5 (PLCC package) Controls Power Down Mode\n\n");
+ printf("\n");
+}
+
+
+
+/*-------------------------------------------------
print_82s153_pls153_product_terms - prints the product
terms for a 82S153/PLS153
-------------------------------------------------*/
@@ -3741,7 +4002,7 @@ static void print_82s153_pls153_product_terms(const pal_data* pal, const jed_dat
indent += strlen(LOW_SYMBOL);
}
- sprintf(buffer, OUTPUT_SYMBOL "%d " COMBINATORIAL_ASSIGNMENT " ", outputpins[index].pin);
+ snprintf(buffer, 200, OUTPUT_SYMBOL "%d " COMBINATORIAL_ASSIGNMENT " ", outputpins[index].pin);
printf("%s", buffer);
@@ -3844,7 +4105,7 @@ static void print_ck2605_product_terms(const pal_data* pal, const jed_data* jed)
indent += strlen(LOW_SYMBOL);
}
- sprintf(buffer, OUTPUT_SYMBOL "%d " COMBINATORIAL_ASSIGNMENT " ", outputpins[index].pin);
+ snprintf(buffer, 200, OUTPUT_SYMBOL "%d " COMBINATORIAL_ASSIGNMENT " ", outputpins[index].pin);
printf("%s", buffer);
@@ -3954,7 +4215,7 @@ static void print_epl10p8_product_terms(const pal_data* pal, const jed_data* jed
printf("Equations:\n\n");
- for (index = 0; index < ARRAY_LENGTH(memory_cells); ++index)
+ for (index = 0; index < std::size(memory_cells); ++index)
{
flags = outputpins[index].flags;
@@ -3967,7 +4228,7 @@ static void print_epl10p8_product_terms(const pal_data* pal, const jed_data* jed
indent += strlen(LOW_SYMBOL);
}
- sprintf(buffer, OUTPUT_SYMBOL "%d " COMBINATORIAL_ASSIGNMENT " ", outputpins[index].pin);
+ snprintf(buffer, 200, OUTPUT_SYMBOL "%d " COMBINATORIAL_ASSIGNMENT " ", outputpins[index].pin);
printf("%s", buffer);
@@ -4426,7 +4687,7 @@ static void print_82s100_pls100_product_terms(const pal_data* pal, const jed_dat
indent += strlen(LOW_SYMBOL);
}
- sprintf(buffer, OUTPUT_SYMBOL "%d " COMBINATORIAL_ASSIGNMENT " ", outputpins[index].pin);
+ snprintf(buffer, 200, OUTPUT_SYMBOL "%d " COMBINATORIAL_ASSIGNMENT " ", outputpins[index].pin);
printf("%s", buffer);
@@ -4504,8 +4765,8 @@ static void config_pal10l8_pins(const pal_data* pal, const jed_data* jed)
{18, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{19, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -4528,8 +4789,8 @@ static void config_pal10h8_pins(const pal_data* pal, const jed_data* jed)
{18, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{19, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -4550,8 +4811,8 @@ static void config_pal12l6_pins(const pal_data* pal, const jed_data* jed)
{17, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{18, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -4572,8 +4833,8 @@ static void config_pal12h6_pins(const pal_data* pal, const jed_data* jed)
{17, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{18, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -4592,8 +4853,8 @@ static void config_pal14l4_pins(const pal_data* pal, const jed_data* jed)
{16, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{17, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -4612,8 +4873,8 @@ static void config_pal14h4_pins(const pal_data* pal, const jed_data* jed)
{16, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{17, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -4630,8 +4891,8 @@ static void config_pal16l2_pins(const pal_data* pal, const jed_data* jed)
{15, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{16, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -4648,8 +4909,8 @@ static void config_pal16h2_pins(const pal_data* pal, const jed_data* jed)
{15, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{16, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -4666,8 +4927,8 @@ static void config_pal16c1_pins(const pal_data* pal, const jed_data* jed)
{15, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{16, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -4696,7 +4957,7 @@ static void config_pal16l8_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -4732,7 +4993,7 @@ static void config_pal16r4_pins(const pal_data* pal, const jed_data* jed)
++output_pin_count;
}
- for (index = 0; index < ARRAY_LENGTH(registered_pins); ++index)
+ for (index = 0; index < std::size(registered_pins); ++index)
{
output_pins[output_pin_count].pin = registered_pins[index];
output_pins[output_pin_count].flags = OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED;
@@ -4756,7 +5017,7 @@ static void config_pal16r4_pins(const pal_data* pal, const jed_data* jed)
++output_pin_count;
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -4784,7 +5045,7 @@ static void config_pal16r6_pins(const pal_data* pal, const jed_data* jed)
++output_pin_count;
}
- for (index = 0; index < ARRAY_LENGTH(registered_pins); ++index)
+ for (index = 0; index < std::size(registered_pins); ++index)
{
output_pins[output_pin_count].pin = registered_pins[index];
output_pins[output_pin_count].flags = OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED;
@@ -4800,7 +5061,7 @@ static void config_pal16r6_pins(const pal_data* pal, const jed_data* jed)
++output_pin_count;
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -4824,274 +5085,8 @@ static void config_pal16r8_pins(const pal_data* pal, const jed_data* jed)
{18, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED},
{19, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
-}
-
-
-
-/*-------------------------------------------------
- config_palce16v8_pins - configures the pins for
- a PALCE16V8
--------------------------------------------------*/
-
-static void config_palce16v8_pins(const pal_data* pal, const jed_data* jed)
-{
- typedef struct _output_logic_macrocell output_logic_macrocell;
- struct _output_logic_macrocell
- {
- uint16_t pin;
- uint16_t sl0_fuse; /* registers allowed (0 - registered, 1 - not registered) */
- uint16_t sl1_fuse; /* output polarity (0 - low, 1 - high) */
- uint16_t fuserowoutputenable;
- };
-
- static output_logic_macrocell macrocells[] = {
- {12, 2127, 2055, 1792},
- {13, 2126, 2054, 1536},
- {14, 2125, 2053, 1280},
- {15, 2124, 2052, 1024},
- {16, 2123, 2051, 768},
- {17, 2122, 2050, 512},
- {18, 2121, 2049, 256},
- {19, 2120, 2048, 0}};
- static pin_fuse_columns pinfusecolumns_i_or_o[] = {
- {1, 3, 2},
- {2, 1, 0},
- {3, 5, 4},
- {4, 9, 8},
- {5, 13, 12},
- {6, 17, 16},
- {7, 21, 20},
- {8, 25, 24},
- {9, 29, 28},
- {11, 31, 30},
- {12, 27, 26},
- {13, 23, 22},
- {14, 19, 18},
- {17, 15, 14},
- {18, 11, 10},
- {19, 7, 6}};
- static pin_fuse_columns pinfusecolumns_io[] = {
- {1, 3, 2},
- {2, 1, 0},
- {3, 5, 4},
- {4, 9, 8},
- {5, 13, 12},
- {6, 17, 16},
- {7, 21, 20},
- {8, 25, 24},
- {9, 29, 28},
- {11, 31, 30},
- {13, 27, 26},
- {14, 23, 22},
- {15, 19, 18},
- {16, 15, 14},
- {17, 11, 10},
- {18, 7, 6}};
- static pin_fuse_columns pinfusecolumns_regs[] = {
- {2, 1, 0},
- {3, 5, 4},
- {4, 9, 8},
- {5, 13, 12},
- {6, 17, 16},
- {7, 21, 20},
- {8, 25, 24},
- {9, 29, 28},
- {12, 31, 30},
- {13, 27, 26},
- {14, 23, 22},
- {15, 19, 18},
- {16, 15, 14},
- {17, 11, 10},
- {18, 7, 6},
- {19, 3, 2}};
- static uint16_t input_pins_i_or_o[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11};
- static uint16_t input_pins_io[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11};
- static uint16_t input_pins_regs[] = {2, 3, 4, 5, 6, 7, 8, 9};
- static uint16_t sg0 = 2192;
- static uint16_t sg1 = 2193;
- uint16_t input_pins[18];
- pin_output_config output_pins[ARRAY_LENGTH(macrocells)];
- uint16_t index, input_pin_count, output_pin_count;
-
- input_pin_count = 0;
- output_pin_count = 0;
-
- if (!jed_get_fuse(jed, sg0))
- {
- /* Device uses registers */
-
- if (jed_get_fuse(jed, sg1))
- {
- memcpy(palce16v8pinfusecolumns, pinfusecolumns_regs, sizeof(pinfusecolumns_regs));
-
- memcpy(input_pins, input_pins_regs, sizeof(input_pins_regs));
-
- input_pin_count = ARRAY_LENGTH(input_pins_regs);
-
- for (index = 0; index < ARRAY_LENGTH(macrocells); ++index)
- {
- if (!jed_get_fuse(jed, macrocells[index].sl0_fuse))
- {
- /* Registered output */
-
- config_palce16v8_pin_as_8_product_terms(macrocells[index].pin);
-
- output_pins[output_pin_count].pin = macrocells[index].pin;
- output_pins[output_pin_count].flags = OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED;
-
- if (!jed_get_fuse(jed, macrocells[index].sl1_fuse))
- {
- output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
- }
- else
- {
- output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
- }
-
- ++output_pin_count;
-
- input_pins[input_pin_count] = macrocells[index].pin;
-
- ++input_pin_count;
- }
- else
- {
- /* Combinatorial I/O */
-
- if (does_output_enable_fuse_row_allow_output(pal, jed, macrocells[index].fuserowoutputenable))
- {
- config_palce16v8_pin_as_7_product_terms_and_oe_term(macrocells[index].pin);
-
- output_pins[output_pin_count].pin = macrocells[index].pin;
- output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT;
-
- if (!jed_get_fuse(jed, macrocells[index].sl1_fuse))
- {
- output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
- }
- else
- {
- output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
- }
-
- ++output_pin_count;
- }
-
- input_pins[input_pin_count] = macrocells[index].pin;
-
- ++input_pin_count;
- }
- }
- }
- else
- {
- fprintf(stderr, "Unknown configuration type!\n");
- }
- }
- else
- {
- /* Device uses no registers */
-
- if (jed_get_fuse(jed, sg1))
- {
- /* Combinatorial I/O (7 product terms and 1 output enable product term) */
-
- memcpy(palce16v8pinfusecolumns, pinfusecolumns_io, sizeof(pinfusecolumns_io));
-
- memcpy(input_pins, input_pins_io, sizeof(input_pins_io));
-
- input_pin_count = ARRAY_LENGTH(input_pins_io);
-
- for (index = 0; index < ARRAY_LENGTH(macrocells); ++index)
- {
- if (does_output_enable_fuse_row_allow_output(pal, jed, macrocells[index].fuserowoutputenable))
- {
- config_palce16v8_pin_as_7_product_terms_and_oe_term(macrocells[index].pin);
-
- output_pins[output_pin_count].pin = macrocells[index].pin;
- output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT;
-
- if (!jed_get_fuse(jed, macrocells[index].sl1_fuse))
- {
- output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
- }
- else
- {
- output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
- }
-
- ++output_pin_count;
- }
-
- /* Pins 12 and 19 cannot be used as an input only an output. */
-
- if (macrocells[index].pin != 12 && macrocells[index].pin != 19)
- {
- input_pins[input_pin_count] = macrocells[index].pin;
-
- ++input_pin_count;
- }
- }
- }
- else
- {
- /* Combinatorial Output or Input */
-
- memcpy(palce16v8pinfusecolumns, pinfusecolumns_i_or_o, sizeof(pinfusecolumns_i_or_o));
-
- memcpy(input_pins, input_pins_i_or_o, sizeof(input_pins_i_or_o));
-
- input_pin_count = ARRAY_LENGTH(input_pins_i_or_o);
-
- for (index = 0; index < ARRAY_LENGTH(macrocells); ++index)
- {
- if (!jed_get_fuse(jed, macrocells[index].sl0_fuse))
- {
- /* pin configured as an output only */
-
- config_palce16v8_pin_as_8_product_terms(macrocells[index].pin);
-
- output_pins[output_pin_count].pin = macrocells[index].pin;
- output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE;
-
- if (!jed_get_fuse(jed, macrocells[index].sl1_fuse))
- {
- output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
- }
- else
- {
- output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
- }
-
- ++output_pin_count;
- }
- else
- {
- /* pin configured as an input only */
-
- input_pins[input_pin_count] = macrocells[index].pin;
-
- ++input_pin_count;
- }
- }
- }
- }
-
- set_input_pins(input_pins, input_pin_count);
- set_output_pins(output_pins, output_pin_count);
-
- /* 2056 - 2119 are the 64 bit signature fuses */
-
- /* 2128 - 2135 product term 8? */
- /* 2136 - 2143 product term 7? */
- /* 2144 - 2151 product term 6? */
- /* 2152 - 2159 product term 5? */
- /* 2160 - 2167 product term 4? */
- /* 2168 - 2175 product term 3? */
- /* 2176 - 2183 product term 2? */
- /* 2184 - 2191 product term 1? */
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -5129,7 +5124,7 @@ static void config_gal16v8_pins(const pal_data* pal, const jed_data* jed)
{17, NO_OUTPUT_ENABLE_FUSE_ROW, 512, 736},
{18, NO_OUTPUT_ENABLE_FUSE_ROW, 256, 480},
{19, NO_OUTPUT_ENABLE_FUSE_ROW, 0, 224}};
- static pin_fuse_rows pinfuserows_combinatorial[] = {
+ static pin_fuse_rows pinfuserows_combinatorialcomplex[] = {
{12, 1792, 1824, 2016},
{13, 1536, 1568, 1760},
{14, 1280, 1312, 1504},
@@ -5138,6 +5133,15 @@ static void config_gal16v8_pins(const pal_data* pal, const jed_data* jed)
{17, 512, 544, 736},
{18, 256, 288, 480},
{19, 0, 32, 224}};
+ static pin_fuse_rows pinfuserows_combinatorialsimple[] = {
+ {12, NO_OUTPUT_ENABLE_FUSE_ROW, 1792, 2016},
+ {13, NO_OUTPUT_ENABLE_FUSE_ROW, 1536, 1760},
+ {14, NO_OUTPUT_ENABLE_FUSE_ROW, 1280, 1504},
+ {15, NO_OUTPUT_ENABLE_FUSE_ROW, 1024, 1248},
+ {16, NO_OUTPUT_ENABLE_FUSE_ROW, 768, 992},
+ {17, NO_OUTPUT_ENABLE_FUSE_ROW, 512, 736},
+ {18, NO_OUTPUT_ENABLE_FUSE_ROW, 256, 480},
+ {19, NO_OUTPUT_ENABLE_FUSE_ROW, 0, 224}};
static pin_fuse_columns pinfusecolumns_registered[] = {
{2, 1, 0},
{3, 5, 4},
@@ -5191,9 +5195,9 @@ static void config_gal16v8_pins(const pal_data* pal, const jed_data* jed)
{19, 7, 6}};
static uint16_t input_pins_registered[] = {2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19};
static uint16_t input_pins_combinatorialcomplex[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 14, 15, 16, 17, 18};
- static uint16_t input_pins_combinatorialsimple[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 17, 18, 19};
- pin_output_config output_pins[ARRAY_LENGTH(macrocells)];
- uint16_t index, output_pin_count;
+ uint16_t input_pins_combinatorialsimple[18];
+ pin_output_config output_pins[std::size(macrocells)];
+ uint16_t index, input_pin_count, output_pin_count;
output_pin_count = 0;
@@ -5208,12 +5212,12 @@ static void config_gal16v8_pins(const pal_data* pal, const jed_data* jed)
{
/* Complex Mode */
- set_input_pins(input_pins_combinatorialcomplex, ARRAY_LENGTH(input_pins_combinatorialcomplex));
+ set_input_pins(input_pins_combinatorialcomplex, std::size(input_pins_combinatorialcomplex));
- memcpy(gal16v8pinfuserows, pinfuserows_combinatorial, sizeof(pinfuserows_combinatorial));
+ memcpy(gal16v8pinfuserows, pinfuserows_combinatorialcomplex, sizeof(pinfuserows_combinatorialcomplex));
memcpy(gal16v8pinfusecolumns, pinfusecolumns_combinatorialcomplex, sizeof(pinfusecolumns_combinatorialcomplex));
- for (index = 0; index < ARRAY_LENGTH(macrocells); ++index)
+ for (index = 0; index < std::size(macrocells); ++index)
{
if (is_gal16v8_product_term_enabled(pal, jed, pal->pinfuserows[index].fuserowoutputenable) &&
does_output_enable_fuse_row_allow_output(pal, jed, pal->pinfuserows[index].fuserowoutputenable))
@@ -5248,25 +5252,64 @@ static void config_gal16v8_pins(const pal_data* pal, const jed_data* jed)
{
/* Simple Mode */
- set_input_pins(input_pins_combinatorialsimple, ARRAY_LENGTH(input_pins_combinatorialsimple));
+ input_pin_count = 0;
- memcpy(gal16v8pinfuserows, pinfuserows_registered, sizeof(pinfuserows_registered));
+ for (index = 1; index < 10; ++index)
+ {
+ input_pins_combinatorialsimple[input_pin_count] = index;
+
+ ++input_pin_count;
+ }
+
+ input_pins_combinatorialsimple[input_pin_count] = 11;
+
+ ++input_pin_count;
+
+ memcpy(gal16v8pinfuserows, pinfuserows_combinatorialsimple, sizeof(pinfuserows_combinatorialsimple));
memcpy(gal16v8pinfusecolumns, pinfusecolumns_combinatorialsimple, sizeof(pinfusecolumns_combinatorialsimple));
- for (index = 0; index < ARRAY_LENGTH(macrocells); ++index)
+ for (index = 0; index < std::size(macrocells); ++index)
{
- if (jed_get_fuse(jed, macrocells[index].ac1_fuse))
+ if (macrocells[index].pin != 15 && macrocells[index].pin != 16)
{
- /* Pin is for input only */
+ if (jed_get_fuse(jed, macrocells[index].ac1_fuse))
+ {
+ /* Pin is for input only */
+
+ input_pins_combinatorialsimple[input_pin_count] = macrocells[index].pin;
- if (macrocells[index].pin == 15 || macrocells[index].pin == 16)
+ ++input_pin_count;
+ }
+ else
{
- fprintf(stderr, "Pin %d cannot be configured as an input pin.\n",
- macrocells[index].pin);
+ output_pins[output_pin_count].pin = macrocells[index].pin;
+ output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL;
+
+ if (jed_get_fuse(jed, macrocells[index].xor_fuse))
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
+ }
+
+ output_pins[output_pin_count].flags |= OUTPUT_FEEDBACK_OUTPUT;
+
+ input_pins_combinatorialsimple[input_pin_count] = macrocells[index].pin;
+
+ ++input_pin_count;
+
+ ++output_pin_count;
}
}
else
{
+ /* For pins 15 and 16 ignore the value of the ac1_fuse (This
+ normally determine if the pin is an input or output.) because
+ according to the datasheet these macrocells are output
+ only when in simple mode. */
+
output_pins[output_pin_count].pin = macrocells[index].pin;
output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL;
@@ -5279,38 +5322,32 @@ static void config_gal16v8_pins(const pal_data* pal, const jed_data* jed)
output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
}
- if (output_pins[output_pin_count].pin != 15 &&
- output_pins[output_pin_count].pin != 16)
- {
- output_pins[output_pin_count].flags |= OUTPUT_FEEDBACK_OUTPUT;
- }
- else
- {
- output_pins[output_pin_count].flags |= OUTPUT_FEEDBACK_NONE;
- }
+ output_pins[output_pin_count].flags |= OUTPUT_FEEDBACK_NONE;
++output_pin_count;
}
}
+
+ set_input_pins(input_pins_combinatorialsimple, input_pin_count);
}
}
else
{
/* Registered */
- set_input_pins(input_pins_registered, ARRAY_LENGTH(input_pins_registered));
+ set_input_pins(input_pins_registered, std::size(input_pins_registered));
memcpy(gal16v8pinfusecolumns, pinfusecolumns_registered, sizeof(pinfusecolumns_registered));
- for (index = 0; index < ARRAY_LENGTH(macrocells); ++index)
+ for (index = 0; index < std::size(macrocells); ++index)
{
if (jed_get_fuse(jed, macrocells[index].ac1_fuse))
{
/* combinatorial pin */
- gal16v8pinfuserows[index].fuserowoutputenable = pinfuserows_combinatorial[index].fuserowoutputenable;
- gal16v8pinfuserows[index].fuserowtermstart = pinfuserows_combinatorial[index].fuserowtermstart;
- gal16v8pinfuserows[index].fuserowtermend = pinfuserows_combinatorial[index].fuserowtermend;
+ gal16v8pinfuserows[index].fuserowoutputenable = pinfuserows_combinatorialcomplex[index].fuserowoutputenable;
+ gal16v8pinfuserows[index].fuserowtermstart = pinfuserows_combinatorialcomplex[index].fuserowtermstart;
+ gal16v8pinfuserows[index].fuserowtermend = pinfuserows_combinatorialcomplex[index].fuserowtermend;
if (is_gal16v8_product_term_enabled(pal, jed, pal->pinfuserows[index].fuserowoutputenable) &&
does_output_enable_fuse_row_allow_output(pal, jed, pal->pinfuserows[index].fuserowoutputenable))
@@ -5387,14 +5424,14 @@ static void config_peel18cv8_pins(const pal_data* pal, const jed_data* jed)
{18, 2668, 2669, 2670, 2671},
{19, 2664, 2665, 2666, 2667}};
static uint16_t input_pins[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19};
- pin_output_config output_pins[ARRAY_LENGTH(macrocells)];
+ pin_output_config output_pins[std::size(macrocells)];
uint16_t index, output_pin_count;
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
output_pin_count = 0;
- for (index = 0; index < ARRAY_LENGTH(macrocells); ++index)
+ for (index = 0; index < std::size(macrocells); ++index)
{
if (jed_get_fuse(jed, macrocells[index].feedback1_fuse) &&
!jed_get_fuse(jed, macrocells[index].feedback2_fuse))
@@ -5509,7 +5546,7 @@ static void config_ampal18p8_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[8];
uint16_t index, output_pin_count;
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
output_pin_count = 0;
@@ -5565,12 +5602,12 @@ static void config_gal18v10_pins(const pal_data* pal, const jed_data* jed)
{18, 3458, 3459},
{19, 3456, 3457}};
static uint16_t input_pins[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19};
- pin_output_config output_pins[ARRAY_LENGTH(macrocells)];
+ pin_output_config output_pins[std::size(macrocells)];
uint16_t index, output_pin_count;
output_pin_count = 0;
- for (index = 0; index < ARRAY_LENGTH(output_pins); ++index)
+ for (index = 0; index < std::size(output_pins); ++index)
{
if (jed_get_fuse(jed, macrocells[index].s1_fuse))
{
@@ -5613,7 +5650,7 @@ static void config_gal18v10_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -5653,7 +5690,7 @@ static void config_pal20l8_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -5693,7 +5730,7 @@ static void config_pal20l10_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -5729,7 +5766,7 @@ static void config_pal20r4_pins(const pal_data* pal, const jed_data* jed)
++output_pin_count;
}
- for (index = 0; index < ARRAY_LENGTH(registered_pins); ++index)
+ for (index = 0; index < std::size(registered_pins); ++index)
{
output_pins[output_pin_count].pin = registered_pins[index];
output_pins[output_pin_count].flags = OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED;
@@ -5753,7 +5790,7 @@ static void config_pal20r4_pins(const pal_data* pal, const jed_data* jed)
++output_pin_count;
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -5781,7 +5818,7 @@ static void config_pal20r6_pins(const pal_data* pal, const jed_data* jed)
++output_pin_count;
}
- for (index = 0; index < ARRAY_LENGTH(registered_pins); ++index)
+ for (index = 0; index < std::size(registered_pins); ++index)
{
output_pins[output_pin_count].pin = registered_pins[index];
output_pins[output_pin_count].flags = OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED;
@@ -5797,7 +5834,7 @@ static void config_pal20r6_pins(const pal_data* pal, const jed_data* jed)
++output_pin_count;
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -5821,8 +5858,8 @@ static void config_pal20r8_pins(const pal_data* pal, const jed_data* jed)
{21, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED},
{22, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -5847,8 +5884,8 @@ static void config_pal20ra10_pins(const pal_data* pal, const jed_data* jed)
{22, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED},
{23, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -5873,12 +5910,12 @@ static void config_pal20x4_pins(const pal_data* pal, const jed_data* jed)
{22, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT},
{23, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
/*-------------------------------------------------
- config_pal20x10_pins - configures the pins for
+ config_pal20x8_pins - configures the pins for
a PAL20X8
-------------------------------------------------*/
@@ -5897,8 +5934,8 @@ static void config_pal20x8_pins(const pal_data* pal, const jed_data* jed)
{22, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED},
{23, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -5923,8 +5960,568 @@ static void config_pal20x10_pins(const pal_data* pal, const jed_data* jed)
{22, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED},
{23, OUTPUT_ACTIVELOW | OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
+}
+
+
+
+/*-------------------------------------------------
+ config_gal20v8_pins - configures the pins for
+ a GAL20V8
+-------------------------------------------------*/
+
+static void config_gal20v8_pins(const pal_data* pal, const jed_data* jed)
+{
+ typedef struct _output_logic_macrocell output_logic_macrocell;
+ struct _output_logic_macrocell
+ {
+ uint16_t pin;
+ uint16_t xor_fuse;
+ uint16_t ac1_fuse;
+ };
+
+ static output_logic_macrocell macrocells[] = {
+ {15, 2567, 2639},
+ {16, 2566, 2638},
+ {17, 2565, 2637},
+ {18, 2564, 2636},
+ {19, 2563, 2635},
+ {20, 2562, 2634},
+ {21, 2561, 2633},
+ {22, 2560, 2632}};
+ static pin_fuse_rows pinfuserows_registered[] = {
+ {15, NO_OUTPUT_ENABLE_FUSE_ROW, 2240, 2520},
+ {16, NO_OUTPUT_ENABLE_FUSE_ROW, 1920, 2200},
+ {17, NO_OUTPUT_ENABLE_FUSE_ROW, 1600, 1880},
+ {18, NO_OUTPUT_ENABLE_FUSE_ROW, 1280, 1560},
+ {19, NO_OUTPUT_ENABLE_FUSE_ROW, 960, 1240},
+ {20, NO_OUTPUT_ENABLE_FUSE_ROW, 640, 920},
+ {21, NO_OUTPUT_ENABLE_FUSE_ROW, 320, 600},
+ {22, NO_OUTPUT_ENABLE_FUSE_ROW, 0, 280}};
+ static pin_fuse_rows pinfuserows_combinatorialcomplex[] = {
+ {15, 2240, 2280, 2520},
+ {16, 1920, 1960, 2200},
+ {17, 1600, 1640, 1880},
+ {18, 1280, 1320, 1560},
+ {19, 960, 1000, 1240},
+ {20, 640, 680, 920},
+ {21, 320, 360, 600},
+ {22, 0, 40, 280}};
+ static pin_fuse_rows pinfuserows_combinatorialsimple[] = {
+ {15, NO_OUTPUT_ENABLE_FUSE_ROW, 2240, 2520},
+ {16, NO_OUTPUT_ENABLE_FUSE_ROW, 1920, 2200},
+ {17, NO_OUTPUT_ENABLE_FUSE_ROW, 1600, 1880},
+ {18, NO_OUTPUT_ENABLE_FUSE_ROW, 1280, 1560},
+ {19, NO_OUTPUT_ENABLE_FUSE_ROW, 960, 1240},
+ {20, NO_OUTPUT_ENABLE_FUSE_ROW, 640, 920},
+ {21, NO_OUTPUT_ENABLE_FUSE_ROW, 320, 600},
+ {22, NO_OUTPUT_ENABLE_FUSE_ROW, 0, 280}};
+ static pin_fuse_columns pinfusecolumns_registered[] = {
+ {2, 1, 0},
+ {3, 5, 4},
+ {4, 9, 8},
+ {5, 13, 12},
+ {6, 17, 16},
+ {7, 21, 20},
+ {8, 25, 24},
+ {9, 29, 28},
+ {10, 33, 32},
+ {11, 37, 36},
+ {14, 39, 38},
+ {15, 35, 34},
+ {16, 31, 30},
+ {17, 27, 26},
+ {18, 23, 22},
+ {19, 19, 18},
+ {20, 15, 14},
+ {21, 11, 10},
+ {22, 7, 6},
+ {23, 3, 2}};
+ static pin_fuse_columns pinfusecolumns_combinatorialcomplex[] = {
+ {1, 3, 2},
+ {2, 1, 0},
+ {3, 5, 4},
+ {4, 9, 8},
+ {5, 13, 12},
+ {6, 17, 16},
+ {7, 21, 20},
+ {8, 25, 24},
+ {9, 29, 28},
+ {10, 33, 32},
+ {11, 37, 36},
+ {13, 39, 38},
+ {14, 35, 34},
+ {16, 31, 30},
+ {17, 27, 26},
+ {18, 23, 22},
+ {19, 19, 18},
+ {20, 15, 14},
+ {21, 11, 10},
+ {23, 7, 6}};
+ static pin_fuse_columns pinfusecolumns_combinatorialsimple[] = {
+ {1, 3, 2},
+ {2, 1, 0},
+ {3, 5, 4},
+ {4, 9, 8},
+ {5, 13, 12},
+ {6, 17, 16},
+ {7, 21, 20},
+ {8, 25, 24},
+ {9, 29, 28},
+ {10, 33, 32},
+ {11, 37, 36},
+ {13, 39, 38},
+ {14, 35, 34},
+ {15, 31, 30},
+ {16, 27, 26},
+ {17, 23, 22},
+ {20, 19, 18},
+ {21, 15, 14},
+ {22, 11, 10},
+ {23, 7, 6}};
+ static uint16_t input_pins_registered[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
+ static uint16_t input_pins_combinatorialcomplex[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 16, 17, 18, 19, 20, 21, 23};
+ uint16_t input_pins_combinatorialsimple[22];
+ pin_output_config output_pins[std::size(macrocells)];
+ uint16_t index, input_pin_count, output_pin_count;
+
+ output_pin_count = 0;
+
+ /* SYN Fuse: 0 - registered, 1 - combinatorial */
+
+ if (jed_get_fuse(jed, 2704))
+ {
+ /* Combinatorial */
+ /* AC0 Fuse: 0 - simple mode, 1 - complex mode */
+
+ if (jed_get_fuse(jed, 2705))
+ {
+ /* Complex Mode */
+
+ set_input_pins(input_pins_combinatorialcomplex, std::size(input_pins_combinatorialcomplex));
+
+ memcpy(gal20v8pinfuserows, pinfuserows_combinatorialcomplex, sizeof(pinfuserows_combinatorialcomplex));
+ memcpy(gal20v8pinfusecolumns, pinfusecolumns_combinatorialcomplex, sizeof(pinfusecolumns_combinatorialcomplex));
+
+ for (index = 0; index < std::size(macrocells); ++index)
+ {
+ if (is_gal20v8_product_term_enabled(pal, jed, pal->pinfuserows[index].fuserowoutputenable) &&
+ does_output_enable_fuse_row_allow_output(pal, jed, pal->pinfuserows[index].fuserowoutputenable))
+ {
+ output_pins[output_pin_count].pin = macrocells[index].pin;
+ output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL;
+
+ if (jed_get_fuse(jed, macrocells[index].xor_fuse))
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
+ }
+
+ if (output_pins[output_pin_count].pin != 15 &&
+ output_pins[output_pin_count].pin != 22)
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_FEEDBACK_OUTPUT;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_FEEDBACK_NONE;
+ }
+
+ ++output_pin_count;
+ }
+ }
+ }
+ else
+ {
+ /* Simple Mode */
+
+ input_pin_count = 0;
+
+ for (index = 1; index < 12; ++index)
+ {
+ input_pins_combinatorialsimple[input_pin_count] = index;
+
+ ++input_pin_count;
+ }
+
+ for (index = 13; index < 15; ++index)
+ {
+ input_pins_combinatorialsimple[input_pin_count] = index;
+
+ ++input_pin_count;
+ }
+
+ memcpy(gal20v8pinfuserows, pinfuserows_combinatorialsimple, sizeof(pinfuserows_combinatorialsimple));
+ memcpy(gal20v8pinfusecolumns, pinfusecolumns_combinatorialsimple, sizeof(pinfusecolumns_combinatorialsimple));
+
+ for (index = 0; index < std::size(macrocells); ++index)
+ {
+ if (jed_get_fuse(jed, macrocells[index].ac1_fuse))
+ {
+ /* Pin is for input only */
+
+ input_pins_combinatorialsimple[input_pin_count] = macrocells[index].pin;
+
+ ++input_pin_count;
+
+ if (macrocells[index].pin == 18 || macrocells[index].pin == 19)
+ {
+ fprintf(stderr, "Pin %d cannot be configured as an input pin.\n",
+ macrocells[index].pin);
+ }
+ }
+ else
+ {
+ output_pins[output_pin_count].pin = macrocells[index].pin;
+ output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL;
+
+ if (jed_get_fuse(jed, macrocells[index].xor_fuse))
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
+ }
+
+ if (macrocells[index].pin != 18 && macrocells[index].pin != 19)
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_FEEDBACK_OUTPUT;
+
+ input_pins_combinatorialsimple[input_pin_count] = macrocells[index].pin;
+
+ ++input_pin_count;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_FEEDBACK_NONE;
+ }
+
+ ++output_pin_count;
+ }
+ }
+
+ input_pins_combinatorialsimple[input_pin_count] = 23;
+
+ ++input_pin_count;
+
+ set_input_pins(input_pins_combinatorialsimple, input_pin_count);
+ }
+ }
+ else
+ {
+ /* Registered */
+
+ set_input_pins(input_pins_registered, std::size(input_pins_registered));
+
+ memcpy(gal20v8pinfusecolumns, pinfusecolumns_registered, sizeof(pinfusecolumns_registered));
+
+ for (index = 0; index < std::size(macrocells); ++index)
+ {
+ if (jed_get_fuse(jed, macrocells[index].ac1_fuse))
+ {
+ /* combinatorial pin */
+
+ gal20v8pinfuserows[index].fuserowoutputenable = pinfuserows_combinatorialcomplex[index].fuserowoutputenable;
+ gal20v8pinfuserows[index].fuserowtermstart = pinfuserows_combinatorialcomplex[index].fuserowtermstart;
+ gal20v8pinfuserows[index].fuserowtermend = pinfuserows_combinatorialcomplex[index].fuserowtermend;
+
+ if (is_gal20v8_product_term_enabled(pal, jed, pal->pinfuserows[index].fuserowoutputenable) &&
+ does_output_enable_fuse_row_allow_output(pal, jed, pal->pinfuserows[index].fuserowoutputenable))
+ {
+ output_pins[output_pin_count].pin = macrocells[index].pin;
+ output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT;
+
+ if (jed_get_fuse(jed, macrocells[index].xor_fuse))
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
+ }
+
+ ++output_pin_count;
+ }
+ }
+ else
+ {
+ /* registered pin */
+
+ gal20v8pinfuserows[index].fuserowoutputenable = pinfuserows_registered[index].fuserowoutputenable;
+ gal20v8pinfuserows[index].fuserowtermstart = pinfuserows_registered[index].fuserowtermstart;
+ gal20v8pinfuserows[index].fuserowtermend = pinfuserows_registered[index].fuserowtermend;
+
+ output_pins[output_pin_count].pin = macrocells[index].pin;
+ output_pins[output_pin_count].flags = OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED;
+
+ if (jed_get_fuse(jed, macrocells[index].xor_fuse))
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
+ }
+
+ ++output_pin_count;
+ }
+ }
+ }
+
+ set_output_pins(output_pins, output_pin_count);
+}
+
+
+
+/*-------------------------------------------------
+ config_palce22v10_pal22v10_pins - configures the pins for
+ a PALCE22V10
+-------------------------------------------------*/
+
+static void config_palce22v10_pal22v10_pins(const pal_data* pal, const jed_data* jed)
+{
+ typedef struct _output_logic_macrocell output_logic_macrocell;
+ struct _output_logic_macrocell
+ {
+ uint16_t pin;
+ uint16_t s0_fuse; /* output polarity (0 - low, 1 - high) */
+ uint16_t s1_fuse; /* registers allowed (0 - registered, 1 - not registered) */
+ };
+
+ static output_logic_macrocell macrocells[] = {
+ {14, 5826, 5827},
+ {15, 5824, 5825},
+ {16, 5822, 5823},
+ {17, 5820, 5821},
+ {18, 5818, 5819},
+ {19, 5816, 5817},
+ {20, 5814, 5815},
+ {21, 5812, 5813},
+ {22, 5810, 5811},
+ {23, 5808, 5809}};
+ static uint16_t input_pins[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
+ pin_output_config output_pins[std::size(macrocells)];
+ uint16_t index, output_pin_count;
+
+ output_pin_count = 0;
+
+ for (index = 0; index < std::size(output_pins); ++index)
+ {
+ if (jed_get_fuse(jed, macrocells[index].s1_fuse))
+ {
+ /* Combinatorial output or dedicated input */
+
+ if (does_output_enable_fuse_row_allow_output(pal, jed, pal->pinfuserows[index].fuserowoutputenable))
+ {
+ output_pins[output_pin_count].pin = macrocells[index].pin;
+ output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT;
+
+ if (!jed_get_fuse(jed, macrocells[index].s0_fuse))
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
+ }
+
+ ++output_pin_count;
+ }
+ }
+ else
+ {
+ /* Registered output */
+
+ output_pins[output_pin_count].pin = macrocells[index].pin;
+ output_pins[output_pin_count].flags = OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED;
+
+ if (!jed_get_fuse(jed, macrocells[index].s0_fuse))
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
+ }
+
+ ++output_pin_count;
+ }
+ }
+
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, output_pin_count);
+}
+
+
+
+/*-------------------------------------------------
+ config_gal22v10_pins - configures the pins for
+ a GAL22V10
+-------------------------------------------------*/
+
+static void config_gal22v10_pins(const pal_data* pal, const jed_data* jed)
+{
+ typedef struct _output_logic_macrocell output_logic_macrocell;
+ struct _output_logic_macrocell
+ {
+ uint16_t pin;
+ uint16_t s0_fuse; /* 0 - active low, 1 - active high */
+ uint16_t s1_fuse; /* 0 - registered, 1 - combinatorial */
+ };
+
+ static output_logic_macrocell macrocells[] = {
+ {14, 5826, 5827},
+ {15, 5824, 5825},
+ {16, 5822, 5823},
+ {17, 5820, 5821},
+ {18, 5818, 5819},
+ {19, 5816, 5817},
+ {20, 5814, 5815},
+ {21, 5812, 5813},
+ {22, 5810, 5811},
+ {23, 5808, 5809}};
+ static uint16_t input_pins[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
+ pin_output_config output_pins[std::size(macrocells)];
+ uint16_t index, output_pin_count;
+
+ output_pin_count = 0;
+
+ for (index = 0; index < std::size(output_pins); ++index)
+ {
+ if (jed_get_fuse(jed, macrocells[index].s1_fuse))
+ {
+ /* Combinatorial output or dedicated input */
+
+ if (does_output_enable_fuse_row_allow_output(pal, jed, pal->pinfuserows[index].fuserowoutputenable))
+ {
+ output_pins[output_pin_count].pin = macrocells[index].pin;
+ output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT;
+
+ if (!jed_get_fuse(jed, macrocells[index].s0_fuse))
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
+ }
+
+ ++output_pin_count;
+ }
+ }
+ else
+ {
+ /* Registered output */
+
+ output_pins[output_pin_count].pin = macrocells[index].pin;
+ output_pins[output_pin_count].flags = OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED;
+
+ if (!jed_get_fuse(jed, macrocells[index].s0_fuse))
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
+ }
+
+ ++output_pin_count;
+ }
+ }
+
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, output_pin_count);
+}
+
+
+
+/*-------------------------------------------------
+ config_atf22v10_power_down_mode_pins - configures the pins for
+ a ATF22V10 configured in power down mode.
+-------------------------------------------------*/
+
+static void config_atf22v10_power_down_mode_pins(const pal_data* pal, const jed_data* jed)
+{
+ typedef struct _output_logic_macrocell output_logic_macrocell;
+ struct _output_logic_macrocell
+ {
+ uint16_t pin;
+ uint16_t s0_fuse; /* 0 - active low, 1 - active high */
+ uint16_t s1_fuse; /* 0 - registered, 1 - combinatorial */
+ };
+
+ static output_logic_macrocell macrocells[] = {
+ {14, 5826, 5827},
+ {15, 5824, 5825},
+ {16, 5822, 5823},
+ {17, 5820, 5821},
+ {18, 5818, 5819},
+ {19, 5816, 5817},
+ {20, 5814, 5815},
+ {21, 5812, 5813},
+ {22, 5810, 5811},
+ {23, 5808, 5809}};
+ static uint16_t input_pins[] = {1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
+ pin_output_config output_pins[std::size(macrocells)];
+ uint16_t index, output_pin_count;
+
+ output_pin_count = 0;
+
+ if (jed_get_fuse(jed, 5893))
+ {
+ fprintf(stderr, "Warning: Power down fuse not blown!\n");
+ }
+
+ for (index = 0; index < std::size(output_pins); ++index)
+ {
+ if (jed_get_fuse(jed, macrocells[index].s1_fuse))
+ {
+ /* Combinatorial output or dedicated input */
+
+ if (does_output_enable_fuse_row_allow_output(pal, jed, pal->pinfuserows[index].fuserowoutputenable))
+ {
+ output_pins[output_pin_count].pin = macrocells[index].pin;
+ output_pins[output_pin_count].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_OUTPUT;
+
+ if (!jed_get_fuse(jed, macrocells[index].s0_fuse))
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
+ }
+
+ ++output_pin_count;
+ }
+ }
+ else
+ {
+ /* Registered output */
+
+ output_pins[output_pin_count].pin = macrocells[index].pin;
+ output_pins[output_pin_count].flags = OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED;
+
+ if (!jed_get_fuse(jed, macrocells[index].s0_fuse))
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVELOW;
+ }
+ else
+ {
+ output_pins[output_pin_count].flags |= OUTPUT_ACTIVEHIGH;
+ }
+
+ ++output_pin_count;
+ }
+ }
+
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, output_pin_count);
}
@@ -5962,7 +6559,7 @@ static void config_82s153_pls153_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -6001,7 +6598,7 @@ static void config_ck2605_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -6035,7 +6632,7 @@ static void config_epl10p8_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[8];
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(memory_cells); ++index)
+ for (index = 0; index < std::size(memory_cells); ++index)
{
output_pins[index].pin = memory_cells[index].pin;
output_pins[index].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE;
@@ -6050,8 +6647,8 @@ static void config_epl10p8_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6083,7 +6680,7 @@ static void config_epl12p6_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[8];
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(memory_cells); ++index)
+ for (index = 0; index < std::size(memory_cells); ++index)
{
output_pins[index].pin = memory_cells[index].pin;
output_pins[index].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE;
@@ -6098,8 +6695,8 @@ static void config_epl12p6_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6129,7 +6726,7 @@ static void config_epl14p4_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[8];
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(memory_cells); ++index)
+ for (index = 0; index < std::size(memory_cells); ++index)
{
output_pins[index].pin = memory_cells[index].pin;
output_pins[index].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE;
@@ -6144,8 +6741,8 @@ static void config_epl14p4_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6173,7 +6770,7 @@ static void config_epl16p2_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[8];
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(memory_cells); ++index)
+ for (index = 0; index < std::size(memory_cells); ++index)
{
output_pins[index].pin = memory_cells[index].pin;
output_pins[index].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE;
@@ -6188,8 +6785,8 @@ static void config_epl16p2_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6223,7 +6820,7 @@ static void config_epl16p8_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[8];
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(memory_cells); ++index)
+ for (index = 0; index < std::size(memory_cells); ++index)
{
output_pins[index].pin = memory_cells[index].pin;
output_pins[index].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE;
@@ -6238,8 +6835,8 @@ static void config_epl16p8_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6273,7 +6870,7 @@ static void config_epl16rp8_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[8];
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(memory_cells); ++index)
+ for (index = 0; index < std::size(memory_cells); ++index)
{
output_pins[index].pin = memory_cells[index].pin;
output_pins[index].flags = OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED;
@@ -6288,8 +6885,8 @@ static void config_epl16rp8_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6323,7 +6920,7 @@ static void config_epl16rp6_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[8];
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(memory_cells); ++index)
+ for (index = 0; index < std::size(memory_cells); ++index)
{
output_pins[index].pin = memory_cells[index].pin;
@@ -6348,8 +6945,8 @@ static void config_epl16rp6_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6383,7 +6980,7 @@ static void config_epl16rp4_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[8];
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(memory_cells); ++index)
+ for (index = 0; index < std::size(memory_cells); ++index)
{
output_pins[index].pin = memory_cells[index].pin;
@@ -6407,8 +7004,8 @@ static void config_epl16rp4_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
#endif
@@ -6425,7 +7022,7 @@ static void config_pal10p8_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[8];
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(output_pins); ++index)
+ for (index = 0; index < std::size(output_pins); ++index)
{
output_pins[index].pin = index + 12;
output_pins[index].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE;
@@ -6440,8 +7037,8 @@ static void config_pal10p8_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6457,7 +7054,7 @@ static void config_pal12p6_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[6];
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(output_pins); ++index)
+ for (index = 0; index < std::size(output_pins); ++index)
{
output_pins[index].pin = index + 13;
output_pins[index].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE;
@@ -6472,8 +7069,8 @@ static void config_pal12p6_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6489,7 +7086,7 @@ static void config_pal14p4_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[4];
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(output_pins); ++index)
+ for (index = 0; index < std::size(output_pins); ++index)
{
output_pins[index].pin = index + 14;
output_pins[index].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE;
@@ -6504,8 +7101,8 @@ static void config_pal14p4_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6521,7 +7118,7 @@ static void config_pal16p2_pins(const pal_data* pal, const jed_data* jed)
pin_output_config output_pins[2];
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(output_pins); ++index)
+ for (index = 0; index < std::size(output_pins); ++index)
{
output_pins[index].pin = index + 15;
output_pins[index].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE;
@@ -6536,8 +7133,8 @@ static void config_pal16p2_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6575,7 +7172,7 @@ static void config_pal16p8_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -6629,7 +7226,7 @@ static void config_pal16rp4_pins(const pal_data* pal, const jed_data* jed)
++output_pin_count;
}
- for (index = 0; index < ARRAY_LENGTH(registered_pins); ++index)
+ for (index = 0; index < std::size(registered_pins); ++index)
{
output_pins[output_pin_count].pin = registered_pins[index];
output_pins[output_pin_count].flags = OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED;
@@ -6680,7 +7277,7 @@ static void config_pal16rp4_pins(const pal_data* pal, const jed_data* jed)
++output_pin_count;
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -6717,7 +7314,7 @@ static void config_pal16rp6_pins(const pal_data* pal, const jed_data* jed)
++output_pin_count;
}
- for (index = 0; index < ARRAY_LENGTH(registered_pins); ++index)
+ for (index = 0; index < std::size(registered_pins); ++index)
{
output_pins[output_pin_count].pin = registered_pins[index];
output_pins[output_pin_count].flags = OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED;
@@ -6751,7 +7348,7 @@ static void config_pal16rp6_pins(const pal_data* pal, const jed_data* jed)
++output_pin_count;
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
+ set_input_pins(input_pins, std::size(input_pins));
set_output_pins(output_pins, output_pin_count);
}
@@ -6776,7 +7373,7 @@ static void config_pal16rp8_pins(const pal_data* pal, const jed_data* jed)
{19, OUTPUT_REGISTERED | OUTPUT_FEEDBACK_REGISTERED}};
uint16_t index;
- for (index = 0; index < ARRAY_LENGTH(output_pins); ++index)
+ for (index = 0; index < std::size(output_pins); ++index)
{
if (!jed_get_fuse(jed, 2055 - index))
{
@@ -6788,8 +7385,8 @@ static void config_pal16rp8_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6820,8 +7417,8 @@ static void config_pal6l16_pins(const pal_data* pal, const jed_data* jed)
{22, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{23, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6850,8 +7447,8 @@ static void config_pal8l14_pins(const pal_data* pal, const jed_data* jed)
{22, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{23, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6876,8 +7473,8 @@ static void config_pal12h10_pins(const pal_data* pal, const jed_data* jed)
{22, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{23, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6902,8 +7499,8 @@ static void config_pal12l10_pins(const pal_data* pal, const jed_data* jed)
{22, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{23, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6926,8 +7523,8 @@ static void config_pal14h8_pins(const pal_data* pal, const jed_data* jed)
{21, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{22, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6950,8 +7547,8 @@ static void config_pal14l8_pins(const pal_data* pal, const jed_data* jed)
{21, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{22, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6972,8 +7569,8 @@ static void config_pal16h6_pins(const pal_data* pal, const jed_data* jed)
{20, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{21, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -6994,8 +7591,8 @@ static void config_pal16l6_pins(const pal_data* pal, const jed_data* jed)
{20, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{21, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -7014,8 +7611,8 @@ static void config_pal18h4_pins(const pal_data* pal, const jed_data* jed)
{19, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{20, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -7034,8 +7631,8 @@ static void config_pal18l4_pins(const pal_data* pal, const jed_data* jed)
{19, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{20, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -7052,8 +7649,8 @@ static void config_pal20c1_pins(const pal_data* pal, const jed_data* jed)
{18, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{19, OUTPUT_ACTIVEHIGH | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -7070,8 +7667,8 @@ static void config_pal20l2_pins(const pal_data* pal, const jed_data* jed)
{18, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE},
{19, OUTPUT_ACTIVELOW | OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE}};
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -7086,7 +7683,7 @@ static void config_82s100_pls100_pins(const pal_data* pal, const jed_data* jed)
static uint16_t input_pins[] = {9, 8, 7, 6, 5, 4, 3, 2, 27, 26, 25, 24, 23, 22, 21, 20};
pin_output_config output_pins[8];
- for (uint16_t index = 0; index < ARRAY_LENGTH(output_pins); ++index)
+ for (uint16_t index = 0; index < std::size(output_pins); ++index)
{
output_pins[index].pin = pal->pinfuserows[index].pin;
output_pins[index].flags = OUTPUT_COMBINATORIAL | OUTPUT_FEEDBACK_NONE;
@@ -7101,8 +7698,8 @@ static void config_82s100_pls100_pins(const pal_data* pal, const jed_data* jed)
}
}
- set_input_pins(input_pins, ARRAY_LENGTH(input_pins));
- set_output_pins(output_pins, ARRAY_LENGTH(output_pins));
+ set_input_pins(input_pins, std::size(input_pins));
+ set_output_pins(output_pins, std::size(output_pins));
}
@@ -7131,6 +7728,29 @@ static int is_gal16v8_product_term_enabled(const pal_data* pal, const jed_data*
/*-------------------------------------------------
+ is_gal20v8_product_term_enabled - determines if
+ a fuse row in a GAL20V8 is enabled
+-------------------------------------------------*/
+
+static int is_gal20v8_product_term_enabled(const pal_data* pal, const jed_data* jed, uint16_t fuserow)
+{
+ uint16_t fuse_ptd;
+
+ fuse_ptd = (fuserow / calc_fuse_column_count(pal)) + 2640;
+
+ if (fuse_ptd > 2703)
+ {
+ fprintf(stderr, "Fuse row %d is illegal!\n", fuserow);
+
+ return 0;
+ }
+
+ return jed_get_fuse(jed, fuse_ptd);
+}
+
+
+
+/*-------------------------------------------------
get_peel18cv8_pin_fuse_state - determines the
fuse state of an input pin in a fuse row
-------------------------------------------------*/
@@ -7228,53 +7848,6 @@ static uint16_t get_peel18cv8_pin_fuse_state(const pal_data* pal, const jed_data
/*-------------------------------------------------
- read_source_file - read a raw source file
- into an allocated memory buffer
--------------------------------------------------*/
-
-static int read_source_file(const char *srcfile)
-{
- size_t bytes;
- FILE *file;
-
- /* open the source file */
- file = fopen(srcfile, "rb");
- if (!file)
- {
- fprintf(stderr, "Unable to open source file '%s'!\n", srcfile);
- return 1;
- }
-
- /* allocate memory for the data */
- fseek(file, 0, SEEK_END);
- srcbuflen = ftell(file);
- fseek(file, 0, SEEK_SET);
- srcbuf = (uint8_t *)malloc(srcbuflen);
- if (!srcbuf)
- {
- fprintf(stderr, "Unable to allocate %d bytes for the source!\n", (int)srcbuflen);
- fclose(file);
- return 1;
- }
-
- /* read the data */
- bytes = fread(srcbuf, 1, srcbuflen, file);
- if (bytes != srcbuflen)
- {
- fprintf(stderr, "Error reading %d bytes from the source!\n", (int)srcbuflen);
- free(srcbuf);
- fclose(file);
- return 1;
- }
-
- /* close up shop */
- fclose(file);
- return 0;
-}
-
-
-
-/*-------------------------------------------------
write_dest_file - write a memory buffer raw
into a desintation file
-------------------------------------------------*/
@@ -7323,6 +7896,8 @@ static int print_usage()
" jedutil -view <source.jed> <device> -- dump JED logic equations\n"
" jedutil -view <source.bin> <device> -- dump binary logic equations\n"
" jedutil -viewlist -- view list of supported devices\n"
+ " jedutil -listcompatible <source.jed> -- list compatible devices\n"
+ " jedutil -listcompatible <source.bin> -- list compatible devices\n"
);
return 0;
@@ -7340,7 +7915,6 @@ static int command_convert(int argc, char *argv[])
int src_is_jed, src_is_pla, dst_is_jed;
int numfuses = 0;
jed_data jed;
- int err;
if (argc < 2)
{
@@ -7375,10 +7949,10 @@ static int command_convert(int argc, char *argv[])
}
/* read the source file */
- err = read_source_file(srcfile);
- if (err != 0)
+ auto src = util::stdio_read(fopen(srcfile, "rb"));
+ if (!src)
{
- free(srcbuf);
+ fprintf(stderr, "Unable to open source file '%s'!\n", srcfile);
return 1;
}
@@ -7390,16 +7964,18 @@ static int command_convert(int argc, char *argv[])
printf("Converting '%s' to binary form '%s'\n", srcfile, dstfile);
/* read the fuse data */
+ int err;
if (src_is_jed)
- err = jed_parse(srcbuf, srcbuflen, &jed);
- else if (src_is_pla)
- err = pla_parse(srcbuf, srcbuflen, &jed);
+ err = jed_parse(*src, &jed);
+ else /* if (src_is_pla) */
+ err = pla_parse(*src, &jed);
+ src.reset();
switch (err)
{
- case JEDERR_INVALID_DATA: fprintf(stderr, "Fatal error: Invalid source file\n"); free(srcbuf); return 1;
- case JEDERR_BAD_XMIT_SUM: fprintf(stderr, "Fatal error: Bad transmission checksum\n"); free(srcbuf); return 1;
- case JEDERR_BAD_FUSE_SUM: fprintf(stderr, "Fatal error: Bad fusemap checksum\n"); free(srcbuf); return 1;
+ case JEDERR_INVALID_DATA: fprintf(stderr, "Fatal error: Invalid source file\n"); return 1;
+ case JEDERR_BAD_XMIT_SUM: fprintf(stderr, "Fatal error: Bad transmission checksum\n"); return 1;
+ case JEDERR_BAD_FUSE_SUM: fprintf(stderr, "Fatal error: Bad fusemap checksum\n"); return 1;
}
/* override the number of fuses */
@@ -7416,7 +7992,6 @@ static int command_convert(int argc, char *argv[])
if (!dstbuf)
{
fprintf(stderr, "Unable to allocate %d bytes for the target buffer!\n", (int)dstbuflen);
- free(srcbuf);
return 1;
}
dstbuflen = jedbin_output(&jed, dstbuf, dstbuflen);
@@ -7428,10 +8003,12 @@ static int command_convert(int argc, char *argv[])
printf("Converting '%s' to JED form '%s'\n", srcfile, dstfile);
/* read the binary data */
- err = jedbin_parse(srcbuf, srcbuflen, &jed);
+ int err = jedbin_parse(*src, &jed);
+ src.reset();
+
switch (err)
{
- case JEDERR_INVALID_DATA: fprintf(stderr, "Fatal error: Invalid binary JEDEC file\n"); free(srcbuf); return 1;
+ case JEDERR_INVALID_DATA: fprintf(stderr, "Fatal error: Invalid binary JEDEC file\n"); return 1;
}
/* print out data */
@@ -7444,15 +8021,13 @@ static int command_convert(int argc, char *argv[])
if (!dstbuf)
{
fprintf(stderr, "Unable to allocate %d bytes for the target buffer!\n", (int)dstbuflen);
- free(srcbuf);
return 1;
}
dstbuflen = jed_output(&jed, dstbuf, dstbuflen);
}
/* write the destination file */
- err = write_dest_file(dstfile);
- free(srcbuf);
+ int err = write_dest_file(dstfile);
if (err != 0)
return 1;
@@ -7472,6 +8047,7 @@ static int command_view(int argc, char *argv[])
int result = 0;
const char *srcfile, *palname;
int is_jed;
+ pal_data_vector pal_data_vector;
const pal_data* pal;
jed_data jed;
int err;
@@ -7489,18 +8065,19 @@ static int command_view(int argc, char *argv[])
is_jed = is_jed_file(srcfile);
/* find the pal entry */
- pal = find_pal_data(palname);
- if (!pal)
+ find_pal_data(palname, pal_data_vector);
+
+ if (pal_data_vector.size() == 0)
{
fprintf(stderr, "Unknown pal name.\n");
return 1;
}
/* read the source file */
- err = read_source_file(srcfile);
- if (err != 0)
+ auto src = util::stdio_read(fopen(srcfile, "rb"));
+ if (!src)
{
- result = 1;
+ fprintf(stderr, "Unable to open source file '%s'!\n", srcfile);
goto end;
}
@@ -7508,7 +8085,8 @@ static int command_view(int argc, char *argv[])
if (is_jed)
{
/* read the JEDEC data */
- err = jed_parse(srcbuf, srcbuflen, &jed);
+ err = jed_parse(*src, &jed);
+ src.reset();
switch (err)
{
case JEDERR_INVALID_DATA: fprintf(stderr, "Fatal error: Invalid .JED file\n"); result = 1; goto end;
@@ -7519,14 +8097,25 @@ static int command_view(int argc, char *argv[])
else
{
/* read the binary data */
- err = jedbin_parse(srcbuf, srcbuflen, &jed);
+ err = jedbin_parse(*src, &jed);
+ src.reset();
switch (err)
{
case JEDERR_INVALID_DATA: fprintf(stderr, "Fatal error: Invalid binary JEDEC file\n"); result = 1; goto end;
}
}
- if (jed.numfuses != pal->numfuses)
+ pal = nullptr;
+
+ for (pal_data_vector::iterator it = pal_data_vector.begin(); pal == nullptr && it != pal_data_vector.end(); ++it)
+ {
+ if (jed.numfuses == (*it)->numfuses)
+ {
+ pal = *it;
+ }
+ }
+
+ if (pal == nullptr)
{
fprintf(stderr, "Fuse count does not match this pal type.");
result = 1;
@@ -7548,7 +8137,6 @@ static int command_view(int argc, char *argv[])
}
end:
- free(srcbuf);
return result;
}
@@ -7561,6 +8149,9 @@ end:
static int command_viewlist(int argc, char *argv[])
{
+ typedef std::set<std::string> string_set;
+
+ string_set nameset;
int index;
if (argc > 0)
@@ -7568,15 +8159,92 @@ static int command_viewlist(int argc, char *argv[])
return print_usage();
}
- for (index = 0; index < ARRAY_LENGTH(paldata); ++index)
+ for (index = 0; index < std::size(paldata); ++index)
+ {
+ nameset.insert(paldata[index].name);
+ }
+
+ for (string_set::iterator it = nameset.begin(); it != nameset.end(); ++it)
{
- printf("%s\n", paldata[index].name);
+ printf("%s\n", (*it).c_str());
}
return 0;
}
+
+/*-------------------------------------------------
+ command_listcompatible - views the list of
+ compatible devices
+-------------------------------------------------*/
+
+static int command_listcompatible(int argc, char *argv[])
+{
+ int result = 0;
+ const char *srcfile;
+ int is_jed;
+ jed_data jed;
+ int err;
+ int index;
+
+ if (argc != 1)
+ {
+ return print_usage();
+ }
+
+ /* extract arguments */
+ srcfile = argv[0];
+
+ /* does the source end in '.jed'? */
+ is_jed = is_jed_file(srcfile);
+
+ /* read the source file */
+ auto src = util::stdio_read(fopen(srcfile, "rb"));
+ if (!src)
+ {
+ fprintf(stderr, "Unable to open source file '%s'!\n", srcfile);
+ goto end;
+ }
+
+ /* if the source is JED, convert to binary */
+ if (is_jed)
+ {
+ /* read the JEDEC data */
+ err = jed_parse(*src, &jed);
+ src.reset();
+ switch (err)
+ {
+ case JEDERR_INVALID_DATA: fprintf(stderr, "Fatal error: Invalid .JED file\n"); result = 1; goto end;
+ case JEDERR_BAD_XMIT_SUM: fprintf(stderr, "Fatal error: Bad transmission checksum\n"); result = 1; goto end;
+ case JEDERR_BAD_FUSE_SUM: fprintf(stderr, "Fatal error: Bad fusemap checksum\n"); result = 1; goto end;
+ }
+ }
+ else
+ {
+ /* read the binary data */
+ err = jedbin_parse(*src, &jed);
+ src.reset();
+ switch (err)
+ {
+ case JEDERR_INVALID_DATA: fprintf(stderr, "Fatal error: Invalid binary JEDEC file\n"); result = 1; goto end;
+ }
+ }
+
+ for (index = 0; index < std::size(paldata); ++index)
+ {
+ if (paldata[index].numfuses == jed.numfuses)
+ {
+ printf("%s\n", paldata[index].name);
+ }
+ }
+
+end:
+ return result;
+}
+
+
+
/*-------------------------------------------------
main - primary entry point
-------------------------------------------------*/
@@ -7584,9 +8252,10 @@ static int command_viewlist(int argc, char *argv[])
int main(int argc, char *argv[])
{
command_entry command_entries[] = {
- {"-convert", &command_convert},
- {"-view", &command_view},
- {"-viewlist", &command_viewlist}};
+ {"-convert", &command_convert},
+ {"-view", &command_view},
+ {"-viewlist", &command_viewlist},
+ {"-listcompatible", &command_listcompatible}};
int index;
if (argc < 2)
@@ -7594,7 +8263,7 @@ int main(int argc, char *argv[])
return print_usage();
}
- for (index = 0; index < ARRAY_LENGTH(command_entries); ++index)
+ for (index = 0; index < std::size(command_entries); ++index)
{
if (!strcmp(argv[1], command_entries[index].command))
return command_entries[index].command_func(argc - 2, &argv[2]);
diff --git a/src/tools/ldresample.cpp b/src/tools/ldresample.cpp
index 5386ac31229..4fcd19c3afc 100644
--- a/src/tools/ldresample.cpp
+++ b/src/tools/ldresample.cpp
@@ -8,17 +8,18 @@
****************************************************************************/
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <math.h>
-#include <new>
-#include <assert.h>
+#include "avhuff.h"
#include "bitmap.h"
#include "chd.h"
-#include "avhuff.h"
#include "vbiparse.h"
+#include <cassert>
+#include <cctype>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <new>
+
//**************************************************************************
@@ -46,18 +47,18 @@ const uint32_t MINIMUM_SIGNAL_COUNT = 20;
struct movie_info
{
- double framerate;
- int iframerate;
- int numfields;
- int width;
- int height;
- int samplerate;
- int channels;
- int interlaced;
- bitmap_yuy16 bitmap;
- std::vector<int16_t> lsound;
- std::vector<int16_t> rsound;
- uint32_t samples;
+ double framerate;
+ int iframerate;
+ int numfields;
+ int width;
+ int height;
+ int samplerate;
+ int channels;
+ int interlaced;
+ bitmap_yuy16 bitmap;
+ std::vector<int16_t> lsound;
+ std::vector<int16_t> rsound;
+ uint32_t samples;
};
@@ -156,22 +157,22 @@ inline uint32_t sample_number_to_field(const movie_info &info, uint32_t samplenu
// information about it
//-------------------------------------------------
-static chd_error open_chd(chd_file &file, const char *filename, movie_info &info)
+static std::error_condition open_chd(chd_file &file, const char *filename, movie_info &info)
{
// open the file
- chd_error chderr = file.open(filename);
- if (chderr != CHDERR_NONE)
+ std::error_condition chderr = file.open(filename);
+ if (chderr)
{
- fprintf(stderr, "Error opening CHD file: %s\n", chd_file::error_string(chderr));
+ fprintf(stderr, "Error opening CHD file: %s\n", chderr.message().c_str());
return chderr;
}
// get the metadata
std::string metadata;
chderr = file.read_metadata(AV_METADATA_TAG, 0, metadata);
- if (chderr != CHDERR_NONE)
+ if (chderr)
{
- fprintf(stderr, "Error getting A/V metadata: %s\n", chd_file::error_string(chderr));
+ fprintf(stderr, "Error getting A/V metadata: %s\n", chderr.message().c_str());
return chderr;
}
@@ -180,7 +181,7 @@ static chd_error open_chd(chd_file &file, const char *filename, movie_info &info
if (sscanf(metadata.c_str(), AV_METADATA_FORMAT, &fps, &fpsfrac, &width, &height, &interlaced, &channels, &rate) != 7)
{
fprintf(stderr, "Improperly formatted metadata\n");
- return CHDERR_INVALID_DATA;
+ return chd_file::error::INVALID_METADATA;
}
// extract movie info
@@ -197,7 +198,7 @@ static chd_error open_chd(chd_file &file, const char *filename, movie_info &info
info.bitmap.resize(info.width, info.height);
info.lsound.resize(info.samplerate);
info.rsound.resize(info.samplerate);
- return CHDERR_NONE;
+ return std::error_condition();
}
@@ -205,28 +206,28 @@ static chd_error open_chd(chd_file &file, const char *filename, movie_info &info
// create_chd - create a new CHD file
//-------------------------------------------------
-static chd_error create_chd(chd_file_compressor &file, const char *filename, chd_file &source, const movie_info &info)
+static std::error_condition create_chd(chd_file_compressor &file, const char *filename, chd_file &source, const movie_info &info)
{
// create the file
chd_codec_type compression[4] = { CHD_CODEC_AVHUFF };
- chd_error chderr = file.create(filename, source.logical_bytes(), source.hunk_bytes(), source.unit_bytes(), compression);
- if (chderr != CHDERR_NONE)
+ std::error_condition chderr = file.create(filename, source.logical_bytes(), source.hunk_bytes(), source.unit_bytes(), compression);
+ if (chderr)
{
- fprintf(stderr, "Error creating new CHD file: %s\n", chd_file::error_string(chderr));
+ fprintf(stderr, "Error creating new CHD file: %s\n", chderr.message().c_str());
return chderr;
}
// clone the metadata
chderr = file.clone_all_metadata(source);
- if (chderr != CHDERR_NONE)
+ if (chderr)
{
- fprintf(stderr, "Error cloning metadata: %s\n", chd_file::error_string(chderr));
+ fprintf(stderr, "Error cloning metadata: %s\n", chderr.message().c_str());
return chderr;
}
// begin compressing
file.compress_begin();
- return CHDERR_NONE;
+ return std::error_condition();
}
@@ -237,8 +238,8 @@ static chd_error create_chd(chd_file_compressor &file, const char *filename, chd
static bool read_chd(chd_file &file, uint32_t field, movie_info &info, uint32_t soundoffs)
{
// configure the codec
- avhuff_decompress_config avconfig;
- avconfig.video.wrap(info.bitmap, info.bitmap.cliprect());
+ avhuff_decoder::config avconfig;
+ avconfig.video = &info.bitmap;
avconfig.maxsamples = info.lsound.size();
avconfig.actsamples = &info.samples;
avconfig.audio[0] = &info.lsound[soundoffs];
@@ -248,8 +249,8 @@ static bool read_chd(chd_file &file, uint32_t field, movie_info &info, uint32_t
file.codec_configure(CHD_CODEC_AVHUFF, AVHUFF_CODEC_DECOMPRESS_CONFIG, &avconfig);
// read the field
- chd_error chderr = file.read_hunk(field, nullptr);
- return (chderr == CHDERR_NONE);
+ std::error_condition chderr = file.codec_process_hunk(field);
+ return !chderr;
}
@@ -507,6 +508,7 @@ int main(int argc, char *argv[])
// verify arguments
if (argc < 2)
return usage();
+
const char *srcfilename = argv[1];
const char *dstfilename = (argc < 3) ? nullptr : argv[2];
double offset = (argc < 4) ? 0.0 : atof(argv[3]);
@@ -524,8 +526,8 @@ int main(int argc, char *argv[])
// open the source file
chd_file srcfile;
movie_info info;
- chd_error err = open_chd(srcfile, srcfilename, info);
- if (err != CHDERR_NONE)
+ std::error_condition err = open_chd(srcfile, srcfilename, info);
+ if (err)
{
fprintf(stderr, "Unable to open file '%s'\n", srcfilename);
return 1;
@@ -537,9 +539,9 @@ int main(int argc, char *argv[])
printf("Sample rate: %dHz\n", info.samplerate);
printf("Total fields: %d\n", info.numfields);
- // if we don't have a destination file, scan for edges
if (dstfilename == nullptr)
{
+ // if we don't have a destination file, scan for edges
for (uint32_t fieldnum = 60; fieldnum < info.numfields - 60; fieldnum += 30)
{
fprintf(stderr, "Field %5d\r", fieldnum);
@@ -547,14 +549,14 @@ int main(int argc, char *argv[])
find_edge_near_field(srcfile, fieldnum, info, true, delta);
}
}
-
- // otherwise, resample the source to the destination
else
{
+ // otherwise, resample the source to the destination
+
// open the destination file
- chd_resample_compressor dstfile(srcfile, info, int64_t(offset * 65536.0 * 256.0), int64_t(slope * 65536.0 * 256.0));
- err = create_chd(dstfile, dstfilename, srcfile, info);
- if (!dstfile.opened())
+ auto dstfile = std::make_unique<chd_resample_compressor>(srcfile, info, int64_t(offset * 65536.0 * 256.0), int64_t(slope * 65536.0 * 256.0));
+ err = create_chd(*dstfile, dstfilename, srcfile, info);
+ if (!dstfile->opened())
{
fprintf(stderr, "Unable to create file '%s'\n", dstfilename);
return 1;
@@ -563,7 +565,7 @@ int main(int argc, char *argv[])
// loop over all the fields in the source file
double progress, ratio;
osd_ticks_t last_update = 0;
- while (dstfile.compress_continue(progress, ratio) == CHDERR_COMPRESSING)
+ while (dstfile->compress_continue(progress, ratio) == chd_file::error::COMPRESSING)
if (osd_ticks() - last_update > osd_ticks_per_second() / 4)
{
last_update = osd_ticks();
diff --git a/src/tools/ldverify.cpp b/src/tools/ldverify.cpp
index 2a326508323..bdb3b8c0a1f 100644
--- a/src/tools/ldverify.cpp
+++ b/src/tools/ldverify.cpp
@@ -8,18 +8,19 @@
****************************************************************************/
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <new>
-#include <assert.h>
-#include "coretmpl.h"
-#include "aviio.h"
#include "avhuff.h"
+#include "aviio.h"
#include "bitmap.h"
#include "chd.h"
+#include "coretmpl.h"
#include "vbiparse.h"
+#include <cassert>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <new>
+
//**************************************************************************
@@ -174,10 +175,10 @@ static void *open_chd(const char *filename, movie_info &info)
auto chd = new chd_file;
// open the file
- chd_error chderr = chd->open(filename);
- if (chderr != CHDERR_NONE)
+ std::error_condition chderr = chd->open(filename);
+ if (chderr)
{
- fprintf(stderr, "Error opening CHD file: %s\n", chd_file::error_string(chderr));
+ fprintf(stderr, "Error opening CHD file: %s\n", chderr.message().c_str());
delete chd;
return nullptr;
}
@@ -185,9 +186,9 @@ static void *open_chd(const char *filename, movie_info &info)
// get the metadata
std::string metadata;
chderr = chd->read_metadata(AV_METADATA_TAG, 0, metadata);
- if (chderr != CHDERR_NONE)
+ if (chderr)
{
- fprintf(stderr, "Error getting A/V metadata: %s\n", chd_file::error_string(chderr));
+ fprintf(stderr, "Error getting A/V metadata: %s\n", chderr.message().c_str());
delete chd;
return nullptr;
}
@@ -235,8 +236,10 @@ static int read_chd(void *file, int frame, bitmap_yuy16 &bitmap, int16_t *lsound
for (int fieldnum = 0; fieldnum < interlace_factor; fieldnum++)
{
// make a fake bitmap for this field
- avhuff_decompress_config avconfig;
- avconfig.video.wrap(&bitmap.pix16(fieldnum), bitmap.width(), bitmap.height() / interlace_factor, bitmap.rowpixels() * interlace_factor);
+ bitmap_yuy16 video;
+ video.wrap(&bitmap.pix(fieldnum), bitmap.width(), bitmap.height() / interlace_factor, bitmap.rowpixels() * interlace_factor);
+ avhuff_decoder::config avconfig;
+ avconfig.video = &video;
// configure the codec
uint32_t numsamples;
@@ -249,8 +252,8 @@ static int read_chd(void *file, int frame, bitmap_yuy16 &bitmap, int16_t *lsound
chdfile->codec_configure(CHD_CODEC_AVHUFF, AVHUFF_CODEC_DECOMPRESS_CONFIG, &avconfig);
// read the frame
- chd_error chderr = chdfile->read_hunk(frame * interlace_factor + fieldnum, nullptr);
- if (chderr != CHDERR_NONE)
+ std::error_condition chderr = chdfile->codec_process_hunk(frame * interlace_factor + fieldnum);
+ if (chderr)
return false;
// account for samples read
@@ -320,7 +323,7 @@ static void verify_video(video_info &video, int frame, bitmap_yuy16 &bitmap)
// parse the VBI data
vbi_metadata metadata;
- vbi_parse_all(&bitmap.pix16(fieldnum), bitmap.rowpixels() * 2, bitmap.width(), 8, &metadata);
+ vbi_parse_all(&bitmap.pix(fieldnum), bitmap.rowpixels() * 2, bitmap.width(), 8, &metadata);
// if we have data in both 17 and 18, it should match
if (metadata.line17 != 0 && metadata.line18 != 0 && metadata.line17 != metadata.line18)
@@ -484,11 +487,11 @@ static void verify_video(video_info &video, int frame, bitmap_yuy16 &bitmap)
{
for (int x = 16; x < 720 - 16; x++)
{
- yhisto[bitmap.pix16(y, x) >> 8]++;
+ yhisto[bitmap.pix(y, x) >> 8]++;
if (x % 2 == 0)
- cbhisto[bitmap.pix16(y, x) & 0xff]++;
+ cbhisto[bitmap.pix(y, x) & 0xff]++;
else
- crhisto[bitmap.pix16(y, x) & 0xff]++;
+ crhisto[bitmap.pix(y, x) & 0xff]++;
}
pixels += 720 - 16 - 16;
}
diff --git a/src/tools/pngcmp.cpp b/src/tools/pngcmp.cpp
index af104e928b3..480f9fadb14 100644
--- a/src/tools/pngcmp.cpp
+++ b/src/tools/pngcmp.cpp
@@ -8,16 +8,19 @@
****************************************************************************/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include "osdcore.h"
+#include "corefile.h"
#include "png.h"
+#include "osdfile.h"
+
+#include <cassert>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <new>
+
/***************************************************************************
CONSTANTS & DEFINES
***************************************************************************/
@@ -73,56 +76,55 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img
bitmap_argb32 finalbitmap;
int width, height, maxwidth;
util::core_file::ptr file;
- osd_file::error filerr;
- png_error pngerr;
+ std::error_condition filerr;
int error = 100;
- bool bitmaps_differ;
- int x, y;
/* open the source image */
filerr = util::core_file::open(imgfile1, OPEN_FLAG_READ, file);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
- printf("Could not open %s (%d)\n", imgfile1.c_str(), int(filerr));
+ printf("Could not open %s (%s)\n", imgfile1.c_str(), filerr.message().c_str());
goto error;
}
/* load the source image */
- pngerr = png_read_bitmap(*file, bitmap1);
+ filerr = util::png_read_bitmap(*file, bitmap1);
file.reset();
- if (pngerr != PNGERR_NONE)
+ if (filerr)
{
- printf("Could not read %s (%d)\n", imgfile1.c_str(), pngerr);
+ printf("Could not read %s (%s)\n", imgfile1.c_str(), filerr.message().c_str());
goto error;
}
/* open the source image */
filerr = util::core_file::open(imgfile2, OPEN_FLAG_READ, file);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
- printf("Could not open %s (%d)\n", imgfile2.c_str(), int(filerr));
+ printf("Could not open %s (%s)\n", imgfile2.c_str(), filerr.message().c_str());
goto error;
}
/* load the source image */
- pngerr = png_read_bitmap(*file, bitmap2);
+ filerr = util::png_read_bitmap(*file, bitmap2);
file.reset();
- if (pngerr != PNGERR_NONE)
+ if (filerr)
{
- printf("Could not read %s (%d)\n", imgfile2.c_str(), pngerr);
+ printf("Could not read %s (%s)\n", imgfile2.c_str(), filerr.message().c_str());
goto error;
}
/* if the sizes are different, we differ; otherwise start off assuming we are the same */
+ bool bitmaps_differ;
bitmaps_differ = (bitmap2.width() != bitmap1.width() || bitmap2.height() != bitmap1.height());
/* compare scanline by scanline */
- for (y = 0; y < bitmap2.height() && !bitmaps_differ; y++)
+ for (int y = 0; y < bitmap2.height() && !bitmaps_differ; y++)
{
- uint32_t *base = &bitmap1.pix32(y);
- uint32_t *curr = &bitmap2.pix32(y);
+ uint32_t const *base = &bitmap1.pix(y);
+ uint32_t const *curr = &bitmap2.pix(y);
/* scan the scanline */
+ int x;
for (x = 0; x < bitmap2.width(); x++)
if (*base++ != *curr++)
break;
@@ -148,16 +150,16 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img
/* now copy and compare each set of bitmaps */
int curheight = std::max(bitmap1.height(), bitmap2.height());
/* iterate over rows in these bitmaps */
- for (y = 0; y < curheight; y++)
+ for (int y = 0; y < curheight; y++)
{
- uint32_t *src1 = (y < bitmap1.height()) ? &bitmap1.pix32(y) : nullptr;
- uint32_t *src2 = (y < bitmap2.height()) ? &bitmap2.pix32(y) : nullptr;
- uint32_t *dst1 = &finalbitmap.pix32(y);
- uint32_t *dst2 = &finalbitmap.pix32(y, bitmap1.width() + BITMAP_SPACE);
- uint32_t *dstdiff = &finalbitmap.pix32(y, bitmap1.width() + BITMAP_SPACE + maxwidth + BITMAP_SPACE);
+ uint32_t const *src1 = (y < bitmap1.height()) ? &bitmap1.pix(y) : nullptr;
+ uint32_t const *src2 = (y < bitmap2.height()) ? &bitmap2.pix(y) : nullptr;
+ uint32_t *dst1 = &finalbitmap.pix(y);
+ uint32_t *dst2 = &finalbitmap.pix(y, bitmap1.width() + BITMAP_SPACE);
+ uint32_t *dstdiff = &finalbitmap.pix(y, bitmap1.width() + BITMAP_SPACE + maxwidth + BITMAP_SPACE);
/* now iterate over columns */
- for (x = 0; x < maxwidth; x++)
+ for (int x = 0; x < maxwidth; x++)
{
int pix1 = -1, pix2 = -2;
@@ -171,16 +173,16 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img
/* write the final PNG */
filerr = util::core_file::open(outfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
- printf("Could not open %s (%d)\n", outfilename.c_str(), int(filerr));
+ printf("Could not open %s (%s)\n", outfilename.c_str(), filerr.message().c_str());
goto error;
}
- pngerr = png_write_bitmap(*file, nullptr, finalbitmap, 0, nullptr);
+ filerr = util::png_write_bitmap(*file, nullptr, finalbitmap, 0, nullptr);
file.reset();
- if (pngerr != PNGERR_NONE)
+ if (filerr)
{
- printf("Could not write %s (%d)\n", outfilename.c_str(), pngerr);
+ printf("Could not write %s (%s)\n", outfilename.c_str(), filerr.message().c_str());
goto error;
}
}
diff --git a/src/tools/regrep.cpp b/src/tools/regrep.cpp
index 91dcaecd518..316ef805f5a 100644
--- a/src/tools/regrep.cpp
+++ b/src/tools/regrep.cpp
@@ -6,14 +6,21 @@
****************************************************************************/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <new>
-#include <assert.h>
-#include "osdcore.h"
+#include "corefile.h"
+#include "corestr.h"
+#include "path.h"
#include "png.h"
+#include "strformat.h"
+
+#include "osdcomm.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <new>
/***************************************************************************
@@ -61,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];
};
@@ -148,15 +155,15 @@ static int CLIB_DECL compare_file(const void *file0ptr, const void *file1ptr);
static summary_file *sort_file_list(void);
/* HTML helpers */
-static util::core_file::ptr create_file_and_output_header(std::string &filename, std::string &templatefile, std::string &title);
-static void output_footer_and_close_file(util::core_file::ptr &&file, std::string &templatefile, std::string &title);
+static util::core_file::ptr create_file_and_output_header(std::string_view filename, std::string_view templatefile, const std::string &title);
+static void output_footer_and_close_file(util::write_stream::ptr &&file, std::string_view templatefile, const std::string &title);
/* report generators */
-static void output_report(std::string &dirname, std::string &tempheader, std::string &tempfooter, summary_file *filelist);
+static void output_report(std::string_view dirname, std::string_view tempheader, std::string_view tempfooter, summary_file *filelist);
static int compare_screenshots(summary_file *curfile);
-static int generate_png_diff(const summary_file *curfile, std::string &destdir, const char *destname);
-static void create_linked_file(std::string &dirname, const summary_file *curfile, const summary_file *prevfile, const summary_file *nextfile, const char *pngfile, std::string &tempheader, std::string &tempfooter);
-static void append_driver_list_table(const char *header, std::string &dirname, util::core_file &indexfile, const summary_file *listhead, std::string &tempheader, std::string &tempfooter);
+static int generate_png_diff(const summary_file *curfile, std::string_view destdir, std::string_view destname);
+static void create_linked_file(std::string_view dirname, const summary_file *curfile, const summary_file *prevfile, const summary_file *nextfile, std::string_view pngfile, std::string_view tempheader, std::string_view tempfooter);
+static void append_driver_list_table(const char *header, std::string_view dirname, util::core_file &indexfile, const summary_file *listhead, std::string_view tempheader, std::string_view tempfooter);
@@ -218,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;
@@ -235,7 +242,7 @@ int main(int argc, char *argv[])
/* read the template file into an astring */
std::string tempheader;
- if (util::core_file::load(tempfilename.c_str(), &buffer, bufsize) == osd_file::error::NONE)
+ if (!util::core_file::load(tempfilename, &buffer, bufsize))
{
tempheader.assign((const char *)buffer, bufsize);
free(buffer);
@@ -284,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)
@@ -292,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);
@@ -504,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;
@@ -560,18 +571,18 @@ static summary_file *sort_file_list(void)
HTML file with a standard header
-------------------------------------------------*/
-static util::core_file::ptr create_file_and_output_header(std::string &filename, std::string &templatefile, std::string &title)
+static util::core_file::ptr create_file_and_output_header(std::string_view filename, std::string_view templatefile, const std::string &title)
{
util::core_file::ptr file;
/* create the indexfile */
- if (util::core_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file) != osd_file::error::NONE)
+ if (util::core_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file))
return util::core_file::ptr();
/* print a header */
std::string modified(templatefile);
- strreplace(modified, "<!--TITLE-->", title.c_str());
- file->write(modified.c_str(), modified.length());
+ strreplace(modified, "<!--TITLE-->", title);
+ /*auto const [err, written] =*/ write(*file, modified.c_str(), modified.length()); // FIXME: check for errors
/* return the file */
return file;
@@ -583,11 +594,11 @@ static util::core_file::ptr create_file_and_output_header(std::string &filename,
standard footer to an HTML file and close it
-------------------------------------------------*/
-static void output_footer_and_close_file(util::core_file::ptr &&file, std::string &templatefile, std::string &title)
+static void output_footer_and_close_file(util::write_stream::ptr &&file, std::string_view templatefile, const std::string &title)
{
std::string modified(templatefile);
- strreplace(modified, "<!--TITLE-->", title.c_str());
- file->write(modified.c_str(), modified.length());
+ strreplace(modified, "<!--TITLE-->", title);
+ /*auto const [err, written] =*/ write(*file, modified.c_str(), modified.length()); // FIXME: check for errors
file.reset();
}
@@ -602,12 +613,11 @@ static void output_footer_and_close_file(util::core_file::ptr &&file, std::strin
report HTML files
-------------------------------------------------*/
-static void output_report(std::string &dirname, std::string &tempheader, std::string &tempfooter, summary_file *filelist)
+static void output_report(std::string_view dirname, std::string_view tempheader, std::string_view tempfooter, summary_file *filelist)
{
summary_file *buckethead[BUCKET_COUNT], **buckettailptr[BUCKET_COUNT];
summary_file *curfile;
std::string title("MAME Regressions");
- std::string tempname;
int listnum, bucknum;
util::core_file::ptr indexfile;
int count = 0, total;
@@ -686,7 +696,7 @@ static void output_report(std::string &dirname, std::string &tempheader, std::st
*buckettailptr[bucknum] = nullptr;
/* output header */
- tempname = string_format("%s" PATH_SEPARATOR "%s", dirname.c_str(), "index.html");
+ std::string tempname = util::path_concat(dirname, "index.html");
indexfile = create_file_and_output_header(tempname, tempheader, title);
if (!indexfile)
{
@@ -695,7 +705,7 @@ static void output_report(std::string &dirname, std::string &tempheader, std::st
}
/* iterate over buckets and output them */
- for (bucknum = 0; bucknum < ARRAY_LENGTH(bucket_output_order); bucknum++)
+ for (bucknum = 0; bucknum < std::size(bucket_output_order); bucknum++)
{
int curbucket = bucket_output_order[bucknum];
@@ -719,43 +729,43 @@ static void output_report(std::string &dirname, std::string &tempheader, std::st
static int compare_screenshots(summary_file *curfile)
{
bitmap_argb32 bitmaps[MAX_COMPARES];
- int unique[MAX_COMPARES];
+ int unique[MAX_COMPARES]{};
int numunique = 0;
- int listnum;
/* iterate over all files and load their bitmaps */
- for (listnum = 0; listnum < list_count; listnum++)
+ for (int listnum = 0; listnum < list_count; listnum++)
if (curfile->status[listnum] == STATUS_SUCCESS)
{
std::string fullname;
- osd_file::error filerr;
+ std::error_condition filerr;
util::core_file::ptr file;
/* get the filename for the image */
- fullname = string_format("%s" PATH_SEPARATOR "snap" PATH_SEPARATOR "%s" PATH_SEPARATOR "final.png", lists[listnum].dir, curfile->name);
+ fullname = util::path_concat(lists[listnum].dir, "snap", curfile->name, "final.png");
/* open the file */
filerr = util::core_file::open(fullname, OPEN_FLAG_READ, file);
/* if that failed, look in the old location */
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
/* get the filename for the image */
- fullname = string_format("%s" PATH_SEPARATOR "snap" PATH_SEPARATOR "_%s.png", lists[listnum].dir, curfile->name);
+ fullname = util::path_concat(lists[listnum].dir, "snap", util::string_format("_%s.png", curfile->name));
/* open the file */
filerr = util::core_file::open(fullname, OPEN_FLAG_READ, file);
}
/* if that worked, load the file */
- if (filerr == osd_file::error::NONE)
+ if (!filerr)
{
- png_read_bitmap(*file, bitmaps[listnum]);
+ util::png_read_bitmap(*file, bitmaps[listnum]);
file.reset();
}
}
/* now find all the different bitmap types */
+ int listnum;
for (listnum = 0; listnum < list_count; listnum++)
{
curfile->matchbitmap[listnum] = 0xff;
@@ -774,8 +784,8 @@ static int compare_screenshots(summary_file *curfile)
/* compare scanline by scanline */
for (int y = 0; y < this_bitmap.height() && !bitmaps_differ; y++)
{
- uint32_t *base = &base_bitmap.pix32(y);
- uint32_t *curr = &this_bitmap.pix32(y);
+ uint32_t const *base = &base_bitmap.pix(y);
+ uint32_t const *curr = &this_bitmap.pix(y);
/* scan the scanline */
int x;
@@ -826,41 +836,38 @@ static int compare_screenshots(summary_file *curfile)
side with a third set of differences
-------------------------------------------------*/
-static int generate_png_diff(const summary_file *curfile, std::string &destdir, const char *destname)
+static int generate_png_diff(const summary_file *curfile, std::string_view destdir, std::string_view destname)
{
bitmap_argb32 bitmaps[MAX_COMPARES];
std::string srcimgname;
std::string dstfilename;
- std::string tempname;
bitmap_argb32 finalbitmap;
int width, height, maxwidth;
int bitmapcount = 0;
- int listnum, bmnum;
util::core_file::ptr file;
- osd_file::error filerr;
- png_error pngerr;
+ std::error_condition filerr;
int error = -1;
int starty;
/* generate the common source filename */
- dstfilename = string_format("%s" PATH_SEPARATOR "%s", destdir.c_str(), destname);
- srcimgname = string_format("snap" PATH_SEPARATOR "%s" PATH_SEPARATOR "final.png", curfile->name);
+ dstfilename = util::path_concat(destdir, destname);
+ srcimgname = util::path_concat("snap", curfile->name, "final.png");
/* open and load all unique bitmaps */
- for (listnum = 0; listnum < list_count; listnum++)
+ for (int listnum = 0; listnum < list_count; listnum++)
if (curfile->matchbitmap[listnum] == listnum)
{
- tempname = string_format("%s" PATH_SEPARATOR "%s", lists[listnum].dir, srcimgname.c_str());
+ std::string tempname = util::path_concat(lists[listnum].dir, srcimgname);
/* open the source image */
filerr = util::core_file::open(tempname, OPEN_FLAG_READ, file);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
goto error;
/* load the source image */
- pngerr = png_read_bitmap(*file, bitmaps[bitmapcount++]);
+ filerr = util::png_read_bitmap(*file, bitmaps[bitmapcount++]);
file.reset();
- if (pngerr != PNGERR_NONE)
+ if (filerr)
goto error;
}
@@ -871,7 +878,7 @@ static int generate_png_diff(const summary_file *curfile, std::string &destdir,
/* determine the size of the final bitmap */
height = width = 0;
maxwidth = bitmaps[0].width();
- for (bmnum = 1; bmnum < bitmapcount; bmnum++)
+ for (int bmnum = 1; bmnum < bitmapcount; bmnum++)
{
int curwidth;
@@ -891,24 +898,23 @@ static int generate_png_diff(const summary_file *curfile, std::string &destdir,
/* now copy and compare each set of bitmaps */
starty = 0;
- for (bmnum = 1; bmnum < bitmapcount; bmnum++)
+ for (int bmnum = 1; bmnum < bitmapcount; bmnum++)
{
- bitmap_argb32 &bitmap1 = bitmaps[0];
- bitmap_argb32 &bitmap2 = bitmaps[bmnum];
+ bitmap_argb32 const &bitmap1 = bitmaps[0];
+ bitmap_argb32 const &bitmap2 = bitmaps[bmnum];
int curheight = std::max(bitmap1.height(), bitmap2.height());
- int x, y;
/* iterate over rows in these bitmaps */
- for (y = 0; y < curheight; y++)
+ for (int y = 0; y < curheight; y++)
{
- uint32_t *src1 = (y < bitmap1.height()) ? &bitmap1.pix32(y) : nullptr;
- uint32_t *src2 = (y < bitmap2.height()) ? &bitmap2.pix32(y) : nullptr;
- uint32_t *dst1 = &finalbitmap.pix32(starty + y, 0);
- uint32_t *dst2 = &finalbitmap.pix32(starty + y, bitmap1.width() + BITMAP_SPACE);
- uint32_t *dstdiff = &finalbitmap.pix32(starty + y, bitmap1.width() + BITMAP_SPACE + maxwidth + BITMAP_SPACE);
+ uint32_t const *src1 = (y < bitmap1.height()) ? &bitmap1.pix(y) : nullptr;
+ uint32_t const *src2 = (y < bitmap2.height()) ? &bitmap2.pix(y) : nullptr;
+ uint32_t *dst1 = &finalbitmap.pix(starty + y, 0);
+ uint32_t *dst2 = &finalbitmap.pix(starty + y, bitmap1.width() + BITMAP_SPACE);
+ uint32_t *dstdiff = &finalbitmap.pix(starty + y, bitmap1.width() + BITMAP_SPACE + maxwidth + BITMAP_SPACE);
/* now iterate over columns */
- for (x = 0; x < maxwidth; x++)
+ for (int x = 0; x < maxwidth; x++)
{
int pix1 = -1, pix2 = -2;
@@ -926,11 +932,11 @@ static int generate_png_diff(const summary_file *curfile, std::string &destdir,
/* write the final PNG */
filerr = util::core_file::open(dstfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
goto error;
- pngerr = png_write_bitmap(*file, nullptr, finalbitmap, 0, nullptr);
+ filerr = util::png_write_bitmap(*file, nullptr, finalbitmap, 0, nullptr);
file.reset();
- if (pngerr != PNGERR_NONE)
+ if (filerr)
goto error;
/* if we get here, we are error free */
@@ -948,7 +954,7 @@ error:
file between differing versions
-------------------------------------------------*/
-static void create_linked_file(std::string &dirname, const summary_file *curfile, const summary_file *prevfile, const summary_file *nextfile, const char *pngfile, std::string &tempheader, std::string &tempfooter)
+static void create_linked_file(std::string_view dirname, const summary_file *curfile, const summary_file *prevfile, const summary_file *nextfile, std::string_view pngfile, std::string_view tempheader, std::string_view tempfooter)
{
std::string linkname;
std::string filename;
@@ -957,11 +963,11 @@ static void create_linked_file(std::string &dirname, const summary_file *curfile
int listnum;
/* create the filename */
- filename = string_format("%s.html", curfile->name);
+ filename = util::string_format("%s.html", curfile->name);
/* output header */
- title = string_format("%s Regressions (%s)", curfile->name, curfile->source);
- linkname = string_format("%s" PATH_SEPARATOR "%s", dirname.c_str(), filename.c_str());
+ title = util::string_format("%s Regressions (%s)", curfile->name, curfile->source);
+ linkname = util::path_concat(dirname, filename);
linkfile = create_file_and_output_header(linkname, tempheader, title);
if (linkfile == nullptr)
{
@@ -993,7 +999,7 @@ static void create_linked_file(std::string &dirname, const summary_file *curfile
linkfile->printf("\n\t<h2>%s</h2>\n", lists[listnum].version);
linkfile->printf("\t<p>\n");
linkfile->printf("\t<b>Status:</b> %s\n", status_text[curfile->status[listnum]]);
- if (pngfile != nullptr)
+ if (!pngfile.empty())
imageindex = get_unique_index(curfile, listnum);
if (imageindex != -1)
linkfile->printf(" [%d]", imageindex);
@@ -1002,13 +1008,13 @@ static void create_linked_file(std::string &dirname, const summary_file *curfile
{
linkfile->printf("\t<p>\n");
linkfile->printf("\t<b>Errors:</b>\n");
- linkfile->printf("\t<pre>%s</pre>\n", curfile->text[listnum].c_str());
+ linkfile->printf("\t<pre>%s</pre>\n", curfile->text[listnum]);
linkfile->printf("\t</p>\n");
}
}
/* output link to the image */
- if (pngfile != nullptr)
+ if (!pngfile.empty())
{
linkfile->printf("\n\t<h2>Screenshot Comparisons</h2>\n");
linkfile->printf("\t<p>\n");
@@ -1026,7 +1032,7 @@ static void create_linked_file(std::string &dirname, const summary_file *curfile
of drivers from a list to an HTML file
-------------------------------------------------*/
-static void append_driver_list_table(const char *header, std::string &dirname, util::core_file &indexfile, const summary_file *listhead, std::string &tempheader, std::string &tempfooter)
+static void append_driver_list_table(const char *header, std::string_view dirname, util::core_file &indexfile, const summary_file *listhead, std::string_view tempheader, std::string_view tempfooter)
{
const summary_file *curfile, *prevfile;
int width = 100 / (2 + list_count);
@@ -1054,7 +1060,6 @@ static void append_driver_list_table(const char *header, std::string &dirname, u
for (prevfile = nullptr, curfile = listhead; curfile != nullptr; prevfile = curfile, curfile = curfile->next)
{
int rowspan = 0, uniqueshots = 0;
- char pngdiffname[40];
/* if this is the first entry in this source file, count how many rows we need to span */
if (prevfile == nullptr || strcmp(prevfile->source, curfile->source) != 0)
@@ -1068,19 +1073,19 @@ static void append_driver_list_table(const char *header, std::string &dirname, u
}
/* create screenshots if necessary */
- pngdiffname[0] = 0;
+ std::string pngdiffname;
for (listnum = 0; listnum < list_count; listnum++)
if (curfile->matchbitmap[listnum] == listnum)
uniqueshots++;
if (uniqueshots > 1)
{
- sprintf(pngdiffname, "compare_%s.png", curfile->name);
+ pngdiffname = util::string_format("compare_%s.png", curfile->name);
if (generate_png_diff(curfile, dirname, pngdiffname) != 0)
- pngdiffname[0] = 0;
+ pngdiffname.clear();
}
/* create a linked file */
- create_linked_file(dirname, curfile, prevfile, curfile->next, (pngdiffname[0] == 0) ? nullptr : pngdiffname, tempheader, tempfooter);
+ create_linked_file(dirname, curfile, prevfile, curfile->next, pngdiffname, tempheader, tempfooter);
/* create a row */
indexfile.printf("\t\t<tr>\n\t\t\t");
@@ -1091,7 +1096,7 @@ static void append_driver_list_table(const char *header, std::string &dirname, u
{
int unique_index = -1;
- if (pngdiffname[0] != 0)
+ if (!pngdiffname.empty())
unique_index = get_unique_index(curfile, listnum);
if (unique_index != -1)
indexfile.printf("<td><span style=\"%s\">&nbsp;&nbsp;&nbsp;</span> %s [<a href=\"%s\" target=\"blank\">%d</a>]</td>", status_color[curfile->status[listnum]], status_text[curfile->status[listnum]], pngdiffname, unique_index);
diff --git a/src/tools/romcmp.cpp b/src/tools/romcmp.cpp
index 6a781bc8c29..e3ae03c8f5e 100644
--- a/src/tools/romcmp.cpp
+++ b/src/tools/romcmp.cpp
@@ -8,25 +8,20 @@
***************************************************************************/
+#include "hash.h"
+#include "path.h"
#include "unzip.h"
-#include "osdcore.h"
+
+#include "osdfile.h"
#include "osdcomm.h"
-#include "hash.h"
-#include <stdarg.h>
-#include <stdlib.h>
+#include <cstdarg>
+#include <cstdlib>
+#include <memory>
#define MAX_FILES 1000
-#ifndef MAX_FILENAME_LEN
-#define MAX_FILENAME_LEN 255
-#endif
-
-#ifndef PATH_DELIM
-#define PATH_DELIM '/'
-#endif
-
/* compare modes when one file is twice as long as the other */
@@ -105,369 +100,381 @@ static void compatiblemodes(int mode,int *start,int *end)
struct fileinfo
{
- char name[MAX_FILENAME_LEN+1];
+ std::string name;
int size;
- unsigned char *buf; /* file is read in here */
+ std::unique_ptr<unsigned char []> buf; // file is read in here
int listed;
-};
-static fileinfo files[2][MAX_FILES];
-static float matchscore[MAX_FILES][MAX_FILES][TOTAL_MODES][TOTAL_MODES];
+ static constexpr bool is_ascii_char(int ch)
+ {
+ return (ch >= 0x20 && ch < 0x7f) || (ch == '\n') || (ch == '\r') || (ch == '\t');
+ }
-static bool is_ascii_char(int ch)
-{
- return (ch >= 0x20 && ch < 0x7f) || (ch == '\n') || (ch == '\r') || (ch == '\t');
-}
-static void checkintegrity(const fileinfo *file, int side)
-{
- if (file->buf == nullptr) return;
+ void checkintegrity(int side, bool all_hashes) const
+ {
+ if (!buf)
+ return;
- /* check for bad data lines */
- unsigned mask0 = 0x0000;
- unsigned mask1 = 0xffff;
+ if (all_hashes)
+ {
+ util::crc32_creator crc32;
+ util::sha1_creator sha1;
+ util::sum16_creator sum16;
+ crc32.append(buf.get(), size);
+ sha1.append(buf.get(), size);
+ sum16.append(buf.get(), size);
+ printf("%-23s %-23s [0x%x] CRC(%s) SHA1(%s) SUM(%s)\n",
+ (side & 1) ? name.c_str() : "",
+ (side & 2) ? name.c_str() : "",
+ size,
+ crc32.finish().as_string().c_str(),
+ sha1.finish().as_string().c_str(),
+ sum16.finish().as_string().c_str());
+ side = 0;
+ }
- bool is_ascii = true;
- for (unsigned i = 0; i < file->size; i += 2)
- {
- is_ascii = is_ascii && is_ascii_char(file->buf[i]);
- mask0 |= file->buf[i] << 8;
- mask1 &= (file->buf[i] << 8) | 0x00ff;
- if (i < file->size - 1)
+ // check for bad data lines
+ unsigned mask0 = 0x0000;
+ unsigned mask1 = 0xffff;
+
+ bool is_ascii = true;
+ for (unsigned i = 0; i < size; i += 2)
{
- is_ascii = is_ascii && is_ascii_char(file->buf[i+1]);
- mask0 |= file->buf[i+1];
- mask1 &= file->buf[i+1] | 0xff00;
+ is_ascii = is_ascii && is_ascii_char(buf[i]);
+ mask0 |= buf[i] << 8;
+ mask1 &= (buf[i] << 8) | 0x00ff;
+ if (i < size - 1)
+ {
+ is_ascii = is_ascii && is_ascii_char(buf[i+1]);
+ mask0 |= buf[i+1];
+ mask1 &= buf[i+1] | 0xff00;
+ }
+ if (mask0 == 0xffff && mask1 == 0x0000) break;
}
- if (mask0 == 0xffff && mask1 == 0x0000) break;
- }
- if (is_ascii && mask0 == 0x7f7f && mask1 == 0)
- {
- printf("%-23s %-23s ASCII TEXT FILE\n", side ? "" : file->name, side ? file->name : "");
- return;
- }
+ if (is_ascii && mask0 == 0x7f7f && mask1 == 0)
+ {
+ printf("%-23s %-23s ASCII TEXT FILE\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
+ return;
+ }
- if (mask0 != 0xffff || mask1 != 0x0000)
- {
- int fixedmask;
- int bits;
+ if (mask0 != 0xffff || mask1 != 0x0000)
+ {
+ int fixedmask;
+ int bits;
- fixedmask = (~mask0 | mask1) & 0xffff;
+ fixedmask = (~mask0 | mask1) & 0xffff;
- if (((mask0 >> 8) & 0xff) == (mask0 & 0xff) && ((mask1 >> 8) & 0xff) == (mask1 & 0xff))
- bits = 8;
- else bits = 16;
+ if (((mask0 >> 8) & 0xff) == (mask0 & 0xff) && ((mask1 >> 8) & 0xff) == (mask1 & 0xff))
+ bits = 8;
+ else bits = 16;
- printf("%-23s %-23s FIXED BITS (",side ? "" : file->name,side ? file->name : "");
- for (int i = 0; i < bits; i++)
- {
- if (~mask0 & 0x8000) printf("0");
- else if (mask1 & 0x8000) printf("1");
- else printf("x");
+ printf("%-23s %-23s FIXED BITS (", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
+ for (int i = 0; i < bits; i++)
+ {
+ if (~mask0 & 0x8000) printf("0");
+ else if (mask1 & 0x8000) printf("1");
+ else printf("x");
- mask0 <<= 1;
- mask1 <<= 1;
- }
- printf(")\n");
+ mask0 <<= 1;
+ mask1 <<= 1;
+ }
+ printf(")\n");
- /* if the file contains a fixed value, we don't need to do the other */
- /* validity checks */
- if (fixedmask == 0xffff || fixedmask == 0x00ff || fixedmask == 0xff00)
- return;
- }
+ /* if the file contains a fixed value, we don't need to do the other */
+ /* validity checks */
+ if (fixedmask == 0xffff || fixedmask == 0x00ff || fixedmask == 0xff00)
+ return;
+ }
- unsigned addrbit = 1;
- unsigned addrmirror = 0;
- while (addrbit <= file->size/2)
- {
- unsigned i = 0;
- for (i = 0; i < file->size; i++)
+ unsigned addrbit = 1;
+ unsigned addrmirror = 0;
+ while (addrbit <= size/2)
{
- if ((i ^ addrbit) < file->size && file->buf[i] != file->buf[i ^ addrbit]) break;
+ unsigned i = 0;
+ for (i = 0; i < size; i++)
+ {
+ if ((i ^ addrbit) < size && buf[i] != buf[i ^ addrbit]) break;
+ }
+
+ if (i == size)
+ addrmirror |= addrbit;
+
+ addrbit <<= 1;
}
- if (i == file->size)
- addrmirror |= addrbit;
+ if (addrmirror != 0)
+ {
+ if (addrmirror == size/2)
+ {
+ printf("%-23s %-23s 1ST AND 2ND HALF IDENTICAL\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
+ util::hash_collection hash;
+ hash.compute(buf.get(), size / 2);
+ printf("%-23s %-23s %s\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "", hash.attribute_string().c_str());
+ }
+ else
+ {
+ printf("%-23s %-23s BADADDR", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
+ for (int i = 0; i < 24; i++)
+ {
+ if (size <= (1<<(23-i))) printf(" ");
+ else if (addrmirror & 0x800000) printf("-");
+ else printf("x");
+ addrmirror <<= 1;
+ }
+ printf("\n");
+ }
+ return;
+ }
- addrbit <<= 1;
- }
+ unsigned sizemask = 1;
+ while (sizemask < size - 1)
+ sizemask = (sizemask << 1) | 1;
- if (addrmirror != 0)
- {
- if (addrmirror == file->size/2)
+ mask0 = 0x000000;
+ mask1 = sizemask;
+ for (unsigned i = 0; i < size; i++)
{
- printf("%-23s %-23s 1ST AND 2ND HALF IDENTICAL\n", side ? "" : file->name, side ? file->name : "");
- util::hash_collection hash;
- hash.begin();
- hash.buffer(file->buf, file->size / 2);
- hash.end();
- printf("%-23s %-23s %s\n", side ? "" : file->name, side ? file->name : "", hash.attribute_string().c_str());
+ if (buf[i] != 0xff)
+ {
+ mask0 |= i;
+ mask1 &= i;
+ if (mask0 == sizemask && mask1 == 0x00) break;
+ }
}
- else
+
+ if (mask0 != sizemask || mask1 != 0x00)
{
- printf("%-23s %-23s BADADDR",side ? "" : file->name,side ? file->name : "");
+ printf("%-23s %-23s ", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
for (int i = 0; i < 24; i++)
{
- if (file->size <= (1<<(23-i))) printf(" ");
- else if (addrmirror & 0x800000) printf("-");
+ if (size <= (1<<(23-i))) printf(" ");
+ else if (~mask0 & 0x800000) printf("1");
+ else if (mask1 & 0x800000) printf("0");
else printf("x");
- addrmirror <<= 1;
+ mask0 <<= 1;
+ mask1 <<= 1;
}
- printf("\n");
+ printf(" = 0xFF\n");
+
+ return;
}
- return;
- }
- unsigned sizemask = 1;
- while (sizemask < file->size - 1)
- sizemask = (sizemask << 1) | 1;
- mask0 = 0x000000;
- mask1 = sizemask;
- for (unsigned i = 0; i < file->size; i++)
- {
- if (file->buf[i] != 0xff)
+ mask0 = 0x000000;
+ mask1 = sizemask;
+ for (unsigned i = 0; i < size; i++)
{
- mask0 |= i;
- mask1 &= i;
- if (mask0 == sizemask && mask1 == 0x00) break;
+ if (buf[i] != 0x00)
+ {
+ mask0 |= i;
+ mask1 &= i;
+ if (mask0 == sizemask && mask1 == 0x00) break;
+ }
}
- }
- if (mask0 != sizemask || mask1 != 0x00)
- {
- printf("%-23s %-23s ",side ? "" : file->name,side ? file->name : "");
- for (int i = 0; i < 24; i++)
+ if (mask0 != sizemask || mask1 != 0x00)
{
- if (file->size <= (1<<(23-i))) printf(" ");
- else if (~mask0 & 0x800000) printf("1");
- else if (mask1 & 0x800000) printf("0");
- else printf("x");
- mask0 <<= 1;
- mask1 <<= 1;
- }
- printf(" = 0xFF\n");
-
- return;
- }
+ printf("%-23s %-23s ", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
+ for (int i = 0; i < 24; i++)
+ {
+ if (size <= (1<<(23-i))) printf(" ");
+ else if ((mask0 & 0x800000) == 0) printf("1");
+ else if (mask1 & 0x800000) printf("0");
+ else printf("x");
+ mask0 <<= 1;
+ mask1 <<= 1;
+ }
+ printf(" = 0x00\n");
+ return;
+ }
- mask0 = 0x000000;
- mask1 = sizemask;
- for (unsigned i = 0; i < file->size; i++)
- {
- if (file->buf[i] != 0x00)
+ mask0 = 0xff;
+ for (unsigned i = 0; i < size/4 && mask0 != 0x00; i++)
{
- mask0 |= i;
- mask1 &= i;
- if (mask0 == sizemask && mask1 == 0x00) break;
+ if (buf[ 2*i ] != 0x00) mask0 &= ~0x01;
+ if (buf[ 2*i ] != 0xff) mask0 &= ~0x02;
+ if (buf[ 2*i+1] != 0x00) mask0 &= ~0x04;
+ if (buf[ 2*i+1] != 0xff) mask0 &= ~0x08;
+ if (buf[size/2 + 2*i ] != 0x00) mask0 &= ~0x10;
+ if (buf[size/2 + 2*i ] != 0xff) mask0 &= ~0x20;
+ if (buf[size/2 + 2*i+1] != 0x00) mask0 &= ~0x40;
+ if (buf[size/2 + 2*i+1] != 0xff) mask0 &= ~0x80;
}
+
+ if (mask0 & 0x01) printf("%-23s %-23s 1ST HALF = 00xx\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
+ if (mask0 & 0x02) printf("%-23s %-23s 1ST HALF = FFxx\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
+ if (mask0 & 0x04) printf("%-23s %-23s 1ST HALF = xx00\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
+ if (mask0 & 0x08) printf("%-23s %-23s 1ST HALF = xxFF\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
+ if (mask0 & 0x10) printf("%-23s %-23s 2ND HALF = 00xx\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
+ if (mask0 & 0x20) printf("%-23s %-23s 2ND HALF = FFxx\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
+ if (mask0 & 0x40) printf("%-23s %-23s 2ND HALF = xx00\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
+ if (mask0 & 0x80) printf("%-23s %-23s 2ND HALF = xxFF\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "");
}
- if (mask0 != sizemask || mask1 != 0x00)
+ int usedbytes(int mode) const
{
- printf("%-23s %-23s ",side ? "" : file->name,side ? file->name : "");
- for (int i = 0; i < 24; i++)
+ switch (mode)
{
- if (file->size <= (1<<(23-i))) printf(" ");
- else if ((mask0 & 0x800000) == 0) printf("1");
- else if (mask1 & 0x800000) printf("0");
- else printf("x");
- mask0 <<= 1;
- mask1 <<= 1;
+ case MODE_A:
+ case MODE_NIB1:
+ case MODE_NIB2:
+ return size;
+ case MODE_12:
+ case MODE_22:
+ case MODE_E:
+ case MODE_O:
+ return size / 2;
+ case MODE_14:
+ case MODE_24:
+ case MODE_34:
+ case MODE_44:
+ case MODE_E12:
+ case MODE_O12:
+ case MODE_E22:
+ case MODE_O22:
+ return size / 4;
+ default:
+ return 0;
}
- printf(" = 0x00\n");
-
- return;
}
- mask0 = 0xff;
- for (unsigned i = 0; i < file->size/4 && mask0 != 0x00; i++)
+ void basemultmask(int mode, int &base, int &mult, int &mask) const
{
- if (file->buf[ 2*i ] != 0x00) mask0 &= ~0x01;
- if (file->buf[ 2*i ] != 0xff) mask0 &= ~0x02;
- if (file->buf[ 2*i+1] != 0x00) mask0 &= ~0x04;
- if (file->buf[ 2*i+1] != 0xff) mask0 &= ~0x08;
- if (file->buf[file->size/2 + 2*i ] != 0x00) mask0 &= ~0x10;
- if (file->buf[file->size/2 + 2*i ] != 0xff) mask0 &= ~0x20;
- if (file->buf[file->size/2 + 2*i+1] != 0x00) mask0 &= ~0x40;
- if (file->buf[file->size/2 + 2*i+1] != 0xff) mask0 &= ~0x80;
- }
-
- if (mask0 & 0x01) printf("%-23s %-23s 1ST HALF = 00xx\n",side ? "" : file->name,side ? file->name : "");
- if (mask0 & 0x02) printf("%-23s %-23s 1ST HALF = FFxx\n",side ? "" : file->name,side ? file->name : "");
- if (mask0 & 0x04) printf("%-23s %-23s 1ST HALF = xx00\n",side ? "" : file->name,side ? file->name : "");
- if (mask0 & 0x08) printf("%-23s %-23s 1ST HALF = xxFF\n",side ? "" : file->name,side ? file->name : "");
- if (mask0 & 0x10) printf("%-23s %-23s 2ND HALF = 00xx\n",side ? "" : file->name,side ? file->name : "");
- if (mask0 & 0x20) printf("%-23s %-23s 2ND HALF = FFxx\n",side ? "" : file->name,side ? file->name : "");
- if (mask0 & 0x40) printf("%-23s %-23s 2ND HALF = xx00\n",side ? "" : file->name,side ? file->name : "");
- if (mask0 & 0x80) printf("%-23s %-23s 2ND HALF = xxFF\n",side ? "" : file->name,side ? file->name : "");
-}
-
+ mult = 1;
+ if (mode >= MODE_E)
+ mult = 2;
-static int usedbytes(const fileinfo *file,int mode)
-{
- switch (mode)
- {
- case MODE_A:
- case MODE_NIB1:
- case MODE_NIB2:
- return file->size;
- case MODE_12:
- case MODE_22:
- case MODE_E:
- case MODE_O:
- return file->size / 2;
- case MODE_14:
- case MODE_24:
- case MODE_34:
- case MODE_44:
- case MODE_E12:
- case MODE_O12:
- case MODE_E22:
- case MODE_O22:
- return file->size / 4;
- default:
- return 0;
+ switch (mode)
+ {
+ case MODE_A:
+ case MODE_12:
+ case MODE_14:
+ case MODE_E:
+ case MODE_E12:
+ base = 0; mask = 0xff; break;
+ case MODE_NIB1:
+ base = 0; mask = 0x0f; break;
+ case MODE_NIB2:
+ base = 0; mask = 0xf0; break;
+ case MODE_O:
+ case MODE_O12:
+ base = 1; mask = 0xff; break;
+ case MODE_22:
+ case MODE_E22:
+ base = size / 2; mask = 0xff; break;
+ case MODE_O22:
+ base = 1 + size / 2; mask = 0xff; break;
+ case MODE_24:
+ base = size / 4; mask = 0xff; break;
+ case MODE_34:
+ base = 2*size / 4; mask = 0xff; break;
+ case MODE_44:
+ base = 3*size / 4; mask = 0xff; break;
+ }
}
-}
-static void basemultmask(const fileinfo *file,int mode,int *base,int *mult,int *mask)
-{
- *mult = 1;
- if (mode >= MODE_E) *mult = 2;
-
- switch (mode)
+ float compare(const fileinfo &file2, int mode1, int mode2) const
{
- case MODE_A:
- case MODE_12:
- case MODE_14:
- case MODE_E:
- case MODE_E12:
- *base = 0; *mask = 0xff; break;
- case MODE_NIB1:
- *base = 0; *mask = 0x0f; break;
- case MODE_NIB2:
- *base = 0; *mask = 0xf0; break;
- case MODE_O:
- case MODE_O12:
- *base = 1; *mask = 0xff; break;
- case MODE_22:
- case MODE_E22:
- *base = file->size / 2; *mask = 0xff; break;
- case MODE_O22:
- *base = 1 + file->size / 2; *mask = 0xff; break;
- case MODE_24:
- *base = file->size / 4; *mask = 0xff; break;
- case MODE_34:
- *base = 2*file->size / 4; *mask = 0xff; break;
- case MODE_44:
- *base = 3*file->size / 4; *mask = 0xff; break;
- }
-}
+ if (!buf || !file2.buf)
+ return 0.0;
-static float filecompare(const fileinfo *file1,const fileinfo *file2,int mode1,int mode2)
-{
- int i;
- int match = 0;
- int size1,size2;
- int base1=0,base2=0,mult1=0,mult2=0,mask1=0,mask2=0;
-
-
- if (file1->buf == nullptr || file2->buf == nullptr) return 0.0;
+ int const size1 = usedbytes(mode1);
+ int const size2 = file2.usedbytes(mode2);
- size1 = usedbytes(file1,mode1);
- size2 = usedbytes(file2,mode2);
+ if (size1 != size2)
+ return 0.0;
- if (size1 != size2) return 0.0;
+ int base1=0, base2=0, mult1=0, mult2=0, mask1=0, mask2=0;
+ basemultmask(mode1, base1, mult1, mask1);
+ file2.basemultmask(mode2, base2, mult2, mask2);
- basemultmask(file1,mode1,&base1,&mult1,&mask1);
- basemultmask(file2,mode2,&base2,&mult2,&mask2);
-
- if (mask1 == mask2)
- {
- if (mask1 == 0xff)
+ int match = 0;
+ if (mask1 == mask2)
{
- /* normal compare */
- for (i = 0;i < size1;i++)
- if (file1->buf[base1 + mult1 * i] == file2->buf[base2 + mult2 * i]) match++;
- }
- else
- {
- /* nibble compare, abort if other half is not empty */
- for (i = 0;i < size1;i++)
+ if (mask1 == 0xff)
+ {
+ // normal compare
+ for (int i = 0; i < size1; i++)
+ if (buf[base1 + mult1 * i] == file2.buf[base2 + mult2 * i]) match++;
+ }
+ else
{
- if (((file1->buf[base1 + mult1 * i] & ~mask1) != (0x00 & ~mask1) &&
- (file1->buf[base1 + mult1 * i] & ~mask1) != (0xff & ~mask1)) ||
- ((file2->buf[base1 + mult1 * i] & ~mask2) != (0x00 & ~mask2) &&
- (file2->buf[base1 + mult1 * i] & ~mask2) != (0xff & ~mask2)))
+ // nibble compare, abort if other half is not empty
+ for (int i = 0; i < size1; i++)
{
- match = 0;
- break;
+ if (((buf[base1 + mult1 * i] & ~mask1) != (0x00 & ~mask1) &&
+ (buf[base1 + mult1 * i] & ~mask1) != (0xff & ~mask1)) ||
+ ((file2.buf[base1 + mult1 * i] & ~mask2) != (0x00 & ~mask2) &&
+ (file2.buf[base1 + mult1 * i] & ~mask2) != (0xff & ~mask2)))
+ {
+ match = 0;
+ break;
+ }
+ if ((buf[base1 + mult1 * i] & mask1) == (file2.buf[base2 + mult2 * i] & mask2)) match++;
}
- if ((file1->buf[base1 + mult1 * i] & mask1) == (file2->buf[base2 + mult2 * i] & mask2)) match++;
}
}
- }
- return (float)match / size1;
-}
+ return float(match) / size1;
+ }
+ void readfile(const char *path)
+ {
+ std::string fullname(path ? path : "");
+ util::path_append(fullname, name);
-static void readfile(const char *path,fileinfo *file)
-{
- osd_file::error filerr;
- uint64_t filesize;
- uint32_t actual;
- char fullname[256];
- osd_file::ptr f;
+ buf.reset(new (std::nothrow) unsigned char [size]);
+ if (!buf)
+ {
+ printf("%s: out of memory!\n", name.c_str());
+ return;
+ }
- if (path)
- {
- char delim[2] = { PATH_DELIM, '\0' };
- strcpy(fullname,path);
- strcat(fullname,delim);
- }
- else fullname[0] = 0;
- strcat(fullname,file->name);
+ std::error_condition filerr;
+ osd_file::ptr f;
+ uint64_t filesize;
- if ((file->buf = (unsigned char *)malloc(file->size)) == nullptr)
- {
- printf("%s: out of memory!\n",file->name);
- return;
- }
+ filerr = osd_file::open(fullname, OPEN_FLAG_READ, f, filesize);
+ if (filerr)
+ {
+ printf("%s: error %s\n", fullname.c_str(), filerr.message().c_str());
+ return;
+ }
- filerr = osd_file::open(fullname, OPEN_FLAG_READ, f, filesize);
- if (filerr != osd_file::error::NONE)
- {
- printf("%s: error %d\n", fullname, int(filerr));
- return;
+ uint32_t actual;
+ filerr = f->read(buf.get(), 0, size, actual);
+ if (filerr)
+ {
+ printf("%s: error %s\n", fullname.c_str(), filerr.message().c_str());
+ return;
+ }
}
- filerr = f->read(file->buf, 0, file->size, actual);
- if (filerr != osd_file::error::NONE)
+ void free()
{
- printf("%s: error %d\n", fullname, int(filerr));
- return;
+ buf.reset();
}
-}
-
+};
-static void freefile(fileinfo *file)
-{
- free(file->buf);
- file->buf = nullptr;
-}
+static fileinfo files[2][MAX_FILES];
+static float matchscore[MAX_FILES][MAX_FILES][TOTAL_MODES][TOTAL_MODES];
-static void printname(const fileinfo *file1,const fileinfo *file2,float score,int mode1,int mode2)
+static void printname(const fileinfo *file1, const fileinfo *file2, float score, int mode1, int mode2)
{
- printf("%-12s %s %-12s %s ",file1 ? file1->name : "",modenames[mode1],file2 ? file2->name : "",modenames[mode2]);
+ printf(
+ "%-12s %s %-12s %s ",
+ file1 ? file1->name.c_str() : "",
+ modenames[mode1],
+ file2 ? file2->name.c_str() : "",
+ modenames[mode2]);
if (score == 0.0f) printf("NO MATCH\n");
else if (score == 1.0f) printf("IDENTICAL\n");
- else printf("%3.6f%%\n",(double) (score*100));
+ else printf("%3.6f%%\n", double(score*100));
}
@@ -483,24 +490,23 @@ static int load_files(int i, int *found, const char *path)
while ((d = dir->read()) != nullptr)
{
const char *d_name = d->name;
- char buf[255+1];
+ const std::string buf(util::path_concat(path, d_name)); // FIXME: is this even used for anything?
- sprintf(buf, "%s%c%s", path, PATH_DELIM, d_name);
if (d->type == osd::directory::entry::entry_type::FILE)
{
uint64_t size = d->size;
while (size && (size & 1) == 0) size >>= 1;
//if (size & ~1)
- // printf("%-23s %-23s ignored (not a ROM)\n",i ? "" : d_name,i ? d_name : "");
+ // printf("%-23s %-23s ignored (not a ROM)\n", i ? "" : d_name, i ? d_name : "");
//else
{
- strcpy(files[i][found[i]].name,d_name);
+ files[i][found[i]].name = d_name;
files[i][found[i]].size = d->size;
- readfile(path,&files[i][found[i]]);
+ files[i][found[i]].readfile(path);
files[i][found[i]].listed = 0;
if (found[i] >= MAX_FILES)
{
- printf("%s: max of %d files exceeded\n",path,MAX_FILES);
+ printf("%s: max of %d files exceeded\n", path, MAX_FILES);
break;
}
found[i]++;
@@ -509,15 +515,13 @@ static int load_files(int i, int *found, const char *path)
}
dir.reset();
}
-
- /* if not, try to open as a ZIP file */
else
{
+ /* if not, try to open as a ZIP file */
util::archive_file::ptr zip;
/* wasn't a directory, so try to open it as a zip file */
- if ((util::archive_file::open_zip(path, zip) != util::archive_file::error::NONE) &&
- (util::archive_file::open_7z(path, zip) != util::archive_file::error::NONE))
+ if (util::archive_file::open_zip(path, zip) && util::archive_file::open_7z(path, zip))
{
printf("Error, cannot open zip file '%s' !\n", path);
return 1;
@@ -539,26 +543,29 @@ static int load_files(int i, int *found, const char *path)
}
else
{
- fileinfo *file = &files[i][found[i]];
+ fileinfo &file = files[i][found[i]];
const char *delim = strrchr(zip->current_name().c_str(), '/');
if (delim)
- strcpy (file->name,delim+1);
+ file.name = delim + 1;
else
- strcpy(file->name,zip->current_name().c_str());
- file->size = zip->current_uncompressed_length();
- if ((file->buf = (unsigned char *)malloc(file->size)) == nullptr)
- printf("%s: out of memory!\n",file->name);
+ file.name = zip->current_name();
+ file.size = zip->current_uncompressed_length();
+ file.buf.reset(new (std::nothrow) unsigned char [file.size]);
+ if (!file.buf)
+ {
+ printf("%s: out of memory!\n", file.name.c_str());
+ }
else
{
- if (zip->decompress(file->buf, file->size) != util::archive_file::error::NONE)
+ if (zip->decompress(file.buf.get(), file.size))
{
- free(file->buf);
- file->buf = nullptr;
+ printf("%s: Decompression failed\n", file.name.c_str());
+ file.free();
}
}
- file->listed = 0;
+ file.listed = 0;
if (found[i] >= MAX_FILES)
{
printf("%s: max of %d files exceeded\n",path,MAX_FILES);
@@ -576,29 +583,31 @@ int CLIB_DECL main(int argc,char *argv[])
{
int err;
int total_modes = MODE_NIB2; /* by default, use only MODE_A, MODE_NIB1 and MODE_NIB2 */
+ bool all_hashes = false;
- if (argc >= 2 && strcmp(argv[1],"-d") == 0)
+ while (argc >= 2)
{
+ if (strcmp(argv[1], "-d") == 0)
+ total_modes = TOTAL_MODES;
+ else if (strcmp(argv[1], "-h") == 0)
+ all_hashes = true;
+ else
+ break;
argc--;
argv++;
- total_modes = TOTAL_MODES;
}
if (argc < 2)
{
- printf("usage: romcmp [-d] [dir1 | zip1] [dir2 | zip2]\n");
+ printf("usage: romcmp [-d] [-h] [dir1 | zip1] [dir2 | zip2]\n");
printf("-d enables a slower, more comprehensive comparison.\n");
+ printf("-h prints hashes and sums for all files.\n");
return 0;
}
{
- int found[2];
- int i,j,mode1,mode2;
- int besti,bestj;
-
-
- found[0] = found[1] = 0;
- for (i = 0;i < 2;i++)
+ int found[2] = { 0, 0 };
+ for (int i = 0; i < 2; i++)
{
if (argc > i+1)
{
@@ -613,28 +622,26 @@ int CLIB_DECL main(int argc,char *argv[])
else
printf("%d files\n",found[0]);
- for (i = 0;i < found[0];i++)
- {
- checkintegrity(&files[0][i],0);
- }
-
- for (j = 0;j < found[1];j++)
+ for (int i = 0; i < 2; i++)
{
- checkintegrity(&files[1][j],1);
+ for (int j = 0; j < found[i]; j++)
+ {
+ files[i][j].checkintegrity(1 << i, all_hashes);
+ }
}
if (argc < 3)
{
- /* find duplicates in one dir */
- for (i = 0;i < found[0];i++)
+ // find duplicates in one dir
+ for (int i = 0;i < found[0];i++)
{
- for (j = i+1;j < found[0];j++)
+ for (int j = i+1;j < found[0];j++)
{
- for (mode1 = 0;mode1 < total_modes;mode1++)
+ for (int mode1 = 0;mode1 < total_modes;mode1++)
{
- for (mode2 = 0;mode2 < total_modes;mode2++)
+ for (int mode2 = 0;mode2 < total_modes;mode2++)
{
- if (filecompare(&files[0][i],&files[0][j],mode1,mode2) == 1.0f)
+ if (files[0][i].compare(files[0][j],mode1,mode2) == 1.0f)
printname(&files[0][i],&files[0][j],1.0,mode1,mode2);
}
}
@@ -643,40 +650,38 @@ int CLIB_DECL main(int argc,char *argv[])
}
else
{
- /* compare two dirs */
- for (i = 0;i < found[0];i++)
+ // compare two dirs
+ for (int i = 0;i < found[0];i++)
{
- for (j = 0;j < found[1];j++)
+ for (int j = 0;j < found[1];j++)
{
fprintf(stderr,"%2d%%\r",100*(i*found[1]+j)/(found[0]*found[1]));
- for (mode1 = 0;mode1 < total_modes;mode1++)
+ for (int mode1 = 0;mode1 < total_modes;mode1++)
{
- for (mode2 = 0;mode2 < total_modes;mode2++)
+ for (int mode2 = 0;mode2 < total_modes;mode2++)
{
- matchscore[i][j][mode1][mode2] = filecompare(&files[0][i],&files[1][j],mode1,mode2);
+ matchscore[i][j][mode1][mode2] = files[0][i].compare(files[1][j],mode1,mode2);
}
}
}
}
fprintf(stderr," \r");
+ int besti;
do
{
- float bestscore;
- int bestmode1,bestmode2;
-
besti = -1;
- bestj = -1;
- bestscore = 0.0;
- bestmode1 = bestmode2 = -1;
+ int bestj = -1;
+ float bestscore = 0.0;
+ int bestmode1 = -1, bestmode2 = -1;
- for (mode1 = 0;mode1 < total_modes;mode1++)
+ for (int mode1 = 0;mode1 < total_modes;mode1++)
{
- for (mode2 = 0;mode2 < total_modes;mode2++)
+ for (int mode2 = 0;mode2 < total_modes;mode2++)
{
- for (i = 0;i < found[0];i++)
+ for (int i = 0;i < found[0];i++)
{
- for (j = 0;j < found[1];j++)
+ for (int j = 0;j < found[1];j++)
{
if (matchscore[i][j][mode1][mode2] > bestscore
|| (matchscore[i][j][mode1][mode2] == 1.0f && mode2 == 0 && bestmode2 > 0))
@@ -703,17 +708,17 @@ int CLIB_DECL main(int argc,char *argv[])
matchscore[besti][bestj][bestmode1][bestmode2] = 0.0;
/* remove all matches using the same sections with a worse score */
- for (j = 0;j < found[1];j++)
+ for (int j = 0;j < found[1];j++)
{
- for (mode2 = 0;mode2 < total_modes;mode2++)
+ for (int mode2 = 0;mode2 < total_modes;mode2++)
{
if (matchscore[besti][j][bestmode1][mode2] < bestscore)
matchscore[besti][j][bestmode1][mode2] = 0.0;
}
}
- for (i = 0;i < found[0];i++)
+ for (int i = 0;i < found[0];i++)
{
- for (mode1 = 0;mode1 < total_modes;mode1++)
+ for (int mode1 = 0;mode1 < total_modes;mode1++)
{
if (matchscore[i][bestj][mode1][bestmode2] < bestscore)
matchscore[i][bestj][mode1][bestmode2] = 0.0;
@@ -722,49 +727,50 @@ int CLIB_DECL main(int argc,char *argv[])
/* remove all matches using incompatible sections */
compatiblemodes(bestmode1,&start,&end);
- for (j = 0;j < found[1];j++)
+ for (int j = 0;j < found[1];j++)
{
- for (mode2 = 0;mode2 < total_modes;mode2++)
+ for (int mode2 = 0;mode2 < total_modes;mode2++)
{
- for (mode1 = 0;mode1 < start;mode1++)
+ for (int mode1 = 0;mode1 < start;mode1++)
matchscore[besti][j][mode1][mode2] = 0.0;
- for (mode1 = end+1;mode1 < total_modes;mode1++)
+ for (int mode1 = end+1;mode1 < total_modes;mode1++)
matchscore[besti][j][mode1][mode2] = 0.0;
}
}
compatiblemodes(bestmode2,&start,&end);
- for (i = 0;i < found[0];i++)
+ for (int i = 0;i < found[0];i++)
{
- for (mode1 = 0;mode1 < total_modes;mode1++)
+ for (int mode1 = 0;mode1 < total_modes;mode1++)
{
- for (mode2 = 0;mode2 < start;mode2++)
+ for (int mode2 = 0;mode2 < start;mode2++)
matchscore[i][bestj][mode1][mode2] = 0.0;
- for (mode2 = end+1;mode2 < total_modes;mode2++)
+ for (int mode2 = end+1;mode2 < total_modes;mode2++)
matchscore[i][bestj][mode1][mode2] = 0.0;
}
}
}
- } while (besti != -1);
+ }
+ while (besti != -1);
- for (i = 0;i < found[0];i++)
+ for (int i = 0;i < found[0];i++)
{
if (files[0][i].listed == 0) printname(&files[0][i],nullptr,0.0,0,0);
}
- for (i = 0;i < found[1];i++)
+ for (int i = 0;i < found[1];i++)
{
if (files[1][i].listed == 0) printname(nullptr,&files[1][i],0.0,0,0);
}
}
- for (i = 0;i < found[0];i++)
+ for (int i = 0;i < found[0];i++)
{
- freefile(&files[0][i]);
+ files[0][i].free();
}
- for (i = 0;i < found[1];i++)
+ for (int i = 0;i < found[1];i++)
{
- freefile(&files[1][i]);
+ files[1][i].free();
}
}
diff --git a/src/tools/split.cpp b/src/tools/split.cpp
index 4ef18b6ad06..5668e6e254c 100644
--- a/src/tools/split.cpp
+++ b/src/tools/split.cpp
@@ -8,17 +8,21 @@
****************************************************************************/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
#include "corefile.h"
#include "corestr.h"
-#include "sha1.h"
+#include "hashing.h"
+
+#include <cassert>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <tuple>
+#include <type_traits>
#define DEFAULT_SPLIT_SIZE 100
#define MAX_PARTS 1000
+#define SHA1_DIGEST_SIZE 20
@@ -32,24 +36,27 @@
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)
{
- char expanded[SHA1_DIGEST_SIZE * 2];
- uint8_t sha1digest[SHA1_DIGEST_SIZE];
- struct sha1_ctx sha1;
- int ch;
-
// compute the SHA1
- sha1_init(&sha1);
- sha1_update(&sha1, length, (const uint8_t *)data);
- sha1_final(&sha1);
- sha1_digest(&sha1, sizeof(sha1digest), sha1digest);
+ util::sha1_creator sha1;
+ 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
- for (ch = 0; ch < SHA1_DIGEST_SIZE; ch++)
+ char expanded[sizeof(sha1digest.m_raw) * 2];
+ for (int ch = 0; ch < sizeof(sha1digest.m_raw); ch++)
{
- expanded[ch * 2 + 0] = "0123456789ABCDEF"[sha1digest[ch] >> 4];
- expanded[ch * 2 + 1] = "0123456789ABCDEF"[sha1digest[ch] & 15];
+ expanded[ch * 2 + 0] = "0123456789ABCDEF"[sha1digest.m_raw[ch] >> 4];
+ expanded[ch * 2 + 1] = "0123456789ABCDEF"[sha1digest.m_raw[ch] & 15];
}
// copy it to the buffer
@@ -69,7 +76,7 @@ static int split_file(const char *filename, const char *basename, uint32_t split
void *splitbuffer = nullptr;
int index, partnum;
uint64_t totallength;
- osd_file::error filerr;
+ std::error_condition filerr;
int error = 1;
// convert split size to MB
@@ -82,20 +89,24 @@ static int split_file(const char *filename, const char *basename, uint32_t split
// open the file for read
filerr = util::core_file::open(filename, OPEN_FLAG_READ, infile);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
fprintf(stderr, "Fatal error: unable to open file '%s'\n", filename);
goto cleanup;
}
// get the total length
- totallength = infile->size();
+ if (infile->length(totallength))
+ {
+ fprintf(stderr, "Fatal error: unable to get length of file\n");
+ goto cleanup;
+ }
if (totallength < splitsize)
{
fprintf(stderr, "Fatal error: file is smaller than the split size\n");
goto cleanup;
}
- if ((uint64_t)splitsize * MAX_PARTS < totallength)
+ if ((uint64_t(splitsize) * MAX_PARTS) < totallength)
{
fprintf(stderr, "Fatal error: too many splits (maximum is %d)\n", MAX_PARTS);
goto cleanup;
@@ -120,7 +131,7 @@ static int split_file(const char *filename, const char *basename, uint32_t split
// create the split file
filerr = util::core_file::open(splitfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, splitfile);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
fprintf(stderr, "Fatal error: unable to create split file '%s'\n", splitfilename.c_str());
goto cleanup;
@@ -136,12 +147,11 @@ static int split_file(const char *filename, const char *basename, uint32_t split
// now iterate until done
for (partnum = 0; partnum < 1000; partnum++)
{
- uint32_t actual, length;
-
printf("Reading part %d...", partnum);
// read as much as we can from the file
- length = infile->read(splitbuffer, splitsize);
+ size_t length;
+ std::tie(filerr, length) = read(*infile, splitbuffer, splitsize); // FIXME check error return
if (length == 0)
break;
@@ -152,11 +162,11 @@ static int split_file(const char *filename, const char *basename, uint32_t split
splitfile->printf("hash=%s file=%s.%03d\n", computedhash.c_str(), basefilename.c_str(), partnum);
// compute the full filename for this guy
- outfilename = string_format("%s.%03d", basename, partnum);
+ outfilename = util::string_format("%s.%03d", basename, partnum);
// create it
filerr = util::core_file::open(outfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, outfile);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
printf("\n");
fprintf(stderr, "Fatal error: unable to create output file '%s'\n", outfilename.c_str());
@@ -166,8 +176,9 @@ static int split_file(const char *filename, const char *basename, uint32_t split
printf(" writing %s.%03d...", basefilename.c_str(), partnum);
// write the data
- actual = outfile->write(splitbuffer, length);
- if (actual != length)
+ size_t actual;
+ 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");
@@ -219,7 +230,7 @@ static int join_file(const char *filename, const char *outname, int write_output
std::string basepath;
util::core_file::ptr outfile, infile, splitfile;
void *splitbuffer = nullptr;
- osd_file::error filerr;
+ std::error_condition filerr;
uint32_t splitsize;
char buffer[256];
int error = 1;
@@ -227,7 +238,7 @@ static int join_file(const char *filename, const char *outname, int write_output
// open the file for read
filerr = util::core_file::open(filename, OPEN_FLAG_READ, splitfile);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
fprintf(stderr, "Fatal error: unable to open file '%s'\n", filename);
goto cleanup;
@@ -239,8 +250,7 @@ static int join_file(const char *filename, const char *outname, int write_output
fprintf(stderr, "Fatal error: corrupt or incomplete split file at line:\n%s\n", buffer);
goto cleanup;
}
- outfilename.assign(buffer + 10);
- strtrimspace(outfilename);
+ outfilename.assign(strtrimspace(buffer + 10));
// compute the base path
basepath.assign(filename);
@@ -268,7 +278,7 @@ static int join_file(const char *filename, const char *outname, int write_output
{
// don't overwrite the original!
filerr = util::core_file::open(outfilename, OPEN_FLAG_READ, outfile);
- if (filerr == osd_file::error::NONE)
+ if (!filerr)
{
outfile.reset();
fprintf(stderr, "Fatal error: output file '%s' already exists\n", outfilename.c_str());
@@ -277,7 +287,7 @@ static int join_file(const char *filename, const char *outname, int write_output
// open the output for write
filerr = util::core_file::open(outfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, outfile);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
fprintf(stderr, "Fatal error: unable to create file '%s'\n", outfilename.c_str());
goto cleanup;
@@ -289,8 +299,6 @@ static int join_file(const char *filename, const char *outname, int write_output
// now iterate through each file
while (splitfile->gets(buffer, sizeof(buffer)))
{
- uint32_t length, actual;
-
// make sure the hash and filename are in the right place
if (strncmp(buffer, "hash=", 5) != 0 || strncmp(buffer + 5 + SHA1_DIGEST_SIZE * 2, " file=", 6) != 0)
{
@@ -298,15 +306,15 @@ static int join_file(const char *filename, const char *outname, int write_output
goto cleanup;
}
expectedhash.assign(buffer + 5, SHA1_DIGEST_SIZE * 2);
- infilename.assign(buffer + 5 + SHA1_DIGEST_SIZE * 2 + 6);
- strtrimspace(infilename);
+ infilename.assign(strtrimspace(buffer + 5 + SHA1_DIGEST_SIZE * 2 + 6));
printf(" Reading file '%s'...", infilename.c_str());
// read the file's contents
infilename.insert(0, basepath);
+ size_t length;
filerr = util::core_file::load(infilename.c_str(), &splitbuffer, length);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
printf("\n");
fprintf(stderr, "Fatal error: unable to load file '%s'\n", infilename.c_str());
@@ -329,8 +337,9 @@ static int join_file(const char *filename, const char *outname, int write_output
{
printf(" writing...");
- actual = outfile->write(splitbuffer, length);
- if (actual != length)
+ size_t actual;
+ 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/src2html.cpp b/src/tools/src2html.cpp
deleted file mode 100644
index 32a21de065e..00000000000
--- a/src/tools/src2html.cpp
+++ /dev/null
@@ -1,905 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-/***************************************************************************
-
- MAME source code to HTML converter
-
-****************************************************************************
-
- Template file format:
-
- <html header>
- <!--PATH--> = insert path
- <!--CONTENT--> = insert content
- <html footer>
-
-***************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include "osdcore.h"
-#include "corestr.h"
-#include "corefile.h"
-
-
-/***************************************************************************
- CONSTANTS & DEFINES
-***************************************************************************/
-
-#define PREPROC_CLASS "preproc"
-#define KEYWORD_CLASS "keyword"
-#define CUSTOM_CLASS "custom"
-
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-enum file_type
-{
- FILE_TYPE_INVALID,
- FILE_TYPE_C,
- FILE_TYPE_MAKE,
- FILE_TYPE_XML,
- FILE_TYPE_TEXT
-};
-
-
-struct ext_to_type
-{
- const char * extension;
- file_type type;
-};
-
-
-struct token_entry
-{
- const char * token;
- const char * color;
-};
-
-
-struct include_path
-{
- include_path * next;
- std::string path;
-};
-
-
-struct list_entry
-{
- list_entry * next;
- std::string name;
-};
-
-
-
-/***************************************************************************
- GLOBAL VARIABLES
-***************************************************************************/
-
-static include_path *incpaths;
-
-static const ext_to_type extension_lookup[] =
-{
- { ".c", FILE_TYPE_C },
- { ".h", FILE_TYPE_C },
- { ".lst", FILE_TYPE_C },
- { ".mak", FILE_TYPE_MAKE },
- { "makefile", FILE_TYPE_MAKE },
- { ".lay", FILE_TYPE_XML },
- { ".xml", FILE_TYPE_XML },
- { ".txt", FILE_TYPE_TEXT },
-};
-
-
-static const token_entry dummy_token_table[] =
-{
- { nullptr, KEYWORD_CLASS }
-};
-
-
-static const token_entry c_token_table[] =
-{
- { "#define", PREPROC_CLASS },
- { "#elif", PREPROC_CLASS },
- { "#else", PREPROC_CLASS },
- { "#endif", PREPROC_CLASS },
- { "#error", PREPROC_CLASS },
- { "#if", PREPROC_CLASS },
- { "#ifdef", PREPROC_CLASS },
- { "#ifndef", PREPROC_CLASS },
- { "#include", PREPROC_CLASS },
- { "#line", PREPROC_CLASS },
- { "#pragma", PREPROC_CLASS },
- { "#undef", PREPROC_CLASS },
-
- { "auto", KEYWORD_CLASS },
- { "bool", KEYWORD_CLASS },
- { "break", KEYWORD_CLASS },
- { "case", KEYWORD_CLASS },
- { "catch", KEYWORD_CLASS },
- { "char", KEYWORD_CLASS },
- { "class", KEYWORD_CLASS },
- { "const", KEYWORD_CLASS },
- { "const_cast", KEYWORD_CLASS },
- { "continue", KEYWORD_CLASS },
- { "default", KEYWORD_CLASS },
- { "delete", KEYWORD_CLASS },
- { "do", KEYWORD_CLASS },
- { "double", KEYWORD_CLASS },
- { "dynamic_cast", KEYWORD_CLASS },
- { "else", KEYWORD_CLASS },
- { "enum", KEYWORD_CLASS },
- { "explicit", KEYWORD_CLASS },
- { "export", KEYWORD_CLASS },
- { "extern", KEYWORD_CLASS },
- { "false", KEYWORD_CLASS },
- { "float", KEYWORD_CLASS },
- { "for", KEYWORD_CLASS },
- { "friend", KEYWORD_CLASS },
- { "goto", KEYWORD_CLASS },
- { "if", KEYWORD_CLASS },
- { "inline", KEYWORD_CLASS },
- { "int", KEYWORD_CLASS },
- { "long", KEYWORD_CLASS },
- { "mutable", KEYWORD_CLASS },
- { "namespace", KEYWORD_CLASS },
- { "new", KEYWORD_CLASS },
- { "operator", KEYWORD_CLASS },
- { "private", KEYWORD_CLASS },
- { "protected", KEYWORD_CLASS },
- { "public", KEYWORD_CLASS },
- { "register", KEYWORD_CLASS },
- { "reinterpret_cast", KEYWORD_CLASS },
- { "return", KEYWORD_CLASS },
- { "short", KEYWORD_CLASS },
- { "signed", KEYWORD_CLASS },
- { "sizeof", KEYWORD_CLASS },
- { "static", KEYWORD_CLASS },
- { "static_cast", KEYWORD_CLASS },
- { "struct", KEYWORD_CLASS },
- { "switch", KEYWORD_CLASS },
- { "template", KEYWORD_CLASS },
- { "this", KEYWORD_CLASS },
- { "throw", KEYWORD_CLASS },
- { "true", KEYWORD_CLASS },
- { "try", KEYWORD_CLASS },
- { "typedef", KEYWORD_CLASS },
- { "typeid", KEYWORD_CLASS },
- { "typename", KEYWORD_CLASS },
- { "union", KEYWORD_CLASS },
- { "unsigned", KEYWORD_CLASS },
- { "virtual", KEYWORD_CLASS },
- { "void", KEYWORD_CLASS },
- { "volatile", KEYWORD_CLASS },
- { "wchar_t", KEYWORD_CLASS },
- { "while", KEYWORD_CLASS },
-
-/*
- { "INLINE", CUSTOM_CLASS },
- { "int8_t", CUSTOM_CLASS },
- { "uint8_t", CUSTOM_CLASS },
- { "int16_t", CUSTOM_CLASS },
- { "uint16_t", CUSTOM_CLASS },
- { "int32_t", CUSTOM_CLASS },
- { "uint32_t", CUSTOM_CLASS },
- { "int64_t", CUSTOM_CLASS },
- { "uint64_t", CUSTOM_CLASS },
- { "ARRAY_LENGTH", CUSTOM_CLASS },
-*/
- { nullptr, KEYWORD_CLASS }
-};
-
-
-
-/***************************************************************************
- PROTOTYPES
-***************************************************************************/
-
-// core output functions
-static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std::string &dstdir, std::string &tempheader, std::string &tempfooter);
-static int output_file(file_type type, int srcrootlen, int dstrootlen, std::string &srcfile, std::string &dstfile, bool link_to_file, std::string &tempheader, std::string &tempfooter);
-
-// HTML helpers
-static util::core_file::ptr create_file_and_output_header(std::string &filename, std::string &templatefile, std::string &path);
-static void output_footer_and_close_file(util::core_file::ptr &&file, std::string &templatefile, std::string &path);
-
-// path helpers
-static std::string &normalized_subpath(std::string &dest, std::string &path, int start);
-static void output_path_as_links(util::core_file &file, std::string &path, bool end_is_directory, bool link_to_file);
-static bool find_include_file(std::string &srcincpath, int srcrootlen, int dstrootlen, std::string &srcfile, std::string &dstfile, std::string &filename);
-
-
-
-/***************************************************************************
- MAIN
-***************************************************************************/
-
-/*-------------------------------------------------
- main - main entry point
--------------------------------------------------*/
-
-void usage(const char *argv0)
-{
- fprintf(stderr, "Usage:\n%s <srcroot> <destroot> <template.html> [-Iincpath [-Iincpath [...]]]\n", argv0);
- exit(1);
-}
-
-int main(int argc, char *argv[])
-{
- // loop over arguments
- include_path **incpathhead = &incpaths;
- std::string srcdir, dstdir, tempfilename, tempheader, tempfooter;
- int unadorned = 0;
- for (int argnum = 1; argnum < argc; argnum++)
- {
- char *arg = argv[argnum];
-
- // include path?
- if (arg[0] == '-' && arg[1] == 'I')
- {
- *incpathhead = new include_path;
- if (*incpathhead != nullptr)
- {
- (*incpathhead)->next = nullptr;
- strreplacechr((*incpathhead)->path.assign(&arg[2]), '/', PATH_SEPARATOR[0]);
- incpathhead = &(*incpathhead)->next;
- }
- }
-
- // other parameter
- else if (arg[0] != '-' && unadorned == 0)
- {
- srcdir.assign(arg);
- unadorned++;
- }
- else if (arg[0] != '-' && unadorned == 1)
- {
- dstdir.assign(arg);
- unadorned++;
- }
- else if (arg[0] != '-' && unadorned == 2)
- {
- tempfilename.assign(arg);
- unadorned++;
- }
- else
- usage(argv[0]);
- }
-
- // make sure we got 3 parameters
- if (srcdir.length() == 0 || dstdir.length() == 0 || tempfilename.length() == 0)
- usage(argv[0]);
-
- // read the template file into an std::string
- uint32_t bufsize;
- void *buffer;
- if (util::core_file::load(tempfilename.c_str(), &buffer, bufsize) == osd_file::error::NONE)
- {
- tempheader.assign((const char *)buffer, bufsize);
- free(buffer);
- }
-
- // verify the template
- if (tempheader.length() == 0)
- {
- fprintf(stderr, "Unable to read template file\n");
- return 1;
- }
- int result = tempheader.find("<!--CONTENT-->");
- if (result == -1)
- {
- fprintf(stderr, "Template is missing a <!--CONTENT--> marker\n");
- return 1;
- }
- tempfooter.assign(tempheader).erase(0, result + 14);
- tempheader.erase(result);
-
- // recurse over subdirectories
- return recurse_dir(srcdir.length(), dstdir.length(), srcdir, dstdir, tempheader, tempfooter);
-}
-
-
-
-/***************************************************************************
- CORE OUTPUT FUNCTIONS
-***************************************************************************/
-
-static int compare_list_entries(const void *p1, const void *p2)
-{
- const list_entry *entry1 = *(const list_entry **)p1;
- const list_entry *entry2 = *(const list_entry **)p2;
- return entry1->name.compare(entry2->name);
-}
-
-
-/*-------------------------------------------------
- recurse_dir - recurse through a directory
--------------------------------------------------*/
-
-static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std::string &dstdir, std::string &tempheader, std::string &tempfooter)
-{
- static const osd::directory::entry::entry_type typelist[] = { osd::directory::entry::entry_type::DIR, osd::directory::entry::entry_type::FILE };
-
- // extract a normalized subpath
- std::string srcdir_subpath;
- normalized_subpath(srcdir_subpath, srcdir, srcrootlen + 1);
-
- // create an index file
- std::string indexname;
- indexname = string_format("%s%c%s", dstdir.c_str(), PATH_SEPARATOR[0], "index.html");
- util::core_file::ptr indexfile = create_file_and_output_header(indexname, tempheader, srcdir_subpath);
-
- // output the directory navigation
- indexfile->printf("<h3>Viewing Directory: ");
- output_path_as_links(*indexfile, srcdir_subpath, true, false);
- indexfile->printf("</h3>");
-
- // iterate first over directories, then over files
- int result = 0;
- for (int entindex = 0; entindex < ARRAY_LENGTH(typelist) && result == 0; entindex++)
- {
- auto entry_type = typelist[entindex];
-
- // open the directory and iterate through it
- auto dir = osd::directory::open(srcdir.c_str());
- if (dir == nullptr)
- {
- result = 1;
- break;
- }
-
- // build up the list of files
- const osd::directory::entry *entry;
- int found = 0;
- list_entry *list = nullptr;
- while ((entry = dir->read()) != nullptr)
- if (entry->type == entry_type && entry->name[0] != '.')
- {
- auto lentry = new list_entry;
- lentry->name.assign(entry->name);
- lentry->next = list;
- list = lentry;
- found++;
- }
-
- // close the directory
- dir.reset();
-
- // skip if nothing found
- if (found == 0)
- continue;
-
- // allocate memory for sorting
- auto listarray = new list_entry *[found];
- found = 0;
- for (list_entry *curlist = list; curlist != nullptr; curlist = curlist->next)
- listarray[found++] = curlist;
-
- // sort the list
- qsort(listarray, found, sizeof(listarray[0]), compare_list_entries);
-
- // rebuild the list
- list = nullptr;
- while (--found >= 0)
- {
- listarray[found]->next = list;
- list = listarray[found];
- }
- delete[] listarray;
-
- // iterate through each file
- for (list_entry *curlist = list; curlist != nullptr && result == 0; curlist = curlist->next)
- {
- // add a header
- if (curlist == list)
- indexfile->printf("\t<h2>%s</h2>\n\t<ul>\n", (entry_type == osd::directory::entry::entry_type::DIR) ? "Directories" : "Files");
-
- // build the source filename
- std::string srcfile;
- srcfile = string_format("%s%c%s", srcdir.c_str(), PATH_SEPARATOR[0], curlist->name.c_str());
-
- // if we have a file, output it
- std::string dstfile;
- if (entry_type == osd::directory::entry::entry_type::FILE)
- {
- // make sure we care, first
- file_type type = FILE_TYPE_INVALID;
- for (auto & elem : extension_lookup)
- if (core_filename_ends_with(curlist->name, elem.extension))
- {
- type = elem.type;
- break;
- }
-
- // if we got a valid file, process it
- if (type != FILE_TYPE_INVALID)
- {
- dstfile = string_format("%s%c%s.html", dstdir.c_str(), PATH_SEPARATOR[0], curlist->name.c_str());
- if (indexfile != nullptr)
- indexfile->printf("\t<li><a href=\"%s.html\">%s</a></li>\n", curlist->name.c_str(), curlist->name.c_str());
- result = output_file(type, srcrootlen, dstrootlen, srcfile, dstfile, srcdir.compare(dstdir) == 0, tempheader, tempfooter);
- }
- }
-
- // if we have a directory, recurse
- else
- {
- dstfile = string_format("%s%c%s", dstdir.c_str(), PATH_SEPARATOR[0], curlist->name.c_str());
- if (indexfile != nullptr)
- indexfile->printf("\t<li><a href=\"%s/index.html\">%s/</a></li>\n", curlist->name.c_str(), curlist->name.c_str());
- result = recurse_dir(srcrootlen, dstrootlen, srcfile, dstfile, tempheader, tempfooter);
- }
- }
-
- // close the list if we found some stuff
- if (list != nullptr)
- indexfile->printf("\t</ul>\n");
-
- // free all the allocated entries
- while (list != nullptr)
- {
- list_entry *next = list->next;
- delete list;
- list = next;
- }
- }
-
- if (indexfile != nullptr)
- output_footer_and_close_file(std::move(indexfile), tempfooter, srcdir_subpath);
- return result;
-}
-
-
-/*-------------------------------------------------
- output_file - output a file, converting to
- HTML
--------------------------------------------------*/
-
-static int output_file(file_type type, int srcrootlen, int dstrootlen, std::string &srcfile, std::string &dstfile, bool link_to_file, std::string &tempheader, std::string &tempfooter)
-{
- // extract a normalized subpath
- std::string srcfile_subpath;
- normalized_subpath(srcfile_subpath, srcfile, srcrootlen + 1);
-
- fprintf(stderr, "Processing %s\n", srcfile_subpath.c_str());
-
- // set some defaults
- bool color_quotes = false;
- const char *comment_start = "";
- const char *comment_start_esc = "";
- const char *comment_end = "";
- const char *comment_end_esc = "";
- const char *comment_inline = "";
- const char *comment_inline_esc = "";
- const char *token_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_#";
- const token_entry *token_table = dummy_token_table;
-
- // based on the file type, set the comment info
- switch (type)
- {
- case FILE_TYPE_C:
- color_quotes = true;
- comment_start = comment_start_esc = "/*";
- comment_end = comment_end_esc = "*/";
- comment_inline = comment_inline_esc = "//";
- token_table = c_token_table;
- break;
-
- case FILE_TYPE_MAKE:
- color_quotes = true;
- comment_inline = comment_inline_esc = "#";
- break;
-
- case FILE_TYPE_XML:
- color_quotes = true;
- comment_start = "<!--";
- comment_start_esc = "&lt;!--";
- comment_end = "-->";
- comment_end_esc = "--&gt;";
- break;
-
- default:
- case FILE_TYPE_TEXT:
- break;
- }
-
- // make the token lookup table
- bool is_token[256];
- memset(is_token, 0, sizeof(is_token));
- for (int toknum = 0; token_chars[toknum] != 0; toknum++)
- is_token[(uint8_t)token_chars[toknum]] = true;
-
- // open the source file
- util::core_file::ptr src;
- if (util::core_file::open(srcfile, OPEN_FLAG_READ, src) != osd_file::error::NONE)
- {
- fprintf(stderr, "Unable to read file '%s'\n", srcfile.c_str());
- return 1;
- }
-
- // open the output file
- util::core_file::ptr dst = create_file_and_output_header(dstfile, tempheader, srcfile_subpath);
- if (dst == nullptr)
- {
- fprintf(stderr, "Unable to write file '%s'\n", dstfile.c_str());
- return 1;
- }
-
- // output the directory navigation
- dst->printf("<h3>Viewing File: ");
- output_path_as_links(*dst, srcfile_subpath, false, link_to_file);
- dst->printf("</h3>");
-
- // start with some tags
- dst->printf("\t<pre class=\"source\">\n");
-
- // iterate over lines in the source file
- int linenum = 1;
- bool in_comment = false;
- char srcline[4096];
- std::ostringstream dstline;
- while (src->gets(srcline, ARRAY_LENGTH(srcline)) != nullptr)
- {
- // start with the line number
- dstline.str("");
- util::stream_format(dstline, "<span class=\"linenum\">%5d</span>&nbsp;&nbsp;", linenum++);
-
- // iterate over characters in the source line
- bool escape = false;
- bool in_quotes = false;
- bool in_inline_comment = false;
- bool last_token_was_include = false;
- bool last_was_token = false;
- bool quotes_are_linked = false;
- uint8_t curquote = 0;
- int curcol = 0;
- for (char *srcptr = srcline; *srcptr != 0; )
- {
- uint8_t ch = *srcptr++;
-
- // track whether or not we are within an extended (C-style) comment
- if (!in_quotes && !in_inline_comment)
- {
- if (!in_comment && ch == comment_start[0] && strncmp(srcptr - 1, comment_start, strlen(comment_start)) == 0)
- {
- util::stream_format(dstline, "<span class=\"comment\">%s", comment_start_esc);
- curcol += strlen(comment_start);
- srcptr += strlen(comment_start) - 1;
- ch = 0;
- in_comment = true;
- }
- else if (in_comment && ch == comment_end[0] && strncmp(srcptr - 1, comment_end, strlen(comment_end)) == 0)
- {
- util::stream_format(dstline, "%s</span>", comment_end_esc);
- curcol += strlen(comment_end);
- srcptr += strlen(comment_end) - 1;
- ch = 0;
- in_comment = false;
- }
- }
-
- // track whether or not we are within an inline (C++-style) comment
- if (!in_quotes && !in_comment && !in_inline_comment && ch == comment_inline[0] && strncmp(srcptr - 1, comment_inline, strlen(comment_inline)) == 0)
- {
- util::stream_format(dstline, "<span class=\"comment\">%s", comment_inline_esc);
- curcol += strlen(comment_inline);
- srcptr += strlen(comment_inline) - 1;
- ch = 0;
- in_inline_comment = true;
- }
-
- // if this is the start of a new token, see if we want to color it
- if (!in_quotes && !in_comment && !in_inline_comment && !last_was_token && is_token[ch])
- {
- const token_entry *curtoken;
- char *temp = srcptr;
- int toklength;
-
- // find the end of the token
- while (*temp != 0 && is_token[(uint8_t)*temp])
- temp++;
- toklength = temp - (srcptr - 1);
-
- // scan the token table
- last_token_was_include = false;
- for (curtoken = token_table; curtoken->token != nullptr; curtoken++)
- if (strncmp(srcptr - 1, curtoken->token, toklength) == 0 && strlen(curtoken->token) == toklength)
- {
- util::stream_format(dstline, "<span class=\"%s\">%s</span>", curtoken->color, curtoken->token);
- curcol += strlen(curtoken->token);
- srcptr += strlen(curtoken->token) - 1;
- ch = 0;
-
- // look for include tokens specially
- if (type == FILE_TYPE_C && strcmp(curtoken->token, "#include") == 0)
- last_token_was_include = true;
- break;
- }
- }
- last_was_token = is_token[ch];
-
- // if we hit a tab, expand it
- if (ch == 0x09)
- {
- // compute how many spaces
- int spaces = 4 - curcol % 4;
- while (spaces--)
- {
- dstline.put(' ');
- curcol++;
- }
- }
-
- // otherwise, copy the source character
- else if (ch != 0x0a && ch != 0x0d && ch != 0)
- {
- // track opening quotes
- if (!in_comment && !in_inline_comment && !in_quotes && (ch == '"' || ch == '\''))
- {
- if (color_quotes)
- util::stream_format(dstline, "<span class=\"string\">%c", ch);
- else
- dstline.put(ch);
- in_quotes = true;
- curquote = ch;
-
- // handle includes
- if (last_token_was_include)
- {
- char *endquote = strchr(srcptr, ch);
- if (endquote != nullptr)
- {
- std::string filename(srcptr, endquote - srcptr);
- std::string target;
- if (find_include_file(target, srcrootlen, dstrootlen, srcfile, dstfile, filename))
- {
- util::stream_format(dstline, "<a href=\"%s\">", target.c_str());
- quotes_are_linked = true;
- }
- }
- }
- }
-
- // track closing quotes
- else if (!in_comment && !in_inline_comment && in_quotes && (ch == curquote) && !escape)
- {
- if (quotes_are_linked)
- dstline << "</a>";
- if (color_quotes)
- util::stream_format(dstline, "%c</span>", ch);
- else
- dstline.put(ch);
- in_quotes = false;
- curquote = 0;
- quotes_are_linked = false;
- }
-
- // else just output the current character
- else if (ch == '&')
- dstline << "&amp;";
- else if (ch == '<')
- dstline << "&lt;";
- else if (ch == '>')
- dstline << "&gt;";
- else
- dstline.put(ch);
- curcol++;
- }
-
- // Update escape state
- if (in_quotes)
- escape = (ch == '\\' && type == FILE_TYPE_C) ? !escape : false;
- }
-
- // finish inline comments
- if (in_inline_comment)
- {
- dstline << "</span>";
- in_inline_comment = false;
- }
-
- // append a break and move on
- dstline.put('\n');
- dst->puts(dstline.str().c_str());
- }
-
- // close tags
- dst->printf("\t</pre>\n");
-
- // close the file
- output_footer_and_close_file(std::move(dst), tempfooter, srcfile_subpath);
- return 0;
-}
-
-
-
-/***************************************************************************
- HTML OUTPUT HELPERS
-***************************************************************************/
-
-/*-------------------------------------------------
- create_file_and_output_header - create a new
- HTML file with a standard header
--------------------------------------------------*/
-
-static util::core_file::ptr create_file_and_output_header(std::string &filename, std::string &templatefile, std::string &path)
-{
- // create the indexfile
- util::core_file::ptr file;
- if (util::core_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file) != osd_file::error::NONE)
- return util::core_file::ptr();
-
- // print a header
- std::string modified(templatefile);
- strreplace(modified, "<!--PATH-->", path.c_str());
- file->write(modified.c_str(), modified.length());
-
- // return the file
- return file;
-}
-
-
-/*-------------------------------------------------
- output_footer_and_close_file - write a
- standard footer to an HTML file and close it
--------------------------------------------------*/
-
-static void output_footer_and_close_file(util::core_file::ptr &&file, std::string &templatefile, std::string &path)
-{
- std::string modified(templatefile);
- strreplace(modified, "<!--PATH-->", path.c_str());
- file->write(modified.c_str(), modified.length());
- file.reset();
-}
-
-
-
-/***************************************************************************
- HTML OUTPUT HELPERS
-***************************************************************************/
-
-/*-------------------------------------------------
- normalized_subpath - normalize a path to
- forward slashes and extract a subpath
--------------------------------------------------*/
-
-static std::string &normalized_subpath(std::string &dest, std::string &path, int start)
-{
- strreplacechr(dest.assign(path.substr(start, -1)),PATH_SEPARATOR[0], '/');
- return dest;
-}
-
-
-/*-------------------------------------------------
- output_path_as_links - output a path as a
- series of links
--------------------------------------------------*/
-
-static void output_path_as_links(util::core_file &file, std::string &path, bool end_is_directory, bool link_to_file)
-{
- // first count how deep we are
- int srcdepth = 0;
- for (int slashindex = path.find_first_of('/'); slashindex != -1; slashindex = path.find_first_of('/', slashindex + 1))
- srcdepth++;
- if (end_is_directory)
- srcdepth++;
-
- // output a link to the root
- file.printf("<a href=\"");
- for (int depth = 0; depth < srcdepth; depth++)
- file.printf("../");
- file.printf("index.html\">&lt;root&gt;</a>/");
-
- // now output links to each path up the chain
- int curdepth = 0;
- int lastslash = 0;
- for (int slashindex = path.find_first_of('/', lastslash); slashindex != -1; slashindex = path.find_first_of('/', lastslash))
- {
- std::string substr(path, lastslash, slashindex - lastslash);
-
- curdepth++;
- file.printf("<a href=\"");
- for (int depth = curdepth; depth < srcdepth; depth++)
- file.printf("../");
- file.printf("index.html\">%s</a>/", substr.c_str());
-
- lastslash = slashindex + 1;
- }
-
- // and a final link to the current directory
- std::string substr(path, lastslash, -1);
- if (end_is_directory)
- file.printf("<a href=\"index.html\">%s</a>", substr.c_str());
- else if (link_to_file)
- file.printf("<a href=\"%s\">%s</a>", substr.c_str(), substr.c_str());
- else
- file.printf("<a href=\"%s.html\">%s</a>", substr.c_str(), substr.c_str());
-}
-
-
-/*-------------------------------------------------
- find_include_file - find an include file
--------------------------------------------------*/
-
-static bool find_include_file(std::string &srcincpath, int srcrootlen, int dstrootlen, std::string &srcfile, std::string &dstfile, std::string &filename)
-{
- // iterate over include paths and find the file
- for (include_path *curpath = incpaths; curpath != nullptr; curpath = curpath->next)
- {
- // a '.' include path is specially treated
- if (curpath->path.compare(".") == 0)
- srcincpath.assign(srcfile.substr(0, srcfile.find_last_of(PATH_SEPARATOR[0])));
- else
- srcincpath.assign(srcfile.substr(0, srcrootlen + 1)).append(curpath->path);
-
- // append the filename piecemeal to account for directories
- int lastsepindex = 0;
- int sepindex;
- while ((sepindex = filename.find_first_of('/', lastsepindex)) != -1)
- {
- // handle .. by removing a chunk from the incpath
- std::string pathpart(filename, lastsepindex, sepindex - lastsepindex);
- if (pathpart.compare("..")==0)
- {
- sepindex = srcincpath.find_last_of(PATH_SEPARATOR[0]);
- if (sepindex != -1)
- srcincpath.erase(sepindex);
- }
-
- // otherwise, append a path separator and the pathpart
- else
- srcincpath.append(PATH_SEPARATOR).append(pathpart);
-
- // advance past the previous index
- lastsepindex = sepindex + 1;
- }
-
- // now append the filename
- srcincpath.append(PATH_SEPARATOR).append(filename.substr(lastsepindex, -1));
-
- // see if we can open it
- util::core_file::ptr testfile;
- if (util::core_file::open(srcincpath, OPEN_FLAG_READ, testfile) == osd_file::error::NONE)
- {
- // close the file
- testfile.reset();
-
- // find the longest matching directory substring between the include and source file
- lastsepindex = 0;
- while ((sepindex = srcincpath.find_first_of(PATH_SEPARATOR[0], lastsepindex)) != -1)
- {
- // get substrings up to the current directory
- std::string tempfile(srcfile, 0, sepindex);
- std::string tempinc(srcincpath, 0, sepindex);
-
- // if we don't match, stop
- if (tempfile.compare(tempinc)!=0)
- break;
- lastsepindex = sepindex + 1;
- }
-
- // chop off the common parts of the paths
- std::string tempfile(srcfile, lastsepindex, -1);
- srcincpath = srcincpath.substr(lastsepindex, -1);
- strreplacechr(srcincpath, PATH_SEPARATOR[0], '/');
-
- // for each directory left in the filename, we need to prepend a "../"
- while ((sepindex = tempfile.find_first_of(PATH_SEPARATOR[0])) != -1)
- {
- tempfile.erase(0, sepindex + 1);
- srcincpath.insert(0, "../");
- }
- srcincpath.append(".html");
-
- // free the strings and return the include path
- return true;
- }
- }
- return false;
-}
diff --git a/src/tools/srcclean.cpp b/src/tools/srcclean.cpp
index 431bc00434c..63809b57f1e 100644
--- a/src/tools/srcclean.cpp
+++ b/src/tools/srcclean.cpp
@@ -4,7 +4,7 @@
srcclean.cpp
- Basic source code cleanear.
+ Basic source code cleaner.
****************************************************************************/
@@ -19,15 +19,18 @@
Known C++ limitations:
* No filtering of control characters
+ * Will not handle raw string literals correctly
* Will not produce expected output for a string continuation within
a preprocessor macro, e.g this:
#define MY_MACRO \
"string that \
continues"
- * Will not produce expected output for a string continuation that
- breaks an escape sequence, e.g. this:
- "bad\\
- tbehaviour"
+ * Numeric literals broken by line continuations are not recognised
+ * Will not recognise a comment delimiter broken by multiple line
+ continuations. e.g. this:
+ /\
+ \
+ / preprocessor abuse
Known Lua limitations:
* Whitespace normalisation is applied inside long string literals
@@ -36,6 +39,9 @@
may have spacing adjusted in a way that affects behaviour when
uncommented
+ Known JSON limitations:
+ * Doesn't detect invalid numbers or literals
+
Known XML limitations:
* No special handling for CDATA
* No special handling for processing instructions
@@ -49,7 +55,6 @@
#include "corefile.h"
#include "corestr.h"
-#include "osdcore.h"
#include "strformat.h"
#include <algorithm>
@@ -101,14 +106,21 @@ protected:
static constexpr char32_t HORIZONTAL_TAB = 0x0000'0009U;
static constexpr char32_t LINE_FEED = 0x0000'000aU;
static constexpr char32_t VERTICAL_TAB = 0x0000'000bU;
+ static constexpr char32_t FORM_FEED = 0x0000'000cU;
+ static constexpr char32_t C0_CONTROL_LAST = 0x0000'001fU;
static constexpr char32_t SPACE = 0x0000'0020U;
static constexpr char32_t DOUBLE_QUOTE = 0x0000'0022U;
static constexpr char32_t SINGLE_QUOTE = 0x0000'0027U;
+ static constexpr char32_t ASTERISK = 0x0000'002aU;
static constexpr char32_t HYPHEN_MINUS = 0x0000'002dU;
+ static constexpr char32_t SLASH = 0x0000'002fU;
static constexpr char32_t QUESTION_MARK = 0x0000'003fU;
static constexpr char32_t BACKSLASH = 0x0000'005cU;
static constexpr char32_t BASIC_LATIN_LAST = 0x0000'007fU;
static constexpr char32_t CYRILLIC_SUPPLEMENT_LAST = 0x0000'052fU;
+ static constexpr char32_t LINE_SEPARATOR = 0x0000'2028U;
+ static constexpr char32_t PARAGRAPH_SEPARATOR = 0x0000'2029U;
+ static constexpr char32_t SUPPLEMENTARY_FIRST = 0x0001'0000U;
template <typename OutputIt>
cleaner_base(OutputIt &&output, newline newline_mode, unsigned tab_width);
@@ -128,7 +140,6 @@ private:
static constexpr char32_t NONCHARACTER_LAST = 0x0000'fdefU;
static constexpr char32_t ZERO_WIDTH_NB_SPACE = 0x0000'feffU;
static constexpr char32_t REPLACEMENT_CHARACTER = 0x0000'fffdU;
- static constexpr char32_t SUPPLEMENTARY_FIRST = 0x0001'0000U;
static constexpr char32_t SUPPLEMENTARY_LAST = 0x0010'ffffU;
static constexpr char32_t CODE_LENGTH_THRESHOLDS[6]{
@@ -176,7 +187,7 @@ private:
// output state management
unsigned m_output_column = 0U;
- unsigned m_indent;
+ unsigned m_indent = 0U;
unsigned m_tab_limit = std::numeric_limits<unsigned>::max();
std::vector<char32_t> m_whitespace;
@@ -595,7 +606,7 @@ void cleaner_base::output_utf8(char32_t ch)
void cleaner_base::commit_character(char32_t ch)
{
- assert(ARRAY_LENGTH(m_buffer) > m_position);
+ assert(std::size(m_buffer) > m_position);
assert(1U <= m_code_length);
assert(6U >= m_code_length);
@@ -695,7 +706,7 @@ void cleaner_base::commit_character(char32_t ch)
void cleaner_base::process_if_full()
{
- if (ARRAY_LENGTH(m_buffer) == m_position)
+ if (std::size(m_buffer) == m_position)
{
process_characters(m_buffer, m_buffer + m_position);
m_position = 0U;
@@ -824,8 +835,6 @@ protected:
void output_character(char32_t ch);
private:
- static constexpr char32_t ASTERISK = 0x0000'002aU;
- static constexpr char32_t SLASH = 0x0000'002fU;
static constexpr char32_t UPPERCASE_FIRST = 0x0000'0041U;
static constexpr char32_t UPPERCASE_B = 0x0000'0042U;
static constexpr char32_t UPPERCASE_X = 0x0000'0058U;
@@ -868,19 +877,19 @@ private:
bool tail_is(char32_t ch) const
{
- return !m_tail.empty() && (m_tail.front() == ch);
+ return !m_tail.empty() && (m_tail.back() == ch);
}
void pop_tail()
{
if (!m_tail.empty())
- m_tail.pop_front();
+ m_tail.pop_back();
}
void replace_tail(char32_t ch)
{
assert(!m_tail.empty());
- *m_tail.begin() = ch;
+ m_tail.back() = ch;
}
void flush_tail()
@@ -938,10 +947,12 @@ private:
bool m_escape = false;
std::deque<char32_t> m_tail;
std::uint64_t m_comment_line = 0U;
+ bool m_broken_escape = false;
char32_t m_lead_digit = 0U;
unsigned m_radix = 0U;
std::uint64_t m_tabs_escaped = 0U;
+ std::uint64_t m_broken_comment_delimiters = 0U;
std::uint64_t m_line_comment_continuations = 0U;
std::uint64_t m_string_continuations = 0U;
std::uint64_t m_uppercase_radix = 0U;
@@ -965,6 +976,7 @@ bool cpp_cleaner::affected() const
return
cleaner_base::affected() ||
m_tabs_escaped ||
+ m_broken_comment_delimiters ||
m_line_comment_continuations ||
m_string_continuations ||
m_uppercase_radix ||
@@ -977,6 +989,8 @@ void cpp_cleaner::summarise(std::ostream &os) const
cleaner_base::summarise(os);
if (m_tabs_escaped)
util::stream_format(os, "%1$u tab(s) escaped\n", m_tabs_escaped);
+ if (m_broken_comment_delimiters)
+ util::stream_format(os, "%1$u broken comment delimiter(s) replaced\n", m_broken_comment_delimiters);
if (m_line_comment_continuations)
util::stream_format(os, "%1$u line comment continuation(s) replaced\n", m_line_comment_continuations);
if (m_string_continuations)
@@ -994,7 +1008,6 @@ void cpp_cleaner::output_character(char32_t ch)
{
case parse_state::DEFAULT:
case parse_state::TOKEN:
- case parse_state::CHARACTER_CONSTANT:
case parse_state::NUMERIC_CONSTANT:
if (BASIC_LATIN_LAST < ch)
{
@@ -1004,28 +1017,24 @@ void cpp_cleaner::output_character(char32_t ch)
break;
case parse_state::COMMENT:
case parse_state::LINE_COMMENT:
- break;
case parse_state::STRING_CONSTANT:
- if (CYRILLIC_SUPPLEMENT_LAST < ch)
- {
- ++m_non_ascii;
- ch = QUESTION_MARK;
- }
+ case parse_state::CHARACTER_CONSTANT:
break;
}
switch (ch)
{
+ case HORIZONTAL_TAB:
+ case SPACE:
+ case BACKSLASH:
+ m_tail.emplace_back(ch);
+ break;
default:
flush_tail();
if (LINE_FEED == ch)
- {
cleaner_base::output_character(ch);
- break;
- }
- case HORIZONTAL_TAB:
- case SPACE:
- m_tail.emplace_back(ch);
+ else
+ m_tail.emplace_back(ch);
}
}
@@ -1085,6 +1094,13 @@ void cpp_cleaner::process_default(char32_t ch)
{
switch (ch)
{
+ case LINE_FEED:
+ if (m_escape && tail_is(BACKSLASH))
+ {
+ m_broken_escape = true;
+ return;
+ }
+ break;
case DOUBLE_QUOTE:
m_parse_state = parse_state::STRING_CONSTANT;
break;
@@ -1097,11 +1113,35 @@ void cpp_cleaner::process_default(char32_t ch)
m_parse_state = parse_state::COMMENT;
m_comment_line = m_input_line;
set_tab_limit();
+ if (m_broken_escape)
+ {
+ ++m_broken_comment_delimiters;
+ assert(tail_is(BACKSLASH));
+ pop_tail();
+ output_character(ch);
+ output_character(LINE_FEED);
+ m_escape = false;
+ m_broken_escape = false;
+ return;
+ }
}
break;
case SLASH:
if (m_escape)
+ {
m_parse_state = parse_state::LINE_COMMENT;
+ if (m_broken_escape)
+ {
+ ++m_broken_comment_delimiters;
+ assert(tail_is(BACKSLASH));
+ pop_tail();
+ assert(tail_is(SLASH));
+ pop_tail();
+ output_character(LINE_FEED);
+ output_character(SLASH);
+ m_broken_escape = false;
+ }
+ }
break;
default:
if (is_token_lead(ch))
@@ -1112,11 +1152,15 @@ void cpp_cleaner::process_default(char32_t ch)
{
m_parse_state = parse_state::NUMERIC_CONSTANT;
m_escape = false;
+ m_broken_escape = false;
process_numeric(ch);
return;
}
}
- m_escape = (SLASH == ch) ? !m_escape : false;
+ if (m_broken_escape)
+ output_character(LINE_FEED);
+ m_escape = m_escape ? ((BACKSLASH == ch) && tail_is(SLASH)) : (SLASH == ch);
+ m_broken_escape = false;
output_character(ch);
}
@@ -1125,18 +1169,65 @@ void cpp_cleaner::process_comment(char32_t ch)
{
switch (ch)
{
- case SLASH:
- if (m_escape)
+ case LINE_FEED:
+ if (m_escape && tail_is(BACKSLASH))
+ {
+ m_broken_escape = true;
+ }
+ else
{
m_escape = false;
+ m_broken_escape = false;
+ output_character(ch);
+ }
+ break;
+ case SLASH:
+ if (m_broken_escape)
+ {
m_parse_state = parse_state::DEFAULT;
m_comment_line = 0U;
+ ++m_broken_comment_delimiters;
+ assert(tail_is(BACKSLASH));
+ pop_tail();
+ assert(tail_is(ASTERISK));
+ pop_tail();
+ output_character(LINE_FEED);
+ output_character(ASTERISK);
output_character(ch);
reset_tab_limit();
- break;
}
+ else if (m_escape)
+ {
+ m_parse_state = parse_state::DEFAULT;
+ m_comment_line = 0U;
+ output_character(ch);
+ reset_tab_limit();
+ }
+ else
+ {
+ output_character(ch);
+ }
+ m_escape = false;
+ m_broken_escape = false;
+ break;
+ case BACKSLASH:
+ if (m_broken_escape)
+ {
+ m_escape = false;
+ m_broken_escape = false;
+ output_character(LINE_FEED);
+ }
+ else if (m_escape)
+ {
+ m_escape = tail_is(ASTERISK);
+ }
+ output_character(ch);
+ break;
default:
+ if (m_broken_escape)
+ output_character(LINE_FEED);
m_escape = ASTERISK == ch;
+ m_broken_escape = false;
output_character(ch);
}
}
@@ -1157,6 +1248,7 @@ void cpp_cleaner::process_line_comment(char32_t ch)
break;
}
m_parse_state = parse_state::DEFAULT;
+ [[fallthrough]];
default:
output_character(ch);
}
@@ -1195,9 +1287,24 @@ void cpp_cleaner::process_text(char32_t ch)
else if (tail_is(BACKSLASH))
{
++m_string_continuations;
- replace_tail(DOUBLE_QUOTE);
- output_character(ch);
- output_character(DOUBLE_QUOTE);
+ if (m_escape)
+ {
+ replace_tail(DOUBLE_QUOTE);
+ output_character(ch);
+ output_character(DOUBLE_QUOTE);
+ }
+ else
+ {
+ pop_tail();
+ assert(tail_is(BACKSLASH));
+ pop_tail();
+ output_character(DOUBLE_QUOTE);
+ output_character(ch);
+ output_character(DOUBLE_QUOTE);
+ output_character(BACKSLASH);
+ m_escape = true;
+ return;
+ }
}
else
{
@@ -1211,9 +1318,25 @@ void cpp_cleaner::process_text(char32_t ch)
output_character(char32_t(std::uint8_t('v')));
break;
default:
- output_character(ch);
- if (!m_escape && (((parse_state::STRING_CONSTANT == m_parse_state) ? DOUBLE_QUOTE : SINGLE_QUOTE) == ch))
- m_parse_state = parse_state::DEFAULT;
+ if (CYRILLIC_SUPPLEMENT_LAST >= ch)
+ {
+ output_character(ch);
+ if (!m_escape && (((parse_state::STRING_CONSTANT == m_parse_state) ? DOUBLE_QUOTE : SINGLE_QUOTE) == ch))
+ m_parse_state = parse_state::DEFAULT;
+ }
+ else
+ {
+ ++m_non_ascii;
+ bool const supplementary(SUPPLEMENTARY_FIRST <= ch);
+ if (!m_escape)
+ output_character(BACKSLASH);
+ output_character(char32_t(std::uint8_t(supplementary ? 'U' : 'u')));
+ for (int shift = supplementary ? 28 : 12; 0 <= shift; shift -= 4)
+ {
+ std::uint8_t const digit((ch >> shift) & 0x0fU);
+ output_character(std::uint8_t((10U > digit) ? '0' : ('a' - 10)) + digit);
+ }
+ }
}
m_escape = (BACKSLASH == ch) && !m_escape;
}
@@ -1245,12 +1368,14 @@ void cpp_cleaner::process_numeric(char32_t ch)
case UPPERCASE_B:
++m_uppercase_radix;
ch = LOWERCASE_B;
+ [[fallthrough]];
case LOWERCASE_B:
m_radix = 2U;
break;
case UPPERCASE_X:
++m_uppercase_radix;
ch = LOWERCASE_X;
+ [[fallthrough]];
case LOWERCASE_X:
m_radix = 16U;
break;
@@ -1511,6 +1636,7 @@ void lua_cleaner::process_default(char32_t ch)
m_block_line = m_input_line;
m_block_level = m_long_bracket_level;
m_parse_state = parse_state::LONG_STRING_CONSTANT;
+ [[fallthrough]];
default:
m_long_bracket_level = -1;
}
@@ -1538,6 +1664,7 @@ void lua_cleaner::process_short_comment(char32_t ch)
m_block_level = m_long_bracket_level;
m_parse_state = parse_state::LONG_COMMENT;
set_tab_limit();
+ [[fallthrough]];
default:
m_long_bracket_level = -1;
}
@@ -1632,6 +1759,289 @@ void lua_cleaner::process_long_string_constant(char32_t ch)
/***************************************************************************
+ JSON DATA CLEANER CLASS
+***************************************************************************/
+
+class json_cleaner : public cleaner_base
+{
+public:
+ template <typename OutputIt>
+ json_cleaner(OutputIt &&output, newline newline_mode, unsigned tab_width);
+
+ virtual bool affected() const override;
+ virtual void summarise(std::ostream &os) const override;
+
+protected:
+ void output_character(char32_t ch);
+
+private:
+ enum class parse_state
+ {
+ DEFAULT,
+ COMMENT,
+ LINE_COMMENT,
+ STRING_CONSTANT
+ };
+
+ virtual void process_characters(char32_t const *begin, char32_t const *end) override;
+ virtual void input_complete() override;
+
+ void process_default(char32_t ch);
+ void process_comment(char32_t ch);
+ void process_line_comment(char32_t ch);
+ void process_text(char32_t ch);
+
+ parse_state m_parse_state = parse_state::DEFAULT;
+ std::uint64_t m_input_line = 1U;
+ bool m_escape = false;
+ std::uint64_t m_comment_line = 0U;
+
+ std::uint64_t m_tabs_escaped = 0U;
+ std::uint64_t m_newlines_escaped = 0U;
+ std::uint64_t m_form_feeds_escaped = 0U;
+ std::uint64_t m_line_separators_escaped = 0U;
+ std::uint64_t m_paragraph_separators_escaped = 0U;
+ std::uint64_t m_c0_control_escaped = 0U;
+ std::uint64_t m_non_ascii = 0U;
+};
+
+
+template <typename OutputIt>
+json_cleaner::json_cleaner(
+ OutputIt &&output,
+ newline newline_mode,
+ unsigned tab_width)
+ : cleaner_base(std::forward<OutputIt>(output), newline_mode, tab_width)
+{
+}
+
+
+bool json_cleaner::affected() const
+{
+ return
+ cleaner_base::affected() ||
+ m_tabs_escaped ||
+ m_newlines_escaped ||
+ m_form_feeds_escaped ||
+ m_line_separators_escaped ||
+ m_paragraph_separators_escaped ||
+ m_c0_control_escaped ||
+ m_non_ascii;
+}
+
+
+void json_cleaner::summarise(std::ostream &os) const
+{
+ cleaner_base::summarise(os);
+ if (m_tabs_escaped)
+ util::stream_format(os, "%1$u tab(s) escaped\n", m_tabs_escaped);
+ if (m_newlines_escaped)
+ util::stream_format(os, "%1$u line feed(s) escaped\n", m_newlines_escaped);
+ if (m_form_feeds_escaped)
+ util::stream_format(os, "%1$u form feed(s) escaped\n", m_form_feeds_escaped);
+ if (m_line_separators_escaped)
+ util::stream_format(os, "%1$u line separator(s) escaped\n", m_line_separators_escaped);
+ if (m_paragraph_separators_escaped)
+ util::stream_format(os, "%1$u paragraph separator(s) escaped\n", m_paragraph_separators_escaped);
+ if (m_c0_control_escaped)
+ util::stream_format(os, "%1$u C0 control character(s) escaped\n", m_c0_control_escaped);
+ if (m_non_ascii)
+ util::stream_format(os, "%1$u non-ASCII character(s) replaced\n", m_non_ascii);
+}
+
+
+void json_cleaner::output_character(char32_t ch)
+{
+ switch (m_parse_state)
+ {
+ case parse_state::DEFAULT:
+ if (BASIC_LATIN_LAST < ch)
+ {
+ ++m_non_ascii;
+ ch = QUESTION_MARK;
+ }
+ break;
+ case parse_state::COMMENT:
+ case parse_state::LINE_COMMENT:
+ case parse_state::STRING_CONSTANT:
+ break;
+ }
+
+ cleaner_base::output_character(ch);
+}
+
+
+void json_cleaner::process_characters(char32_t const *begin, char32_t const *end)
+{
+ while (begin != end)
+ {
+ char32_t const ch(*begin++);
+ switch (m_parse_state)
+ {
+ case parse_state::DEFAULT:
+ process_default(ch);
+ break;
+ case parse_state::COMMENT:
+ process_comment(ch);
+ break;
+ case parse_state::LINE_COMMENT:
+ process_line_comment(ch);
+ break;
+ case parse_state::STRING_CONSTANT:
+ process_text(ch);
+ break;
+ }
+
+ if (LINE_FEED == ch)
+ ++m_input_line;
+ }
+}
+
+
+void json_cleaner::input_complete()
+{
+ switch (m_parse_state)
+ {
+ case parse_state::COMMENT:
+ throw std::runtime_error(util::string_format("unterminated multi-line comment beginning on line %1$u", m_comment_line));
+ case parse_state::STRING_CONSTANT:
+ throw std::runtime_error(util::string_format("unterminated string literal on line %1$u", m_input_line));
+ default:
+ break;
+ }
+}
+
+
+void json_cleaner::process_default(char32_t ch)
+{
+ switch (ch)
+ {
+ case DOUBLE_QUOTE:
+ m_parse_state = parse_state::STRING_CONSTANT;
+ break;
+ case ASTERISK:
+ if (m_escape)
+ {
+ m_parse_state = parse_state::COMMENT;
+ m_comment_line = m_input_line;
+ set_tab_limit();
+ }
+ break;
+ case SLASH:
+ if (m_escape)
+ m_parse_state = parse_state::LINE_COMMENT;
+ break;
+ }
+ m_escape = (SLASH == ch) && !m_escape;
+ output_character(ch);
+}
+
+
+void json_cleaner::process_comment(char32_t ch)
+{
+ switch (ch)
+ {
+ case SLASH:
+ if (m_escape)
+ {
+ m_parse_state = parse_state::DEFAULT;
+ m_comment_line = 0U;
+ output_character(ch);
+ reset_tab_limit();
+ }
+ else
+ {
+ output_character(ch);
+ }
+ m_escape = false;
+ break;
+ default:
+ m_escape = ASTERISK == ch;
+ output_character(ch);
+ }
+}
+
+
+void json_cleaner::process_line_comment(char32_t ch)
+{
+ switch (ch)
+ {
+ case LINE_FEED:
+ m_parse_state = parse_state::DEFAULT;
+ [[fallthrough]];
+ default:
+ output_character(ch);
+ }
+}
+
+
+void json_cleaner::process_text(char32_t ch)
+{
+ switch (ch)
+ {
+ case HORIZONTAL_TAB:
+ ++m_tabs_escaped;
+ if (!m_escape)
+ output_character(BACKSLASH);
+ output_character(char32_t(std::uint8_t('t')));
+ break;
+ case LINE_FEED:
+ ++m_newlines_escaped;
+ if (!m_escape)
+ output_character(BACKSLASH);
+ output_character(char32_t(std::uint8_t('n')));
+ break;
+ case FORM_FEED:
+ ++m_form_feeds_escaped;
+ if (!m_escape)
+ output_character(BACKSLASH);
+ output_character(char32_t(std::uint8_t('f')));
+ break;
+ case LINE_SEPARATOR:
+ ++m_line_separators_escaped;
+ if (!m_escape)
+ output_character(BACKSLASH);
+ output_character(char32_t(std::uint8_t('u')));
+ output_character(char32_t(std::uint8_t('2')));
+ output_character(char32_t(std::uint8_t('0')));
+ output_character(char32_t(std::uint8_t('2')));
+ output_character(char32_t(std::uint8_t('8')));
+ break;
+ case PARAGRAPH_SEPARATOR:
+ ++m_paragraph_separators_escaped;
+ if (!m_escape)
+ output_character(BACKSLASH);
+ output_character(char32_t(std::uint8_t('u')));
+ output_character(char32_t(std::uint8_t('2')));
+ output_character(char32_t(std::uint8_t('0')));
+ output_character(char32_t(std::uint8_t('2')));
+ output_character(char32_t(std::uint8_t('9')));
+ break;
+ default:
+ if (C0_CONTROL_LAST >= ch)
+ {
+ ++m_c0_control_escaped;
+ if (!m_escape)
+ output_character(BACKSLASH);
+ output_character(char32_t(std::uint8_t('u')));
+ output_character(char32_t(std::uint8_t('0')));
+ output_character(char32_t(std::uint8_t('0')));
+ output_character(char32_t(std::uint8_t('0') + (ch / 0x10U)));
+ output_character(char32_t(std::uint8_t('0') + (ch % 0x10U)));
+ }
+ else
+ {
+ output_character(ch);
+ if (!m_escape && (DOUBLE_QUOTE == ch))
+ m_parse_state = parse_state::DEFAULT;
+ }
+ }
+ m_escape = (BACKSLASH == ch) && !m_escape;
+}
+
+
+
+/***************************************************************************
XML DATA CLEANER CLASS
***************************************************************************/
@@ -1785,6 +2195,13 @@ bool is_lua_source_extension(char const *ext)
}
+bool is_json_extension(char const *ext)
+{
+ return
+ !core_stricmp(ext, ".json");
+}
+
+
bool is_xml_extension(char const *ext)
{
return
@@ -1806,7 +2223,7 @@ int main(int argc, char *argv[])
{
bool keep_backup(false);
bool dry_run(false);
-#if defined(WIN32)
+#if defined(_WIN32)
cleaner_base::newline newline_mode(cleaner_base::newline::DOS);
#else
cleaner_base::newline newline_mode(cleaner_base::newline::UNIX);
@@ -1848,13 +2265,13 @@ int main(int argc, char *argv[])
{
// open the file
util::core_file::ptr infile;
- osd_file::error const err(util::core_file::open(argv[i], OPEN_FLAG_READ, infile));
- if (osd_file::error::NONE != err)
+ std::error_condition const err(util::core_file::open(argv[i], OPEN_FLAG_READ, infile));
+ if (err)
{
if (affected)
std::cerr << std::endl;
affected = true;
- util::stream_format(std::cerr, "Can't open %1$s\n", argv[i]);
+ util::stream_format(std::cerr, "Can't open %1$s (%2$s)\n", argv[i], err.message());
++failures;
continue;
}
@@ -1865,12 +2282,15 @@ int main(int argc, char *argv[])
char const *const ext(std::strrchr(argv[i], '.'));
bool const is_c_file(ext && is_c_source_extension(ext));
bool const is_lua_file(ext && is_lua_source_extension(ext));
+ bool const is_json_file(ext && is_json_extension(ext));
bool const is_xml_file(ext && is_xml_extension(ext));
std::unique_ptr<cleaner_base> cleaner;
if (is_c_file)
cleaner = std::make_unique<cpp_cleaner>(std::back_inserter(output), newline_mode, 4U);
else if (is_lua_file)
cleaner = std::make_unique<lua_cleaner>(std::back_inserter(output), newline_mode, 4U);
+ else if (is_json_file)
+ cleaner = std::make_unique<json_cleaner>(std::back_inserter(output), newline_mode, 4U);
else if (is_xml_file)
cleaner = std::make_unique<xml_cleaner>(std::back_inserter(output), newline_mode, 4U);
else
@@ -1878,12 +2298,29 @@ int main(int argc, char *argv[])
// read/process in chunks
output.clear();
- std::uint64_t remaining(infile->size());
- std::uint32_t block;
- while (remaining && (0U != (block = infile->read(original, (std::min)(std::uint64_t(sizeof(original)), remaining)))))
+ std::uint64_t remaining;
+ if (infile->length(remaining))
+ {
+ util::stream_format(std::cerr, "Can't get length of %1$s\n", argv[i]);
+ ++failures;
+ continue;
+ }
+ 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/testkeys.cpp b/src/tools/testkeys.cpp
index 9ee08808c19..3c00dd79854 100644
--- a/src/tools/testkeys.cpp
+++ b/src/tools/testkeys.cpp
@@ -2,8 +2,8 @@
//
// testkeys.cpp - A small utility to analyze SDL keycodes
//
-// Copyright (c) 1996-2019, Nicola Salmoria and the MAME Team.
-// Visit http://mamedev.org for licensing and usage restrictions.
+// Copyright (c) 1996-2022, Nicola Salmoria and the MAME Team.
+// Visit https://mamedev.org for licensing and usage restrictions.
//
// SDLMAME by Olivier Galibert and R. Belmont
// testkeys by couriersud
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index cd164db7776..be64dc9cb72 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -2,13 +2,12 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- mamedasm.c
-
- Generic MAME disassembler.
+ Universal disassembler.
****************************************************************************/
// the disassemblers assume they're in MAME and emu.h is a PCH, so we minimally pander to them
+#include "coretmpl.h"
#include "disasmintf.h"
using offs_t = osd::u32;
@@ -16,7 +15,6 @@ using util::BIT;
#include "cpu/8x300/8x300dasm.h"
#include "cpu/adsp2100/2100dasm.h"
-#include "cpu/alph8201/8201dasm.h"
#include "cpu/alpha/alphad.h"
#include "cpu/alto2/alto2dsm.h"
#include "cpu/am29000/am29dasm.h"
@@ -29,63 +27,89 @@ 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"
#include "cpu/cop400/cop420ds.h"
#include "cpu/cop400/cop424ds.h"
#include "cpu/cop400/cop444ds.h"
+#include "cpu/cops1/cops1d.h"
#include "cpu/cosmac/cosdasm.h"
#include "cpu/cp1610/1610dasm.h"
#include "cpu/cr16b/cr16bdasm.h"
+#include "cpu/cr16c/cr16cdasm.h"
#include "cpu/cubeqcpu/cubedasm.h"
+#include "cpu/ddp516/ddp516d.h"
#include "cpu/dsp16/dsp16dis.h"
#include "cpu/dsp32/dsp32dis.h"
+#include "cpu/dsp56000/dsp56000d.h"
#include "cpu/dsp56156/dsp56dsm.h"
#include "cpu/e0c6200/e0c6200d.h"
#include "cpu/e132xs/32xsdasm.h"
#include "cpu/es5510/es5510d.h"
#include "cpu/esrip/esripdsm.h"
-#include "cpu/f2mc16/f2mc16dasm.h"
+#include "cpu/evolution/evod.h"
+#include "cpu/f2mc16/f2mc16d.h"
#include "cpu/f8/f8dasm.h"
+#include "cpu/fr/frdasm.h"
#include "cpu/g65816/g65816ds.h"
+#include "cpu/gigatron/gigatrondasm.h"
#include "cpu/h6280/6280dasm.h"
+#include "cpu/h8/gt913d.h"
#include "cpu/h8/h8d.h"
#include "cpu/h8/h8hd.h"
#include "cpu/h8/h8s2000d.h"
#include "cpu/h8/h8s2600d.h"
+#include "cpu/h16/h16dasm.h"
+#include "cpu/h8500/h8500dasm.h"
#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"
+#include "cpu/ht1130/ht1130d.h"
#include "cpu/i386/i386dasm.h"
#include "cpu/i8008/8008dasm.h"
#include "cpu/i8085/8085dasm.h"
#include "cpu/i8089/i8089_dasm.h"
#include "cpu/i860/i860dis.h"
#include "cpu/i960/i960dis.h"
+#include "cpu/ibm1800/ibm1800d.h"
#include "cpu/ie15/ie15dasm.h"
+#include "cpu/interdata16/dasm16.h"
#include "cpu/jaguar/jagdasm.h"
+#include "cpu/ks0164/ks0164d.h"
+#include "cpu/lc57/lc57d.h"
+#include "cpu/lc58/lc58d.h"
#include "cpu/lc8670/lc8670dsm.h"
#include "cpu/lh5801/5801dasm.h"
#include "cpu/lr35902/lr35902d.h"
+#include "cpu/m16c/m16cdasm.h"
+#include "cpu/m32c/m32cdasm.h"
#include "cpu/m37710/m7700ds.h"
#include "cpu/m6502/m4510d.h"
#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"
#include "cpu/m68000/m68kdasm.h"
#include "cpu/m6805/6805dasm.h"
#include "cpu/m6809/6x09dasm.h"
+#include "cpu/m68hc16/cpu16dasm.h"
+#include "cpu/m88000/m88000d.h"
#include "cpu/mb86233/mb86233d.h"
#include "cpu/mb86235/mb86235d.h"
#include "cpu/mb88xx/mb88dasm.h"
@@ -93,29 +117,48 @@ using util::BIT;
#include "cpu/mcs40/mcs40dasm.h"
#include "cpu/mcs48/mcs48dsm.h"
#include "cpu/mcs51/mcs51dasm.h"
-#include "cpu/mcs51/axc51-core_dasm.h"
+#include "cpu/axc51/axc51dasm.h"
#include "cpu/mcs96/i8x9xd.h"
#include "cpu/mcs96/i8xc196d.h"
#include "cpu/melps4/melps4d.h"
#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/ns32000/ns32000dasm.h"
+#include "cpu/nios2/nios2dasm.h"
+#include "cpu/nova/novadasm.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/pdp1/tx0dasm.h"
#include "cpu/pdp8/pdp8dasm.h"
+#include "cpu/pic16/pic16d.h"
+#include "cpu/pic1670/pic1670d.h"
#include "cpu/pic16c5x/16c5xdsm.h"
#include "cpu/pic16c62x/16c62xdsm.h"
+#include "cpu/pic17/pic17d.h"
#include "cpu/powerpc/ppc_dasm.h"
#include "cpu/pps4/pps4dasm.h"
+#include "cpu/pps41/pps41d.h"
#include "cpu/psx/psxdasm.h"
#include "cpu/rii/riidasm.h"
+#include "cpu/romp/rompdasm.h"
#include "cpu/rsp/rsp_dasm.h"
+#include "cpu/rw5000/rw5000d.h"
+#include "cpu/rx01/rx01dasm.h"
#include "cpu/s2650/2650dasm.h"
#include "cpu/saturn/saturnds.h"
#include "cpu/sc61860/scdasm.h"
@@ -125,6 +168,7 @@ using util::BIT;
#include "cpu/se3208/se3208dis.h"
#include "cpu/sh/sh_dasm.h"
#include "cpu/sharc/sharcdsm.h"
+#include "cpu/sigma2/sigma2d.h"
#include "cpu/sm510/sm510d.h"
#include "cpu/sm8500/sm8500d.h"
#include "cpu/sparc/sparcdasm.h"
@@ -132,6 +176,7 @@ using util::BIT;
#include "cpu/ssem/ssemdasm.h"
#include "cpu/ssp1601/ssp1601d.h"
#include "cpu/st62xx/st62xx_dasm.h"
+#include "cpu/st9/st9dasm.h"
#include "cpu/superfx/sfx_dasm.h"
#include "cpu/t11/t11dasm.h"
#include "cpu/tlcs870/tlcs870d.h"
@@ -149,27 +194,61 @@ using util::BIT;
#include "cpu/tms7000/7000dasm.h"
#include "cpu/tms9900/9900dasm.h"
#include "cpu/tms9900/tms99com.h"
+#include "cpu/tx0/tx0dasm.h"
#include "cpu/ucom4/ucom4d.h"
#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"
+#include "cpu/upd78k/upd78k2d.h"
+#include "cpu/upd78k/upd78k3d.h"
+#include "cpu/upd78k/upd78k4d.h"
#include "cpu/v60/v60d.h"
+#include "cpu/v620/v620dasm.h"
#include "cpu/v810/v810dasm.h"
+#include "cpu/v850/v850dasm.h"
+#include "cpu/vax/vaxdasm.h"
+#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"
-#include "corefile.h"
#include "corestr.h"
#include "eminline.h"
+#include "endianness.h"
+#include "ioprocs.h"
+#include "osdfile.h"
+#include "strformat.h"
#include <algorithm>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
#include <cstring>
+#include <functional>
#include <iostream>
+#include <memory>
#include <stdexcept>
+#include <string>
+#include <utility>
+#include <vector>
+
+#ifdef _WIN32
+#include <fcntl.h>
+#include <io.h>
+#include <stdio.h>
+#endif
-#include <ctype.h>
using u8 = util::u8;
using u16 = util::u16;
@@ -194,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;
@@ -270,22 +348,29 @@ 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;
+// Configuration missing
+struct nec_unidasm_t : nec_disassembler::config
+{
+ int mode;
+ nec_unidasm_t() { mode = 1; }
+ virtual ~nec_unidasm_t() override = default;
+ virtual int get_mode() const override { return mode; }
+} nec_unidasm;
-enum endianness { le, be };
+static constexpr auto le = util::endianness::little;
+static constexpr auto be = util::endianness::big;
struct dasm_table_entry
{
const char * name;
- endianness endian;
+ util::endianness endian;
int8_t pcshift;
std::function<util::disasm_interface *()> alloc;
};
@@ -300,10 +385,10 @@ struct options
uint8_t lower;
uint8_t upper;
uint8_t flipped;
- int mode;
const dasm_table_entry *dasm;
uint32_t skip;
uint32_t count;
+ bool octal;
};
static const dasm_table_entry dasm_table[] =
@@ -314,15 +399,15 @@ static const dasm_table_entry dasm_table[] =
{ "alpha_nt", le, 0, []() -> util::disasm_interface * { return new alpha_disassembler(alpha_disassembler::TYPE_NT); } },
{ "alpha_unix", le, 0, []() -> util::disasm_interface * { return new alpha_disassembler(alpha_disassembler::TYPE_UNIX); } },
{ "alpha_vms", le, 0, []() -> util::disasm_interface * { return new alpha_disassembler(alpha_disassembler::TYPE_VMS); } },
- { "alpha8201", le, 0, []() -> util::disasm_interface * { return new alpha8201_disassembler; } },
{ "alto2", be, -2, []() -> util::disasm_interface * { return new alto2_disassembler; } },
+ { "a5000", le, 0, []() -> util::disasm_interface * { return new a5000_disassembler; } },
+ { "a5500", le, 0, []() -> util::disasm_interface * { return new a5500_disassembler; } },
{ "am29000", be, 0, []() -> util::disasm_interface * { return new am29000_disassembler; } },
{ "amis2000", le, 0, []() -> util::disasm_interface * { return new amis2000_disassembler; } },
{ "apexc", be, 0, []() -> util::disasm_interface * { return new apexc_disassembler; } },
{ "arc", be, 0, []() -> util::disasm_interface * { return new arc_disassembler; } },
{ "arcompact", le, 0, []() -> util::disasm_interface * { return new arcompact_disassembler; } },
{ "arm", le, 0, []() -> util::disasm_interface * { return new arm_disassembler; } },
- { "arm_be", be, 0, []() -> util::disasm_interface * { return new arm_disassembler; } },
{ "arm7", le, 0, []() -> util::disasm_interface * { arm7_unidasm.t_flag = false; return new arm7_disassembler(&arm7_unidasm); } },
{ "arm7_be", be, 0, []() -> util::disasm_interface * { arm7_unidasm.t_flag = false; return new arm7_disassembler(&arm7_unidasm); } },
{ "arm7thumb", le, 0, []() -> util::disasm_interface * { arm7_unidasm.t_flag = true; return new arm7_disassembler(&arm7_unidasm); } },
@@ -331,8 +416,16 @@ static const dasm_table_entry dasm_table[] =
{ "avr8", le, 0, []() -> util::disasm_interface * { return new avr8_disassembler; } },
{ "axc51core", le, 0, []() -> util::disasm_interface * { return new axc51core_disassembler; } },
{ "axc208", le, 0, []() -> util::disasm_interface * { return new ax208_disassembler; } },
+ { "b5000", le, 0, []() -> util::disasm_interface * { return new b5000_disassembler; } },
+ { "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); } },
{ "cdp1805", le, 0, []() -> util::disasm_interface * { return new cosmac_disassembler(cosmac_disassembler::TYPE_1805); } },
@@ -343,41 +436,59 @@ static const dasm_table_entry dasm_table[] =
{ "cop444", le, 0, []() -> util::disasm_interface * { return new cop444_disassembler; } },
{ "cop424", le, 0, []() -> util::disasm_interface * { return new cop424_disassembler; } },
{ "cp1610", be, -1, []() -> util::disasm_interface * { return new cp1610_disassembler; } },
+ { "cpu16", be, 0, []() -> util::disasm_interface * { return new cpu16_disassembler; } },
{ "cr16a", le, 0, []() -> util::disasm_interface * { return new cr16a_disassembler; } },
{ "cr16b", le, 0, []() -> util::disasm_interface * { return new cr16b_disassembler; } },
+ { "cr16c", le, 0, []() -> util::disasm_interface * { return new cr16c_disassembler; } },
{ "cquestlin", be, -3, []() -> util::disasm_interface * { return new cquestlin_disassembler; } },
{ "cquestrot", be, -3, []() -> util::disasm_interface * { return new cquestrot_disassembler; } },
{ "cquestsnd", be, -3, []() -> util::disasm_interface * { return new cquestsnd_disassembler; } },
+ { "cyber18", be, -1, []() -> util::disasm_interface * { return new cyber18_disassembler; } },
+ { "ddp516", be, -1, []() -> util::disasm_interface * { return new ddp516_disassembler; } },
{ "dp8344", le, -1, []() -> util::disasm_interface * { return new dp8344_disassembler; } },
{ "ds5002fp", le, 0, []() -> util::disasm_interface * { return new ds5002fp_disassembler; } },
+ { "ds80c320", le, 0, []() -> util::disasm_interface * { return new ds80c320_disassembler; } },
{ "dsp16", le, -1, []() -> util::disasm_interface * { return new dsp16_disassembler; } },
{ "dsp32c", le, 0, []() -> util::disasm_interface * { return new dsp32c_disassembler; } },
+ { "dsp56000", be, -2, []() -> util::disasm_interface * { return new dsp56000_disassembler; } },
{ "dsp56156", le, -1, []() -> util::disasm_interface * { return new dsp56156_disassembler; } },
{ "e0c6200", be, -1, []() -> util::disasm_interface * { return new e0c6200_disassembler; } },
{ "epg3231", le, -1, []() -> util::disasm_interface * { return new epg3231_disassembler; } },
// { "es5510", be, 0, []() -> util::disasm_interface * { return new es5510_disassembler; } }, // Currently does nothing
{ "esrip", be, 0, []() -> util::disasm_interface * { return new esrip_disassembler; } },
+ { "evo", le, -1, []() -> util::disasm_interface * { return new evolution_disassembler; } },
{ "f2mc16", le, 0, []() -> util::disasm_interface * { return new f2mc16_disassembler; } },
{ "f8", be, 0, []() -> util::disasm_interface * { return new f8_disassembler; } },
+ { "fr", be, 0, []() -> util::disasm_interface * { return new fr_disassembler; } },
+ { "fscpu32", be, 0, []() -> util::disasm_interface * { return new m68k_disassembler(m68k_disassembler::TYPE_CPU32); } },
{ "g65816", le, 0, []() -> util::disasm_interface * { return new g65816_disassembler(&g65816_unidasm); } },
+ { "gigatron", be, -1, []() -> util::disasm_interface * { return new gigatron_disassembler; } },
+ { "gt913", be, 0, []() -> util::disasm_interface * { return new gt913_disassembler; } },
{ "h6280", le, 0, []() -> util::disasm_interface * { return new h6280_disassembler; } },
{ "h8", be, 0, []() -> util::disasm_interface * { return new h8_disassembler; } },
{ "h8h", be, 0, []() -> util::disasm_interface * { return new h8h_disassembler; } },
{ "h8s2000", be, 0, []() -> util::disasm_interface * { return new h8s2000_disassembler; } },
{ "h8s2600", be, 0, []() -> util::disasm_interface * { return new h8s2600_disassembler; } },
+ { "h8500", be, 0, []() -> util::disasm_interface * { return new h8500_disassembler; } },
+ { "h16", be, 0, []() -> util::disasm_interface * { return new h16_disassembler; } },
{ "hc11", be, 0, []() -> util::disasm_interface * { return new hc11_disassembler; } },
{ "hcd62121", le, 0, []() -> util::disasm_interface * { return new hcd62121_disassembler; } },
+ { "hd6120", be, -1, []() -> util::disasm_interface * { return new hd6120_disassembler; } },
{ "hd61700", le, -1, []() -> util::disasm_interface * { return new hd61700_disassembler; } },
{ "hd6301", be, 0, []() -> util::disasm_interface * { return new m680x_disassembler(6301); } },
{ "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; } },
{ "hp_5061_3011", be, -1, []() -> util::disasm_interface * { return new hp_5061_3011_disassembler; } },
{ "hp_09825_67907", be, -1, []() -> util::disasm_interface * { return new hp_09825_67907_disassembler; } },
{ "hpc16083", le, 0, []() -> util::disasm_interface * { return new hpc16083_disassembler; } },
{ "hpc16164", le, 0, []() -> util::disasm_interface * { return new hpc16164_disassembler; } },
{ "hyperstone", be, 0, []() -> util::disasm_interface * { return new hyperstone_disassembler(&hyperstone_unidasm); } },
+ { "ht1130", le, 0, []() -> util::disasm_interface * { return new ht1130_disassembler; } },
{ "i4004", le, 0, []() -> util::disasm_interface * { return new i4004_disassembler; } },
{ "i4040", le, 0, []() -> util::disasm_interface * { return new i4040_disassembler; } },
{ "i8008", le, 0, []() -> util::disasm_interface * { return new i8008_disassembler; } },
@@ -393,21 +504,29 @@ static const dasm_table_entry dasm_table[] =
{ "i8xc51fx", le, 0, []() -> util::disasm_interface * { return new i8xc51fx_disassembler; } },
{ "i8xc51gb", le, 0, []() -> util::disasm_interface * { return new i8xc51gb_disassembler; } },
{ "i960", le, 0, []() -> util::disasm_interface * { return new i960_disassembler; } },
+ { "ibm1130", be, -1, []() -> util::disasm_interface * { return new ibm1130_disassembler; } },
+ { "ibm1800", be, -1, []() -> util::disasm_interface * { return new ibm1800_disassembler; } },
{ "ie15", le, 0, []() -> util::disasm_interface * { return new ie15_disassembler; } },
+ { "interdata16", be, 0, []() -> util::disasm_interface * { return new interdata16_disassembler; } },
{ "jaguardsp", be, 0, []() -> util::disasm_interface * { return new jaguar_disassembler(jaguar_disassembler::variant::DSP); } },
{ "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; } },
{ "lh5801", le, 0, []() -> util::disasm_interface * { return new lh5801_disassembler; } },
{ "lr35902", le, 0, []() -> util::disasm_interface * { return new lr35902_disassembler; } },
{ "m146805", be, 0, []() -> util::disasm_interface * { return new m146805_disassembler; } },
+ { "m16c", le, 0, []() -> util::disasm_interface * { return new m16c_disassembler; } },
+ { "m32c", le, 0, []() -> util::disasm_interface * { return new m32c_disassembler; } },
{ "m37710", le, 0, []() -> util::disasm_interface * { return new m7700_disassembler(&m7700_unidasm); } },
{ "m4510", le, 0, []() -> util::disasm_interface * { return new m4510_disassembler; } },
{ "m58846", le, -1, []() -> util::disasm_interface * { return new melps4_disassembler; } },
{ "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); } },
@@ -422,38 +541,75 @@ static const dasm_table_entry dasm_table[] =
{ "m6805", be, 0, []() -> util::disasm_interface * { return new m6805_disassembler; } },
{ "m6808", be, 0, []() -> util::disasm_interface * { return new m680x_disassembler(6808); } },
{ "m6809", be, 0, []() -> util::disasm_interface * { return new m6809_disassembler; } },
- { "m68340", be, 0, []() -> util::disasm_interface * { return new m68k_disassembler(m68k_disassembler::TYPE_68340); } },
{ "m68hc05", be, 0, []() -> util::disasm_interface * { return new m68hc05_disassembler; } },
{ "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); } },
{ "minx", le, 0, []() -> util::disasm_interface * { return new minx_disassembler; } },
{ "mips1be", be, 0, []() -> util::disasm_interface * { return new mips1_disassembler; } },
{ "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; } },
+ { "mn1860", be, 0, []() -> util::disasm_interface * { return new mn1860_disassembler; } },
+ { "mn1870", be, 0, []() -> util::disasm_interface * { return new mn1870_disassembler; } },
+ { "mn1880", be, 0, []() -> util::disasm_interface * { return new mn1880_disassembler; } },
+ { "msm65x2", le, 0, []() -> util::disasm_interface * { return new msm65x2_disassembler; } },
{ "nanoprocessor", le, 0, []() -> util::disasm_interface * { return new hp_nanoprocessor_disassembler; } },
- { "nec", le, 0, []() -> util::disasm_interface * { return new nec_disassembler; } },
+ { "nec", le, 0, []() -> util::disasm_interface * { return new nec_disassembler(&nec_unidasm); } },
+ { "nios2", le, 0, []() -> util::disasm_interface * { return new nios2_disassembler; } },
+ { "nova", be, -1, []() -> util::disasm_interface * { return new nova_disassembler; } },
{ "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, 0, []() -> util::disasm_interface * { return new pdp1_disassembler; } },
- { "pdp8", be, 0, []() -> util::disasm_interface * { return new pdp8_disassembler; } },
+ { "pdp1", be, -2, []() -> util::disasm_interface * { return new pdp1_disassembler; } },
+ { "pdp8", be, -1, []() -> util::disasm_interface * { return new pdp8_disassembler; } },
+ { "pic16", le, -1, []() -> util::disasm_interface * { return new pic16_disassembler; } },
{ "pic16c5x", le, -1, []() -> util::disasm_interface * { return new pic16c5x_disassembler; } },
+ { "pic1670", le, -1, []() -> util::disasm_interface * { return new pic1670_disassembler; } },
{ "pic16c62x", le, -1, []() -> util::disasm_interface * { return new pic16c62x_disassembler; } },
+ { "pic17", le, -1, []() -> util::disasm_interface * { return new pic17_disassembler; } },
+ { "power", be, 0, []() -> util::disasm_interface * { return new power_disassembler; } },
{ "powerpc", be, 0, []() -> util::disasm_interface * { return new powerpc_disassembler; } },
{ "pps4", le, 0, []() -> util::disasm_interface * { return new pps4_disassembler; } },
+ { "prime16s", be, -1, []() -> util::disasm_interface * { return new prime16s_disassembler; } },
+ { "prime32r", be, -1, []() -> util::disasm_interface * { return new prime32r_disassembler; } },
+ { "prime32s", be, -1, []() -> util::disasm_interface * { return new prime32s_disassembler; } },
+ { "prime64r", be, -1, []() -> util::disasm_interface * { return new prime64r_disassembler; } },
+ { "prime64v", be, -1, []() -> util::disasm_interface * { return new prime64v_disassembler; } },
{ "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; } },
- { "s2650", le, 0, []() -> util::disasm_interface * { return new s2650_disassembler(&s2650_unidasm); } },
+ { "rupi44", le, 0, []() -> util::disasm_interface * { return new rupi44_disassembler; } },
+ { "rx01", le, 0, []() -> util::disasm_interface * { return new rx01_disassembler; } },
+ { "s2650", be, 0, []() -> util::disasm_interface * { return new s2650_disassembler(&s2650_unidasm); } },
+ { "sab80515", le, 0, []() -> util::disasm_interface * { return new sab80515_disassembler; } },
+ { "sab80c515", le, 0, []() -> util::disasm_interface * { return new sab80c515_disassembler; } },
{ "saturn", le, 0, []() -> util::disasm_interface * { return new saturn_disassembler(&saturn_unidasm); } },
{ "sc61860", le, 0, []() -> util::disasm_interface * { return new sc61860_disassembler; } },
- { "scmp", le, 0, []() -> util::disasm_interface * { return new scmp_disassembler; } },
+ { "scmp", be, 0, []() -> util::disasm_interface * { return new scmp_disassembler; } },
{ "score7", le, 0, []() -> util::disasm_interface * { return new score7_disassembler; } },
{ "scudsp", be, -2, []() -> util::disasm_interface * { return new scudsp_disassembler; } },
{ "se3208", le, 0, []() -> util::disasm_interface * { return new se3208_disassembler; } },
@@ -461,6 +617,7 @@ static const dasm_table_entry dasm_table[] =
{ "sh4", le, 0, []() -> util::disasm_interface * { return new sh_disassembler(true); } },
{ "sh4be", be, 0, []() -> util::disasm_interface * { return new sh_disassembler(true); } },
{ "sharc", le, -3, []() -> util::disasm_interface * { return new sharc_disassembler; } },
+ { "sigma2", be, -1, []() -> util::disasm_interface * { return new sigma2_disassembler; } },
{ "sm500", le, 0, []() -> util::disasm_interface * { return new sm500_disassembler; } },
{ "sm510", le, 0, []() -> util::disasm_interface * { return new sm510_disassembler; } },
{ "sm511", le, 0, []() -> util::disasm_interface * { return new sm511_disassembler; } },
@@ -468,26 +625,35 @@ static const dasm_table_entry dasm_table[] =
{ "sm590", le, 0, []() -> util::disasm_interface * { return new sm590_disassembler; } },
{ "sm5a", le, 0, []() -> util::disasm_interface * { return new sm5a_disassembler; } },
{ "sm8500", le, 0, []() -> util::disasm_interface * { return new sm8500_disassembler; } },
- { "sparcv7", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 7); } },
- { "sparcv8", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 8); } },
- { "sparcv9", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9); } },
- { "sparcv9vis1", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_1); } },
- { "sparcv9vis2", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_2); } },
- { "sparcv9vis2p", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_2p); } },
- { "sparcv9vis3", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_3); } },
- { "sparcv9vis3b", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_3b); } },
+ { "smc1102", le, 0, []() -> util::disasm_interface * { return new smc1102_disassembler; } },
+ { "sparclite", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::sparclite); } },
+ { "sparcv7", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v7); } },
+ { "sparcv8", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v8); } },
+ { "sparcv9", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9); } },
+ { "sparcv9vis1", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_1); } },
+ { "sparcv9vis2", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_2); } },
+ { "sparcv9vis2p", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_2p); } },
+ { "sparcv9vis3", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_3); } },
+ { "sparcv9vis3b", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_3b); } },
{ "spc700", le, 0, []() -> util::disasm_interface * { return new spc700_disassembler; } },
{ "ssem", le, 0, []() -> util::disasm_interface * { return new ssem_disassembler; } },
{ "ssp1601", be, -1, []() -> util::disasm_interface * { return new ssp1601_disassembler; } },
{ "st62xx", le, 0, []() -> util::disasm_interface * { return new st62xx_disassembler; } },
+ { "st9", be, 0, []() -> util::disasm_interface * { return new st9_disassembler; } },
+ { "st9p", be, 0, []() -> util::disasm_interface * { return new st9p_disassembler; } },
{ "superfx", le, 0, []() -> util::disasm_interface * { return new superfx_disassembler(&superfx_unidasm); } },
{ "t11", le, 0, []() -> util::disasm_interface * { return new t11_disassembler; } },
{ "tlcs870", le, 0, []() -> util::disasm_interface * { return new tlcs870_disassembler; } },
- { "tlcs90", le, 0, []() -> util::disasm_interface * { return new tlcs90_disassembler; } },
{ "tlcs900", le, 0, []() -> util::disasm_interface * { return new tlcs900_disassembler; } },
+ { "tmp90c051", le, 0, []() -> util::disasm_interface * { return new tmp90c051_disassembler; } },
+ { "tmp90840", le, 0, []() -> util::disasm_interface * { return new tmp90840_disassembler; } },
+ { "tmp90844", le, 0, []() -> util::disasm_interface * { return new tmp90844_disassembler; } },
{ "tms0980", be, 0, []() -> util::disasm_interface * { return new tms0980_disassembler; } },
{ "tms1000", le, 0, []() -> util::disasm_interface * { return new tms1000_disassembler; } },
{ "tms1100", le, 0, []() -> util::disasm_interface * { return new tms1100_disassembler; } },
+ { "tms1400", le, 0, []() -> util::disasm_interface * { return new tms1400_disassembler; } },
+ { "tms2100", le, 0, []() -> util::disasm_interface * { return new tms2100_disassembler; } },
+ { "tms2400", le, 0, []() -> util::disasm_interface * { return new tms2400_disassembler; } },
{ "tms32010", be, -1, []() -> util::disasm_interface * { return new tms32010_disassembler; } },
{ "tms32025", be, -1, []() -> util::disasm_interface * { return new tms32025_disassembler; } },
{ "tms32031", le, -2, []() -> util::disasm_interface * { return new tms32031_disassembler; } },
@@ -504,23 +670,76 @@ static const dasm_table_entry dasm_table[] =
{ "tp0320", be, 0, []() -> util::disasm_interface * { return new tp0320_disassembler; } },
{ "tx0_64kw", be, -2, []() -> util::disasm_interface * { return new tx0_64kw_disassembler; } },
{ "tx0_8kw", be, -2, []() -> util::disasm_interface * { return new tx0_8kw_disassembler; } },
+ { "tx0_8kwo", be, -2, []() -> util::disasm_interface * { return new tx0_8kwo_disassembler; } },
{ "ucom4", le, 0, []() -> util::disasm_interface * { return new ucom4_disassembler; } },
{ "unsp10", be, -1, []() -> util::disasm_interface * { return new unsp_disassembler; } },
{ "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; } },
{ "upd7807", le, 0, []() -> util::disasm_interface * { return new upd7807_disassembler; } },
{ "upd7810", le, 0, []() -> util::disasm_interface * { return new upd7810_disassembler; } },
- { "upd78c05", le, 0, []() -> util::disasm_interface * { return new upd78c05_disassembler; } },
+ { "upd78014", le, 0, []() -> util::disasm_interface * { return new upd78014_disassembler; } },
+ { "upd78024", le, 0, []() -> util::disasm_interface * { return new upd78024_disassembler; } },
+ { "upd78044a", le, 0, []() -> util::disasm_interface * { return new upd78044a_disassembler; } },
+ { "upd78054", le, 0, []() -> util::disasm_interface * { return new upd78054_disassembler; } },
+ { "upd78064", le, 0, []() -> util::disasm_interface * { return new upd78064_disassembler; } },
+ { "upd78078", le, 0, []() -> util::disasm_interface * { return new upd78078_disassembler; } },
+ { "upd78083", le, 0, []() -> util::disasm_interface * { return new upd78083_disassembler; } },
+ { "upd78138", le, 0, []() -> util::disasm_interface * { return new upd78138_disassembler; } },
+ { "upd78148", le, 0, []() -> util::disasm_interface * { return new upd78148_disassembler; } },
+ { "upd78214", le, 0, []() -> util::disasm_interface * { return new upd78214_disassembler; } },
+ { "upd78218a", le, 0, []() -> util::disasm_interface * { return new upd78218a_disassembler; } },
+ { "upd78224", le, 0, []() -> util::disasm_interface * { return new upd78224_disassembler; } },
+ { "upd78234", le, 0, []() -> util::disasm_interface * { return new upd78234_disassembler; } },
+ { "upd78244", le, 0, []() -> util::disasm_interface * { return new upd78244_disassembler; } },
+ { "upd780024a", le, 0, []() -> util::disasm_interface * { return new upd780024a_disassembler; } },
+ { "upd78312", le, 0, []() -> util::disasm_interface * { return new upd78312_disassembler; } },
+ { "upd78322", le, 0, []() -> util::disasm_interface * { return new upd78322_disassembler; } },
+ { "upd78328", le, 0, []() -> util::disasm_interface * { return new upd78328_disassembler; } },
+ { "upd78334", le, 0, []() -> util::disasm_interface * { return new upd78334_disassembler; } },
+ { "upd78352", le, 0, []() -> util::disasm_interface * { return new upd78352_disassembler; } },
+ { "upd78356", le, 0, []() -> util::disasm_interface * { return new upd78356_disassembler; } },
+ { "upd78366a", le, 0, []() -> util::disasm_interface * { return new upd78366a_disassembler; } },
+ { "upd78372", le, 0, []() -> util::disasm_interface * { return new upd78372_disassembler; } },
+ { "upd784026", le, 0, []() -> util::disasm_interface * { return new upd784026_disassembler; } },
+ { "upd784038", le, 0, []() -> util::disasm_interface * { return new upd784038_disassembler; } },
+ { "upd784046", le, 0, []() -> util::disasm_interface * { return new upd784046_disassembler; } },
+ { "upd784054", le, 0, []() -> util::disasm_interface * { return new upd784054_disassembler; } },
+ { "upd784216", le, 0, []() -> util::disasm_interface * { return new upd784216_disassembler; } },
+ { "upd784218", le, 0, []() -> util::disasm_interface * { return new upd784218_disassembler; } },
+ { "upd784225", le, 0, []() -> util::disasm_interface * { return new upd784225_disassembler; } },
+ { "upd780065", le, 0, []() -> util::disasm_interface * { return new upd780065_disassembler; } },
+ { "upd780988", le, 0, []() -> util::disasm_interface * { return new upd78083_disassembler; } },
+ { "upd78k0kx1", le, 0, []() -> util::disasm_interface * { return new upd78k0kx1_disassembler; } },
+ { "upd78k0kx2", le, 0, []() -> util::disasm_interface * { return new upd78k0kx2_disassembler; } },
{ "upi41", le, 0, []() -> util::disasm_interface * { return new mcs48_disassembler(true, false); } },
{ "v60", le, 0, []() -> util::disasm_interface * { return new v60_disassembler; } },
+ { "v620", be, -1, []() -> util::disasm_interface * { return new v620_disassembler; } },
+ { "v620f", be, -1, []() -> util::disasm_interface * { return new v620f_disassembler; } },
+ { "v75", be, -1, []() -> util::disasm_interface * { return new v75_disassembler; } },
{ "v810", le, 0, []() -> util::disasm_interface * { return new v810_disassembler; } },
+ { "v850", le, 0, []() -> util::disasm_interface * { return new v850_disassembler; } },
+ { "v850es", le, 0, []() -> util::disasm_interface * { return new v850es_disassembler; } },
+ { "v850e2", le, 0, []() -> util::disasm_interface * { return new v850e2_disassembler; } },
+ { "vax", le, 0, []() -> util::disasm_interface * { return new vax_disassembler; } },
+ { "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; } },
+ { "xerox530", be, -1, []() -> util::disasm_interface * { return new xerox530_disassembler; } },
+ { "xtensa", le, 0, []() -> util::disasm_interface * { return new xtensa_disassembler; } },
{ "z180", le, 0, []() -> util::disasm_interface * { return new z180_disassembler; } },
{ "z8", be, 0, []() -> util::disasm_interface * { return new z8_disassembler; } },
{ "z80", le, 0, []() -> util::disasm_interface * { return new z80_disassembler; } },
@@ -531,7 +750,7 @@ class unidasm_data_buffer : public util::disasm_interface::data_buffer
{
public:
std::vector<u8> data;
- offs_t base_pc;
+ offs_t base_pc = 0;
u32 size;
unidasm_data_buffer(util::disasm_interface *disasm, const dasm_table_entry *entry);
@@ -584,18 +803,17 @@ unidasm_data_buffer::unidasm_data_buffer(util::disasm_interface *_disasm, const
switch(entry->pcshift) {
case -1:
lr8 = [](offs_t pc) -> u8 { throw std::logic_error("debug_disasm_buffer::debug_data_buffer: r8 access on 16-bits granularity bus\n"); };
- lr16 = [this](offs_t pc) -> u16 {
- const u16 *src = get_ptr<u16>(pc);
- return src[0];
- };
-
switch(entry->endian) {
case le:
+ lr16 = [this](offs_t pc) -> u16 {
+ const u16 *src = get_ptr<u16>(pc);
+ return little_endianize_int16(src[0]);
+ };
lr32 = [this, page_mask](offs_t pc) -> u32 {
offs_t lpc = disasm->pc_real_to_linear(pc);
u32 r = 0;
for(int j=0; j != 2; j++) {
- r |= get<u16>(disasm->pc_linear_to_real(lpc)) << (j*16);
+ r |= little_endianize_int16(get<u16>(disasm->pc_linear_to_real(lpc))) << (j*16);
lpc = (lpc & ~page_mask) | ((lpc + 1) & page_mask);
}
return r;
@@ -604,7 +822,7 @@ unidasm_data_buffer::unidasm_data_buffer(util::disasm_interface *_disasm, const
offs_t lpc = disasm->pc_real_to_linear(pc);
u64 r = 0;
for(int j=0; j != 4; j++) {
- r |= u64(get<u16>(disasm->pc_linear_to_real(lpc))) << (j*16);
+ r |= u64(little_endianize_int16(get<u16>(disasm->pc_linear_to_real(lpc)))) << (j*16);
lpc = (lpc & ~page_mask) | ((lpc + 1) & page_mask);
}
return r;
@@ -612,11 +830,15 @@ unidasm_data_buffer::unidasm_data_buffer(util::disasm_interface *_disasm, const
break;
case be:
+ lr16 = [this](offs_t pc) -> u16 {
+ const u16 *src = get_ptr<u16>(pc);
+ return big_endianize_int16(src[0]);
+ };
lr32 = [this, page_mask](offs_t pc) -> u32 {
offs_t lpc = disasm->pc_real_to_linear(pc);
u32 r = 0;
for(int j=0; j != 2; j++) {
- r |= get<u16>(disasm->pc_linear_to_real(lpc)) << ((1-j)*16);
+ r |= big_endianize_int16(get<u16>(disasm->pc_linear_to_real(lpc))) << ((1-j)*16);
lpc = (lpc & ~page_mask) | ((lpc + 1) & page_mask);
}
return r;
@@ -625,7 +847,7 @@ unidasm_data_buffer::unidasm_data_buffer(util::disasm_interface *_disasm, const
offs_t lpc = disasm->pc_real_to_linear(pc);
u64 r = 0;
for(int j=0; j != 4; j++) {
- r |= u64(get<u16>(disasm->pc_linear_to_real(lpc))) << ((3-j)*16);
+ r |= u64(big_endianize_int16(get<u16>(disasm->pc_linear_to_real(lpc)))) << ((3-j)*16);
lpc = (lpc & ~page_mask) | ((lpc + 1) & page_mask);
}
return r;
@@ -778,46 +1000,52 @@ unidasm_data_buffer::unidasm_data_buffer(util::disasm_interface *_disasm, const
case -1:
lr8 = [](offs_t pc) -> u8 { abort(); };
- lr16 = [this](offs_t pc) -> u16 {
- const u16 *p = get_ptr<u16>(pc);
- return p ?
- p[0]
- : 0x0000;
- };
switch(entry->endian) {
case le:
+ lr16 = [this](offs_t pc) -> u16 {
+ const u16 *p = get_ptr<u16>(pc);
+ return p ?
+ little_endianize_int16(p[0])
+ : 0x0000;
+ };
lr32 = [this](offs_t pc) -> u32 {
const u16 *p = get_ptr<u16>(pc);
return p ?
- p[0] |
- (p[1] << 16)
+ little_endianize_int16(p[0]) |
+ (little_endianize_int16(p[1]) << 16)
: 0x00000000;
};
lr64 = [this](offs_t pc) -> u64 {
const u16 *p = get_ptr<u16>(pc);
return p ?
- p[0] |
- (p[1] << 16) |
- (u64(p[2]) << 32) |
- (u64(p[3]) << 48)
+ little_endianize_int16(p[0]) |
+ (little_endianize_int16(p[1]) << 16) |
+ (u64(little_endianize_int16(p[2])) << 32) |
+ (u64(little_endianize_int16(p[3])) << 48)
: 0x0000000000000000;
};
break;
case be:
+ lr16 = [this](offs_t pc) -> u16 {
+ const u16 *p = get_ptr<u16>(pc);
+ return p ?
+ big_endianize_int16(p[0])
+ : 0x0000;
+ };
lr32 = [this](offs_t pc) -> u32 {
const u16 *p = get_ptr<u16>(pc);
return p ?
- (p[0] << 16)|
- p[1]
+ (big_endianize_int16(p[0]) << 16)|
+ big_endianize_int16(p[1])
: 0x00000000;
};
lr64 = [this](offs_t pc) -> u64 {
const u16 *p = get_ptr<u16>(pc);
return p ?
- (u64(p[0]) << 48) |
- (u64(p[1]) << 32) |
- (p[2] << 16) |
- p[3]
+ (u64(big_endianize_int16(p[0])) << 48) |
+ (u64(big_endianize_int16(p[1])) << 32) |
+ (big_endianize_int16(p[2]) << 16) |
+ big_endianize_int16(p[3])
: 0x0000000000000000;
};
break;
@@ -827,28 +1055,34 @@ unidasm_data_buffer::unidasm_data_buffer(util::disasm_interface *_disasm, const
case -2:
lr8 = [](offs_t pc) -> u8 { abort(); };
lr16 = [](offs_t pc) -> u16 { abort(); };
- lr32 = [this](offs_t pc) -> u32 {
- const u32 *p = get_ptr<u32>(pc);
- return p ?
- p[0]
- : 0x00000000;
- };
switch(entry->endian) {
case le:
+ lr32 = [this](offs_t pc) -> u32 {
+ const u32 *p = get_ptr<u32>(pc);
+ return p ?
+ little_endianize_int32(p[0])
+ : 0x00000000;
+ };
lr64 = [this](offs_t pc) -> u64 {
const u32 *p = get_ptr<u32>(pc);
return p ?
- p[0] |
- (u64(p[1]) << 32)
+ little_endianize_int32(p[0]) |
+ (u64(little_endianize_int32(p[1])) << 32)
: 0x0000000000000000;
};
break;
case be:
+ lr32 = [this](offs_t pc) -> u32 {
+ const u32 *p = get_ptr<u32>(pc);
+ return p ?
+ big_endianize_int32(p[0])
+ : 0x00000000;
+ };
lr64 = [this](offs_t pc) -> u64 {
const u32 *p = get_ptr<u32>(pc);
return p ?
- (u64(p[0]) << 32) |
- p[1]
+ (u64(big_endianize_int32(p[0])) << 32) |
+ big_endianize_int32(p[1])
: 0x0000000000000000;
};
break;
@@ -859,26 +1093,38 @@ unidasm_data_buffer::unidasm_data_buffer(util::disasm_interface *_disasm, const
lr8 = [](offs_t pc) -> u8 { abort(); };
lr16 = [](offs_t pc) -> u16 { abort(); };
lr32 = [](offs_t pc) -> u32 { abort(); };
- lr64 = [this](offs_t pc) -> u64 {
- const u64 *p = get_ptr<u64>(pc);
- return p ?
- p[0]
- : 0x0000000000000000;
+ switch(entry->endian) {
+ case le:
+ lr64 = [this](offs_t pc) -> u64 {
+ const u64 *p = get_ptr<u64>(pc);
+ return p ?
+ little_endianize_int64(p[0])
+ : 0x0000000000000000;
+ };
+ break;
+ case be:
+ lr64 = [this](offs_t pc) -> u64 {
+ const u64 *p = get_ptr<u64>(pc);
+ return p ?
+ big_endianize_int64(p[0])
+ : 0x0000000000000000;
+ };
+ break;
};
break;
case 3:
lr8 = [](offs_t pc) -> u8 { abort(); };
- lr16 = [this](offs_t pc) -> u16 {
- if(pc < base_pc)
- return 0x0000;
- offs_t delta = (pc - base_pc) >> 3;
- if(delta >= size)
- return 0x0000;
- return reinterpret_cast<const u16 *>(&data[delta])[0];
- };
switch(entry->endian) {
case le:
+ lr16 = [this](offs_t pc) -> u16 {
+ if(pc < base_pc)
+ return 0x0000;
+ offs_t delta = (pc - base_pc) >> 3;
+ if(delta >= size)
+ return 0x0000;
+ return little_endianize_int16(reinterpret_cast<const u16 *>(&data[delta])[0]);
+ };
lr32 = [this](offs_t pc) -> u32 {
if(pc < base_pc)
return 0x00000000;
@@ -886,10 +1132,18 @@ unidasm_data_buffer::unidasm_data_buffer(util::disasm_interface *_disasm, const
if(delta >= size + 2)
return 0x00000000;
auto p = reinterpret_cast<const u16 *>(&data[delta]);
- return p[0] | (u32(p[1]) << 16);
+ return little_endianize_int16(p[0]) | (u32(little_endianize_int16(p[1])) << 16);
};
break;
case be:
+ lr16 = [this](offs_t pc) -> u16 {
+ if(pc < base_pc)
+ return 0x0000;
+ offs_t delta = (pc - base_pc) >> 3;
+ if(delta >= size)
+ return 0x0000;
+ return big_endianize_int16(reinterpret_cast<const u16 *>(&data[delta])[0]);
+ };
lr32 = [this](offs_t pc) -> u32 {
if(pc < base_pc)
return 0x00000000;
@@ -897,7 +1151,7 @@ unidasm_data_buffer::unidasm_data_buffer(util::disasm_interface *_disasm, const
if(delta >= size + 2)
return 0x00000000;
auto p = reinterpret_cast<const u16 *>(&data[delta]);
- return (u32(p[0]) << 16) | p[1];
+ return (u32(big_endianize_int16(p[0])) << 16) | big_endianize_int16(p[1]);
};
break;
}
@@ -915,11 +1169,28 @@ void unidasm_data_buffer::decrypt(const unidasm_data_buffer &buffer, bool opcode
abort();
}
+static int parse_number(const char *curarg, const char *default_format, u32 *value)
+{
+ int result;
+ if(curarg[0] == '0') {
+ if(tolower((uint8_t)curarg[1]) == 'x')
+ result = sscanf(&curarg[2], "%x", value);
+ else if(tolower((uint8_t)curarg[1]) == 'o')
+ result = sscanf(&curarg[2], "%o", value);
+ else
+ result = sscanf(&curarg[1], "%o", value);
+ }
+ else if(curarg[0] == '$')
+ result = sscanf(&curarg[1], "%x", value);
+ else
+ result = sscanf(&curarg[0], default_format, value);
+ return result;
+}
+
static int parse_options(int argc, char *argv[], options *opts)
{
bool pending_base = false;
bool pending_arch = false;
- bool pending_mode = false;
bool pending_skip = false;
bool pending_count = false;
@@ -930,8 +1201,8 @@ static int parse_options(int argc, char *argv[], options *opts)
char *curarg = argv[arg];
// is it a switch?
- if(curarg[0] == '-') {
- if(pending_base || pending_arch || pending_mode || pending_skip || pending_count)
+ if(curarg[0] == '-' && curarg[1] != '\0') {
+ if(pending_base || pending_arch || pending_skip || pending_count)
goto usage;
if(tolower((uint8_t)curarg[1]) == 'a')
@@ -942,8 +1213,6 @@ static int parse_options(int argc, char *argv[], options *opts)
opts->flipped = true;
else if(tolower((uint8_t)curarg[1]) == 'l')
opts->lower = true;
- else if(tolower((uint8_t)curarg[1]) == 'm')
- pending_mode = true;
else if(tolower((uint8_t)curarg[1]) == 's')
pending_skip = true;
else if(tolower((uint8_t)curarg[1]) == 'c')
@@ -954,119 +1223,86 @@ static int parse_options(int argc, char *argv[], options *opts)
opts->upper = true;
else if(tolower((uint8_t)curarg[1]) == 'x')
opts->xchbytes = true;
+ else if(tolower((uint8_t)curarg[1]) == 'o')
+ opts->octal = true;
else
goto usage;
- }
+ } else if(pending_base) {
// base PC
- else if(pending_base)
- {
- int result;
- if(curarg[0] == '0' && curarg[1] == 'x')
- result = sscanf(&curarg[2], "%x", &opts->basepc);
- else if(curarg[0] == '$')
- result = sscanf(&curarg[1], "%x", &opts->basepc);
- else
- result = sscanf(&curarg[0], "%x", &opts->basepc);
- if(result != 1)
+ if(parse_number(curarg, "%x", &opts->basepc) != 1)
goto usage;
pending_base = false;
- }
- // mode
- else if(pending_mode)
- {
- if(sscanf(curarg, "%d", &opts->mode) != 1)
+ } else if(pending_arch) {
+ // architecture
+ auto const arch = std::find_if(
+ std::begin(dasm_table),
+ std::end(dasm_table),
+ [&curarg] (dasm_table_entry const &e) { return !core_stricmp(curarg, e.name); });
+ if (std::end(dasm_table) == arch)
goto usage;
- pending_mode = false;
- }
-
- // architecture
- else if(pending_arch) {
- int curarch;
- for(curarch = 0; curarch < ARRAY_LENGTH(dasm_table); curarch++)
- if(core_stricmp(curarg, dasm_table[curarch].name) == 0)
- break;
- if(curarch == ARRAY_LENGTH(dasm_table))
- goto usage;
- opts->dasm = &dasm_table[curarch];
+ opts->dasm = &*arch;
pending_arch = false;
- }
- // skip bytes
- else if(pending_skip) {
- int result;
- if(curarg[0] == '0' && curarg[1] == 'x')
- result = sscanf(&curarg[2], "%x", &opts->skip);
- else
- result = sscanf(curarg, "%d", &opts->skip);
- if(result != 1)
+ } else if(pending_skip) {
+ // skip bytes
+ if(parse_number(curarg, "%d", &opts->skip) != 1)
goto usage;
pending_skip = false;
- }
- // size
- else if(pending_count) {
- if(sscanf(curarg, "%d", &opts->count) != 1)
+ } else if(pending_count) {
+ // size
+ if(parse_number(curarg, "%d", &opts->count) != 1)
goto usage;
pending_count = false;
- }
- // filename
- else if(opts->filename == nullptr)
+ } else if(opts->filename == nullptr) {
+ // filename
opts->filename = curarg;
- // fail
- else
+ } else {
+ // fail
goto usage;
+ }
}
// if we have a dangling option, error
- if(pending_base || pending_arch || pending_mode || pending_skip || pending_count)
+ if(pending_base || pending_arch || pending_skip || pending_count)
goto usage;
// if no file or no architecture, fail
if(opts->filename == nullptr || opts->dasm == nullptr)
goto usage;
+
return 0;
usage:
printf("Usage: %s <filename> -arch <architecture> [-basepc <pc>] \n", argv[0]);
- printf(" [-mode <n>] [-norawbytes] [-xchbytes] [-flipped] [-upper] [-lower]\n");
- printf(" [-skip <n>] [-count <n>]\n");
+ printf(" [-norawbytes] [-xchbytes] [-flipped] [-upper] [-lower]\n");
+ printf(" [-skip <n>] [-count <n>] [-octal]\n");
printf("\n");
printf("Supported architectures:");
const int colwidth = 1 + std::strlen(std::max_element(std::begin(dasm_table), std::end(dasm_table), [](const dasm_table_entry &a, const dasm_table_entry &b) { return std::strlen(a.name) < std::strlen(b.name); })->name);
const int columns = std::max(1, 80 / colwidth);
- const int numrows = (ARRAY_LENGTH(dasm_table) + columns - 1) / columns;
- for(unsigned curarch = 0; curarch < numrows * columns; curarch++)
- {
+ const int numrows = (std::size(dasm_table) + columns - 1) / columns;
+ for(unsigned curarch = 0; curarch < numrows * columns; curarch++) {
const int row = curarch / columns;
const int col = curarch % columns;
const int index = col * numrows + row;
if(col == 0)
printf("\n ");
- printf("%-*s", colwidth, (index < ARRAY_LENGTH(dasm_table)) ? dasm_table[index].name : "");
+ printf("%-*s", colwidth, (index < std::size(dasm_table)) ? dasm_table[index].name : "");
}
printf("\n");
return 1;
};
-int main(int argc, char *argv[])
+int disasm_file(util::random_read &file, u64 length, options &opts)
{
- // Parse options first
- options opts;
- if(parse_options(argc, argv, &opts))
- return 1;
-
- // Load the file
- void *data;
- uint32_t length;
- osd_file::error filerr = util::core_file::load(opts.filename, &data, length);
- if(filerr != osd_file::error::NONE)
- {
- fprintf(stderr, "Error opening file '%s'\n", opts.filename);
+ if(opts.skip >= length) {
+ std::fprintf(stderr, "File '%s' is too short (only %llu bytes found)\n", opts.filename, (unsigned long long)length);
return 1;
}
@@ -1079,18 +1315,19 @@ int main(int argc, char *argv[])
// Build the base buffer and fill it (with a margin)
unidasm_data_buffer base_buffer(disasm.get(), opts.dasm);
- u32 rounded_size = (((length - opts.skip) | (granularity - 1)) & ~(granularity - 1));
+ u32 rounded_size = (((length - opts.skip) + (granularity - 1)) & ~(granularity - 1));
base_buffer.data.resize(rounded_size + 8, 0x00);
base_buffer.size = length;
base_buffer.base_pc = opts.basepc;
+ 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;
+ }
if(opts.xchbytes) {
- for(uint32_t offset = opts.skip; offset < length - 1; offset += 2) {
- base_buffer.data[offset - opts.skip] = ((const u8 *)data)[offset + 1];
- base_buffer.data[offset - opts.skip + 1] = ((const u8 *)data)[offset];
- }
+ for(u64 offset = 0; offset < (length - opts.skip) - 1; offset += 2)
+ std::swap(base_buffer.data[offset], base_buffer.data[offset + 1]);
}
- else
- memcpy(&base_buffer.data[0], (const u8 *)data + opts.skip, length - opts.skip);
// Build the decryption buffers if needed
unidasm_data_buffer opcodes_buffer(disasm.get(), opts.dasm), params_buffer(disasm.get(), opts.dasm);
@@ -1104,18 +1341,12 @@ int main(int argc, char *argv[])
unidasm_data_buffer *popcodes = opcodes_buffer.data.empty() ? &base_buffer : &opcodes_buffer;
unidasm_data_buffer *pparams = params_buffer.data.empty() ? popcodes : &params_buffer;
- // Compute the pc warparound
+ // Compute the pc wraparound
offs_t pclength = opts.dasm->pcshift < 0 ? rounded_size >> -opts.dasm->pcshift : rounded_size << opts.dasm->pcshift;
offs_t limit = opts.basepc + pclength;
- offs_t pc_mask;
- if(!limit)
- pc_mask = 0xffffffff;
- else {
- for(pc_mask = 2; pc_mask && pc_mask < limit; pc_mask *= 2);
- pc_mask--;
- }
+ offs_t pc_mask = limit ? util::make_bitmask<offs_t>(32 - count_leading_zeros_32(limit - 1)) : 0xffffffff;
- // Compute the page warparound
+ // Compute the page wraparound
offs_t page_mask = flags & util::disasm_interface::PAGED ? (1 << disasm->page_address_bits()) - 1 : 0;
// Next pc computation lambdas
@@ -1160,7 +1391,7 @@ int main(int argc, char *argv[])
}
// Compute the shift amount from pc delta to granularity-sized elements
- u32 granularity_shift = 31 - count_leading_zeros(disasm->opcode_alignment());
+ u32 granularity_shift = 31 - count_leading_zeros_32(disasm->opcode_alignment());
// Number of pc steps to disassemble
u32 count = pclength;
@@ -1170,8 +1401,8 @@ int main(int argc, char *argv[])
// pc to string conversion
std::function<std::string (offs_t pc)> pc_to_string;
- int aw = 32 - count_leading_zeros(pc_mask);
- bool is_octal = false; // Parameter? Per-cpu config?
+ int aw = 32 - count_leading_zeros_32(pc_mask);
+ bool is_octal = opts.octal; // Parameter? Per-cpu config?
if((flags & util::disasm_interface::PAGED2LEVEL) == util::disasm_interface::PAGED2LEVEL) {
int bits1 = disasm->page_address_bits();
int bits2 = disasm->page2_address_bits();
@@ -1292,62 +1523,122 @@ int main(int argc, char *argv[])
max_len >>= granularity_shift;
std::function<std::string (offs_t pc, offs_t size)> dump_raw_bytes;
- switch(granularity) {
- case 1:
- dump_raw_bytes = [step = disasm->opcode_alignment(), next_pc, base_buffer](offs_t pc, offs_t size) -> std::string {
- std::string result = "";
- for(offs_t i=0; i != size; i++) {
- if(i)
- result += ' ';
- result += util::string_format("%02x", base_buffer.r8(pc));
- pc = next_pc(pc, step);
- }
- return result;
- };
- max_len = (max_len * 3) - 1;
- break;
-
- case 2:
- dump_raw_bytes = [step = disasm->opcode_alignment(), next_pc, base_buffer](offs_t pc, offs_t size) -> std::string {
- std::string result = "";
- for(offs_t i=0; i != size; i++) {
- if(i)
- result += ' ';
- result += util::string_format("%04x", base_buffer.r16(pc));
- pc = next_pc(pc, step);
- }
- return result;
- };
- max_len = (max_len * 5) - 1;
- break;
-
- case 4:
- dump_raw_bytes = [step = disasm->opcode_alignment(), next_pc, base_buffer](offs_t pc, offs_t size) -> std::string {
- std::string result = "";
- for(offs_t i=0; i != size; i++) {
- if(i)
- result += ' ';
- result += util::string_format("%08x", base_buffer.r32(pc));
- pc = next_pc(pc, step);
- }
- return result;
- };
- max_len = (max_len * 9) - 1;
- break;
-
- case 8:
- dump_raw_bytes = [step = disasm->opcode_alignment(), next_pc, base_buffer](offs_t pc, offs_t size) -> std::string {
- std::string result = "";
- for(offs_t i=0; i != size; i++) {
- if(i)
- result += ' ';
- result += util::string_format("%016x", base_buffer.r64(pc));
- pc = next_pc(pc, step);
- }
- return result;
- };
- max_len = (max_len * 17) - 1;
- break;
+ if(is_octal) {
+ switch(granularity) {
+ case 1:
+ dump_raw_bytes = [step = disasm->opcode_alignment(), &next_pc, &base_buffer](offs_t pc, offs_t size) -> std::string {
+ std::string result = "";
+ for(offs_t i=0; i != size; i++) {
+ if(i)
+ result += ' ';
+ result += util::string_format("%03o", base_buffer.r8(pc));
+ pc = next_pc(pc, step);
+ }
+ return result;
+ };
+ max_len = (max_len * 4) - 1;
+ break;
+
+ case 2:
+ dump_raw_bytes = [step = disasm->opcode_alignment(), &next_pc, &base_buffer](offs_t pc, offs_t size) -> std::string {
+ std::string result = "";
+ for(offs_t i=0; i != size; i++) {
+ if(i)
+ result += ' ';
+ result += util::string_format("%06o", base_buffer.r16(pc));
+ pc = next_pc(pc, step);
+ }
+ return result;
+ };
+ max_len = (max_len * 7) - 1;
+ break;
+
+ case 4:
+ dump_raw_bytes = [step = disasm->opcode_alignment(), &next_pc, &base_buffer](offs_t pc, offs_t size) -> std::string {
+ std::string result = "";
+ for(offs_t i=0; i != size; i++) {
+ if(i)
+ result += ' ';
+ result += util::string_format("%011o", base_buffer.r32(pc));
+ pc = next_pc(pc, step);
+ }
+ return result;
+ };
+ max_len = (max_len * 12) - 1;
+ break;
+
+ case 8:
+ dump_raw_bytes = [step = disasm->opcode_alignment(), &next_pc, &base_buffer](offs_t pc, offs_t size) -> std::string {
+ std::string result = "";
+ for(offs_t i=0; i != size; i++) {
+ if(i)
+ result += ' ';
+ result += util::string_format("%022o", base_buffer.r64(pc));
+ pc = next_pc(pc, step);
+ }
+ return result;
+ };
+ max_len = (max_len * 23) - 1;
+ break;
+ }
+ } else {
+ switch(granularity) {
+ case 1:
+ dump_raw_bytes = [step = disasm->opcode_alignment(), &next_pc, &base_buffer](offs_t pc, offs_t size) -> std::string {
+ std::string result = "";
+ for(offs_t i=0; i != size; i++) {
+ if(i)
+ result += ' ';
+ result += util::string_format("%02x", base_buffer.r8(pc));
+ pc = next_pc(pc, step);
+ }
+ return result;
+ };
+ max_len = (max_len * 3) - 1;
+ break;
+
+ case 2:
+ dump_raw_bytes = [step = disasm->opcode_alignment(), &next_pc, &base_buffer](offs_t pc, offs_t size) -> std::string {
+ std::string result = "";
+ for(offs_t i=0; i != size; i++) {
+ if(i)
+ result += ' ';
+ result += util::string_format("%04x", base_buffer.r16(pc));
+ pc = next_pc(pc, step);
+ }
+ return result;
+ };
+ max_len = (max_len * 5) - 1;
+ break;
+
+ case 4:
+ dump_raw_bytes = [step = disasm->opcode_alignment(), &next_pc, &base_buffer](offs_t pc, offs_t size) -> std::string {
+ std::string result = "";
+ for(offs_t i=0; i != size; i++) {
+ if(i)
+ result += ' ';
+ result += util::string_format("%08x", base_buffer.r32(pc));
+ pc = next_pc(pc, step);
+ }
+ return result;
+ };
+ max_len = (max_len * 9) - 1;
+ break;
+
+ case 8:
+ dump_raw_bytes = [step = disasm->opcode_alignment(), &next_pc, &base_buffer](offs_t pc, offs_t size) -> std::string {
+ std::string result = "";
+ for(offs_t i=0; i != size; i++) {
+ if(i)
+ result += ' ';
+ result += util::string_format("%016x", base_buffer.r64(pc));
+ pc = next_pc(pc, step);
+ }
+ return result;
+ };
+ max_len = (max_len * 17) - 1;
+ break;
+ }
}
if(opts.flipped) {
@@ -1366,7 +1657,75 @@ int main(int argc, char *argv[])
util::stream_format(std::cout, "%s: %-*s %s\n", tf(pc_to_string(l.pc)), max_len, tf(dump_raw_bytes(l.pc, l.size >> granularity_shift)), tf(l.dasm));
}
- free(data);
-
return 0;
}
+
+
+int main(int argc, char *argv[])
+{
+ // Parse options first
+ options opts;
+ if(parse_options(argc, argv, &opts))
+ return 1;
+
+ // Load the file
+ void *data = nullptr;
+ util::random_read::ptr file;
+ u64 length = 0;
+ if(std::strcmp(opts.filename, "-") != 0) {
+ osd_file::ptr f;
+ std::error_condition filerr = osd_file::open(std::string(opts.filename), OPEN_FLAG_READ, f, length);
+ if(filerr) {
+ std::fprintf(stderr, "Error opening file '%s' (%s)\n", opts.filename, filerr.message().c_str());
+ return 1;
+ }
+ file = util::osd_file_read(std::move(f));
+ if(!file) {
+ std::fprintf(stderr, "Error when opening file '%s'\n", opts.filename);
+ return 1;
+ }
+ }
+ else
+ {
+#ifdef _WIN32
+ if (_setmode(_fileno(stdin), _O_BINARY) == -1) {
+#else
+ if (!std::freopen(nullptr, "rb", stdin)) {
+#endif
+ std::fprintf(stderr, "Error reopening stdin in binary mode\n");
+ return 1;
+ }
+ std::size_t allocated = 0x1000;
+ data = std::malloc(allocated);
+ while(!std::ferror(stdin) && !std::feof(stdin)) {
+ if(length == allocated) {
+ allocated <<= 1;
+ data = std::realloc(data, allocated);
+ }
+ if(!data) {
+ std::fprintf(stderr, "Error allocating buffer\n");
+ return 1;
+ }
+
+ length += std::fread((u8 *)data + length, 1, allocated - length, stdin);
+ }
+ if(!length || (std::ferror(stdin) && !std::feof(stdin))) {
+ std::fprintf(stderr, "Error reading from stdin\n");
+ std::free(data);
+ return 1;
+ }
+ file = util::ram_read(data, length);
+ if(!file) {
+ std::fprintf(stderr, "Error opening stdin as file\n");
+ std::free(data);
+ return 1;
+ }
+ }
+
+ int result = disasm_file(*file, length, opts);
+
+ file.reset();
+ std::free(data);
+
+ return result;
+}