ResourceForkReader 0.1.0
See the version list below for details.
dotnet add package ResourceForkReader --version 0.1.0
NuGet\Install-Package ResourceForkReader -Version 0.1.0
<PackageReference Include="ResourceForkReader" Version="0.1.0" />
<PackageVersion Include="ResourceForkReader" Version="0.1.0" />
<PackageReference Include="ResourceForkReader" />
paket add ResourceForkReader --version 0.1.0
#r "nuget: ResourceForkReader, 0.1.0"
#:package ResourceForkReader@0.1.0
#addin nuget:?package=ResourceForkReader&version=0.1.0
#tool nuget:?package=ResourceForkReader&version=0.1.0
ResourceForkReader
A lightweight .NET library for parsing classic Macintosh resource fork files. It focuses on reading the resource header and map, enumerating resource types and entries, and extracting raw resource data so you can interpret specific record formats (strings, string lists, versions, code segments, etc.).
A resource fork is a structured collection of typed resources (e.g., icons, strings, version info) historically used in classic Mac OS / early macOS applications. This library lets you inspect those resources from .NET code.
Features
- Read resource fork header (
ResourceForkHeader) and map (ResourceForkMap). - Enumerate resource types and entries (
Typesdictionary). - Extract raw resource data for any entry (
GetResourceData). - Helpers for common record structures:
StringRecord– Pascal-style length-prefixed string.StringListRecord– List of Pascal-style strings (STR#).VersionRecord– Simple 2+2 ASCII version components (VERS).Code0Segment– Parses CODE 0 segment jump table.CodeSegment– Access executable code segment.
- Efficient big-endian parsing utilities (
SpanUtilities). - Zero external dependencies; spans + stackalloc for minimal allocations.
Installation
Currently source-only. You can:
- Reference the project directly:
<ProjectReference Include="../src/ResourceForkReader.csproj" /> - Or copy the
src/folder into your solution.
A NuGet package could be published later (see roadmap).
Quick Start
using var stream = File.OpenRead(Path.Combine("Samples", "Microsoft Excel.res"));
var fork = new ResourceFork(stream);
// Enumerate types
foreach (var (type, entries) in fork.Map.Types)
{
Console.WriteLine($"Type {type} has {entries.Count} resources");
}
// Read a string list (STR#) resource
var strListEntry = fork.Map.Types["STR#"][0];
var data = fork.GetResourceData(strListEntry); // raw bytes
var listRecord = new StringListRecord(data);
foreach (var s in listRecord.Values)
{
Console.WriteLine(s);
}
// Read version (VERS)
var versEntry = fork.Map.Types["VERS"][0];
var versData = fork.GetResourceData(versEntry);
var version = new VersionRecord(versData);
Console.WriteLine($"Version: {version.Major}.{version.Minor}");
API Overview
ResourceFork
ResourceFork(Stream stream)– Accepts a seekable, readable stream of a resource fork ("*.res" or raw fork data).- Properties:
Header–ResourceForkHeaderwith offsets/lengths.Map–ResourceForkMapcontaining type dictionary.
- Methods:
byte[] GetResourceData(ResourceListEntry entry)– Materialize resource bytes.int GetResourceData(ResourceListEntry entry, Stream output)– Stream resource bytes to an output stream (avoids extra allocation).
ResourceForkMap
Parses the map and builds Dictionary<string, List<ResourceListEntry>> Types where keys are four-character type codes ("STR ", "STR#", "CODE", "VERS", etc.). Includes offsets and attributes for each resource.
Records / Helpers
| Type | Purpose |
|---|---|
StringRecord |
Parses a Pascal-style string (STR ). |
StringListRecord |
Parses a string list resource (STR#). |
VersionRecord |
Parses major/minor version from VERS. |
Code0Segment |
Reads CODE 0 segment sizes and jump table. |
CodeSegment |
Exposes executable code after offset. |
SpanUtilities
Internal helpers for reading big-endian numeric and ASCII values from spans.
Working With Resource Types
Classic Mac resource type codes are four ASCII characters. Examples:
CODE– Executable code segments.STR– Single Pascal string (note trailing space).STR#– List of strings.VERS– Version info.
You can extend parsing by adding new record structs/classes for other types (e.g., MENU, ICN#, FREF). Use the raw bytes from GetResourceData.
Build & Test
# Restore
dotnet restore
# Build library and tests
dotnet build
# Run tests
dotnet test
Target framework: .NET 9.0
Tests demonstrate extracting string resources and version records from the sample Microsoft Excel.res file.
Performance Notes
- Uses
Span<T>,ReadOnlySpan<T>, andstackallocfor small, fixed-size reads. - Minimal allocations when streaming resource data (
GetResourceDataoverload withStream). - Big-endian parsing is manual to avoid BitConverter overhead.
Error Handling
- Throws
ArgumentExceptionif stream isn't seekable/readable or if resource data/map offsets are invalid. - Struct constructors validate length constraints and throw if data is insufficient.
Roadmap / Ideas
- Publish NuGet package (add CI + packaging metadata).
- Parsing of resource names (currently
NameOffsetisn't resolved to actual names). - Async I/O methods (
GetResourceDataAsync). - Writing/modifying resource forks.
- Additional built-in record parsers (icons, menus, dialog definitions).
- Optional memory-mapped file support for very large forks.
Limitations
- Read-only; no mutation or creation of resource forks.
- Assumes well-formed classic Mac resource fork layout.
- Doesn't parse resource name table yet.
Contributing
Pull requests welcome. Please add tests for new record types or parsing changes.
License
(Choose a license: MIT recommended.) Example:
Copyright (c) YEAR AUTHOR
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction...
If you add LICENSE with MIT, update this section accordingly.
References
- Apple Legacy Docs: Resource Manager
- Inside Macintosh (Volumes I–VI)
Feel free to open issues for unsupported resource types or feature requests.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.