diff --git a/IIgsResource.h b/IIgsResource.h new file mode 100644 index 0000000..a854d15 --- /dev/null +++ b/IIgsResource.h @@ -0,0 +1,70 @@ +#ifndef __IIGS_RESOURCE__ +#define __IIGS_RESOURCE__ + +#include "stdint.h" + +#define IIgsResChanged 0x0020 +#define IIgsResPreLoad 0x0040 +#define IIgsResProtected 0x0080 +#define IIgsResAbsLoad 0x0400 +#define IIgsResConverter 0x0800 +#define IIgsResMemAttr 0xC31C /* Flags passed to the NewHandle Memory Manager call */ +#define IIgsSystemMap 0x0001 +#define IIgsMapChanged 0x0002 +#define IIgsRomMap 0x0004 +#define IIgsResNameOffset 0x10000 /* type holding names */ +#define IIgsResNameVersion 0x0001 +#define IIgsSysFileID 0x0001 + + +typedef uint32_t IIgsResID; +typedef uint16_t IIgsResType; +typedef uint16_t IIgsResAttr; + +struct IIgsResHeaderRec { + uint32_t rFileVersion; /* Format version of resource fork */ + uint32_t rFileToMap; /* Offset from start to resource map record */ + uint32_t rFileMapSize; /* Number of bytes map occupies in file */ + uint8_t rFileMemo[128]; /* Reserved space for application */ +}; +typedef struct IIgsResHeaderRec IIgsResHeaderRec; + +struct IIgsFreeBlockRec { + uint32_t blkOffset; + uint32_t blkSize; +}; +typedef struct IIgsFreeBlockRec IIgsFreeBlockRec; + +struct IIgsResMap { + struct IIgsResMap **mapNext; /* Handle to next resource map */ + uint16_t mapFlag; /* Bit Flags */ + uint32_t mapOffset; /* Map's file position */ + uint32_t mapSize; /* Number of bytes map occupies in file */ + uint16_t mapToIndex; + uint16_t mapFileNum; + uint16_t mapID; + uint32_t mapIndexSize; + uint32_t mapIndexUsed; + uint16_t mapFreeListSize; + uint16_t mapFreeListUsed; + IIgsFreeBlockRec mapFreeList[1]; /* n bytes (array of free block records) */ +}; +typedef struct IIgsResMap IIgsResMap, *IIgsResMapPtr; + +struct IIgsResRefRec { + IIgsResType resType; + IIgsResID resID; + uint32_t resOffset; + IIgsResAttr resAttr; + uint32_t resSize; + uint32_t resHandle; +}; +typedef struct IIgsResRefRec IIgsResRefRec, *IIgsResRefRecPtr; + +struct IIgsResourceSpec { + IIgsResType resourceType; + IIgsResID resourceID; +}; +typedef struct IIgsResourceSpec IIgsResourceSpec; + +#endif \ No newline at end of file diff --git a/ListRez.c b/ListRez.c index 4d70e7e..97c4ea2 100644 --- a/ListRez.c +++ b/ListRez.c @@ -178,9 +178,9 @@ int onefile(const char *file) typeListPtr = mapdata + map.offset_typelist + 2; namePtr = mapdata + map.offset_namelist; - printf("Type ID Attr Size Name\n"); - printf("----- ----- ----- ------- ----\n"); - // 'CODE' $0004 $0020 $000018 SANELIB + printf("Type ID Size Attr Name\n"); + printf("----- ----- ------- ----- ----\n"); + // 'CODE' $0004 $000018 $0020 SANELIB for (i = map.count + 1; i; --i, typeListPtr += sizeof(MacResourceTypeList)) { @@ -244,11 +244,11 @@ int onefile(const char *file) return -1; } - printf("%-10s $%04x $%04x $%06x %s\n", + printf("%-10s $%04x $%06x $%04x %s\n", tc, ref.ResourceID, + rSize, ref.attr, - rSize, // todo -- size name ); } diff --git a/ListRezIIgs.c b/ListRezIIgs.c new file mode 100644 index 0000000..162524b --- /dev/null +++ b/ListRezIIgs.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2013, Kelvin W Sherlock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "stdint.h" +#include "IIgsResource.h" + +// n.b. - all data is little endian. + +void hexdump(const uint8_t *data, ssize_t size) +{ +const char *HexMap = "0123456789abcdef"; + + char buffer1[16 * 3 + 1 + 1]; + char buffer2[16 + 1]; + ssize_t offset = 0; + unsigned i, j; + + + while(size > 0) + { + unsigned linelen = 16; + + memset(buffer1, ' ', sizeof(buffer1)); + memset(buffer2, ' ', sizeof(buffer2)); + + if (size < linelen) linelen = size; + + + for (i = 0, j = 0; i < linelen; i++) + { + unsigned x = data[i]; + buffer1[j++] = HexMap[x >> 4]; + buffer1[j++] = HexMap[x & 0x0f]; + j++; + if (i == 7) j++; + + // isascii not part of std:: and may be a macro. + buffer2[i] = isascii(x) && isprint(x) ? x : '.'; + + } + + buffer1[sizeof(buffer1)-1] = 0; + buffer2[sizeof(buffer2)-1] = 0; + + + printf("%06x:\t%s\t%s\n", (unsigned)offset, buffer1, buffer2); + + offset += 16; + data += 16; + size -= 16; + } + + printf("\n"); +} + + +const char *ResTypeName(uint16_t type) +{ + switch(type) + { + case 0x8001: return "rIcon"; + case 0x8002: return "rPicture"; + case 0x8003: return "rControlList"; + case 0x8004: return "rControlTemplate"; + case 0x8005: return "rC1InputString"; + case 0x8006: return "rPString"; + case 0x8007: return "rStringList"; + case 0x8008: return "rMenuBar"; + case 0x8009: return "rMenu"; + case 0x800A: return "rMenuItem"; + case 0x800B: return "rTextForLETextBox2"; + case 0x800C: return "rCtlDefProc"; + case 0x800D: return "rCtlColorTbl"; + case 0x800E: return "rWindParam1"; + case 0x800F: return "rWindParam2"; + case 0x8010: return "rWindColor"; + case 0x8011: return "rTextBlock"; + case 0x8012: return "rStyleBlock"; + case 0x8013: return "rToolStartup"; + case 0x8014: return "rResName"; + case 0x8015: return "rAlertString"; + case 0x8016: return "rText"; + case 0x8017: return "rCodeResource"; + case 0x8018: return "rCDEVCode"; + case 0x8019: return "rCDEVFlags"; + case 0x801A: return "rTwoRects"; + case 0x801B: return "rFileType"; + case 0x801C: return "rListRef"; + case 0x801D: return "rCString"; + case 0x801E: return "rXCMD"; + case 0x801F: return "rXFCN"; + case 0x8020: return "rErrorString"; + case 0x8021: return "rKTransTable"; + case 0x8022: return "rWString"; + case 0x8023: return "rC1OutputString"; + case 0x8024: return "rSoundSample"; + case 0x8025: return "rTERuler"; + case 0x8026: return "rFSequence"; + case 0x8027: return "rCursor"; + case 0x8028: return "rItemStruct"; + case 0x8029: return "rVersion"; + case 0x802A: return "rComment"; + case 0x802B: return "rBundle"; + case 0x802C: return "rFinderPath"; + case 0x802D: return "rPaletteWindow"; + case 0x802E: return "rTaggedStrings"; + case 0x802F: return "rPatternList"; + case 0xC001: return "rRectList"; + case 0xC002: return "rPrintRecord"; + case 0xC003: return "rFont"; + default: return NULL; + } +} + +int onefile(const char *file) +{ + int fd; + ssize_t size; + off_t off; + + IIgsResHeaderRec header; + IIgsResMap map; + uint8_t *mapdata; + uint8_t *indexPtr; + + fd = open(file, O_RDONLY | O_BINARY | O_RSRC); + if (fd < 0) + { + fprintf(stderr, "# %s: Error opening file: %s\n", file, strerror(errno)); + return -1; + } + + size = read(fd, &header, sizeof(header)); + if (size < 0) + { + fprintf(stderr, "# %s Error reading file: %s\n", file, strerror(errno)); + close(fd); + return -1; + } + + if (size < sizeof(header)) + { + fprintf(stderr, "# %s: Not a IIgs resource fork.\n", file); + close(fd); + return -1; + } + + header.rFileVersion = EndianU32_LtoN(header.rFileVersion); + header.rFileToMap = EndianU32_LtoN(header.rFileToMap); + header.rFileMapSize = EndianU32_LtoN(header.rFileMapSize); + + if (header.rFileVersion != 0x00000000) + { + fprintf(stderr, "# %s: Not a IIgs resource fork.\n", file); + close(fd); + return -1; + } + + + mapdata = malloc(header.rFileMapSize); + if (!mapdata) + { + fprintf(stderr, "# %s Memory allocation failure: %s\n", file, strerror(errno)); + close(fd); + return -1; + } + + + off = lseek(fd, header.rFileToMap, SEEK_SET); + if (off < 0) + { + fprintf(stderr, "# %s: Not a IIgs resource fork.\n", file); + close(fd); + free(mapdata); + return -1; + } + + size = read(fd, mapdata, header.rFileMapSize); + if (size < 0) + { + fprintf(stderr, "# %s Error reading file: %s\n", file, strerror(errno)); + close(fd); + free(mapdata); + return -1; + } + if (size != header.rFileMapSize) + { + fprintf(stderr, "# %s: Not a IIgs resource fork.\n", file); + close(fd); + free(mapdata); + return -1; + } + + memcpy(&map, mapdata, sizeof(map)); + + // map.mapNext; + map.mapFlag = EndianU16_LtoN(map.mapFlag); + map.mapOffset = EndianU32_LtoN(map.mapOffset); + map.mapSize = EndianU32_LtoN(map.mapSize); + map.mapToIndex = EndianU16_LtoN(map.mapToIndex); + map.mapFileNum = EndianU16_LtoN(map.mapFileNum); + map.mapID = EndianU16_LtoN(map.mapID); + map.mapIndexSize = EndianU32_LtoN(map.mapIndexSize); + map.mapIndexUsed = EndianU32_LtoN(map.mapIndexUsed); + map.mapFreeListSize = EndianU16_LtoN(map.mapFreeListSize); + map.mapFreeListUsed = EndianU16_LtoN(map.mapFreeListUsed); + + indexPtr = mapdata + map.mapToIndex; + + + printf("Type ID Size Attr\n"); + printf("----- --------- ------- -----\n"); + // $8001 rIcon $00000001 $0001c0 $0040 + for(;; indexPtr += sizeof(IIgsResRefRec)) + { + IIgsResRefRec ref; + const char *name; + + memcpy(&ref, indexPtr, sizeof(ref)); + if (!ref.resType) break; + + ref.resType = EndianU16_LtoN(ref.resType); + ref.resID = EndianU32_LtoN(ref.resID); + ref.resOffset = EndianU32_LtoN(ref.resOffset); + ref.resAttr = EndianU16_LtoN(ref.resAttr); + ref.resSize = EndianU32_LtoN(ref.resSize); + //ref.resHandle + + + name = ResTypeName(ref.resType); + printf("$%04x %-20s $%08x $%06x $%04x\n", + ref.resType, + name ? name : "", + ref.resID, + ref.resSize, + ref.resAttr + ); + + } + + + return 0; +} + +void help(int status) +{ + + printf("# ListRezIIgs\n"); + printf("# Usage: ListRezIIgs [options] file"); + printf("#\n"); + + exit(status); +} + +int main(int argc, char **argv) +{ + + // options for resID, resType, list only + if (argc != 2) + help(1); + + onefile(argv[1]); + + return 0; +} \ No newline at end of file diff --git a/makefile b/makefile index e68c405..9756e7c 100644 --- a/makefile +++ b/makefile @@ -26,7 +26,7 @@ LDFLAGS = -w -c 'MPS ' -t MPST \ # LDFLAGS = -d -c 'MPS ' -t MPST -all: Help GetEnv Duplicate SetFile OverlayIIgs ListRez +all: Help GetEnv Duplicate SetFile OverlayIIgs ListRez ListRezIIgs clean: rm -f *.c.o @@ -53,6 +53,8 @@ OverlayIIgs: OverlayIIgs.c.o OverlayIIgs-flags.c.o ListRez: ListRez.c.o mpw Link $(LDFLAGS) -o $@ $^ $(LIBS) +ListRezIIgs: ListRezIIgs.c.o + mpw Link $(LDFLAGS) -o $@ $^ $(LIBS) #SetFile.c : SetFile.rl # ragel -G2 -p -m -o $@ $<