mirror of
https://github.com/christopherkobayashi/dc42tools.git
synced 2024-12-28 05:29:39 +00:00
Initial commit.
This commit is contained in:
parent
1d9a98569f
commit
0fe280bc5a
10
Makefile
Normal file
10
Makefile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
CFLAGS= -O2 -Wall -Werror
|
||||||
|
|
||||||
|
|
||||||
|
all: dc42cksm
|
||||||
|
|
||||||
|
install: all
|
||||||
|
install -m755 dc42cksm /usr/local/bin/
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f dc42cksm *.o
|
220
dc42cksm.c
Normal file
220
dc42cksm.c
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
/* dc42cksm
|
||||||
|
|
||||||
|
A command-line program to view the checksums in a Macintosh Disk Copy 4.2
|
||||||
|
disk image file, and optionally to update the checksums if they’re not
|
||||||
|
correct.
|
||||||
|
|
||||||
|
Originally written by Steve Chamberlin <steve@bigmessowires.com>
|
||||||
|
64-bit-cleaned and lightly converted from C++ to C by Christopher RYU
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
u_int8_t Read8(FILE* file)
|
||||||
|
{
|
||||||
|
u_int8_t b;
|
||||||
|
fread(&b, 1, 1, file);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_int16_t ReadBigEndian16(FILE* file)
|
||||||
|
{
|
||||||
|
u_int8_t b[2];
|
||||||
|
fread(&b, 1, 2, file);
|
||||||
|
return (((u_int16_t)b[0]) << 8) | b[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
u_int32_t ReadBigEndian32(FILE* file)
|
||||||
|
{
|
||||||
|
u_int8_t b[4];
|
||||||
|
fread(&b, 1, 4, file);
|
||||||
|
return (((u_int32_t)b[0]) << 24) | (((u_int32_t)b[1]) << 16) | (((u_int32_t)b[2]) << 8) | b[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetBigEndian32(u_int8_t* pDest, u_int32_t value)
|
||||||
|
{
|
||||||
|
pDest[0] = (value >> 24) & 0xFF;
|
||||||
|
pDest[1] = (value >> 16) & 0xFF;
|
||||||
|
pDest[2] = (value >> 8) & 0xFF;
|
||||||
|
pDest[3] = value & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
/* parse the command line */
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
printf("Disk Copy 4.2 checksum tool:\nVerifies and optionally updates checksums for DC42 disk image files.\n\n");
|
||||||
|
printf("Usage: %s filename\n", argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *sourceFilename = argv[1];
|
||||||
|
|
||||||
|
printf("Verifying Disk Copy 4.2 disk image checksums for %s\n", sourceFilename);
|
||||||
|
|
||||||
|
FILE *pFile = fopen(sourceFilename, "rb");
|
||||||
|
if (!pFile)
|
||||||
|
{
|
||||||
|
printf("Could not open source file %s\n", sourceFilename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check the DC42 signature bytes */
|
||||||
|
fseek(pFile, 0x52, SEEK_SET);
|
||||||
|
u_int16_t magic0 = Read8(pFile);
|
||||||
|
u_int16_t magic1 = Read8(pFile);
|
||||||
|
|
||||||
|
if (magic0 != 1 || magic1 != 0)
|
||||||
|
{
|
||||||
|
printf("This doesn't look like a valid DC42 disk image file. Aborting.\n");
|
||||||
|
fclose(pFile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return to start */
|
||||||
|
fseek(pFile, 0, SEEK_SET);
|
||||||
|
|
||||||
|
/* disk image name */
|
||||||
|
u_int8_t nameLen = Read8(pFile);
|
||||||
|
unsigned char name[64];
|
||||||
|
fread(name, 1, 63, pFile);
|
||||||
|
if (nameLen < 64)
|
||||||
|
name[nameLen] = 0;
|
||||||
|
else
|
||||||
|
name[63] = 0;
|
||||||
|
printf(" stored image name: %s\n", name);
|
||||||
|
|
||||||
|
/* size of data and tag regions */
|
||||||
|
u_int32_t dataSize = ReadBigEndian32(pFile);
|
||||||
|
printf(" data size: %08X\n", dataSize);
|
||||||
|
u_int32_t tagSize = ReadBigEndian32(pFile);
|
||||||
|
printf(" tag size: %08X\n", tagSize);
|
||||||
|
|
||||||
|
/* stored checksums */
|
||||||
|
u_int32_t storedDataChecksum = ReadBigEndian32(pFile);
|
||||||
|
u_int32_t storedTagChecksum = ReadBigEndian32(pFile);
|
||||||
|
|
||||||
|
/* disk encoding */
|
||||||
|
u_int8_t encoding = Read8(pFile);
|
||||||
|
switch (encoding)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
printf(" encoding: 00, GCR single-sided double density 400K\n");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
printf(" encoding: 01, GCR double-sided double density 800K\n");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
printf(" encoding: 02, MFM double-sided double density 720K\n");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
printf(" encoding: 03, MFM double-sided high density 1440K\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf(" encoding: %02X, unknown\n", encoding);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* disk format */
|
||||||
|
u_int8_t format = Read8(pFile);
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case 0x02:
|
||||||
|
printf(" format: 02, Macintosh/Lisa 400K\n");
|
||||||
|
break;
|
||||||
|
case 0x22:
|
||||||
|
printf(" format: 22, Macintosh 800K\n");
|
||||||
|
break;
|
||||||
|
case 0x24:
|
||||||
|
printf(" format: 24, ProDOS 800K\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf(" format: %02X, unknown\n", format);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ignore the magic number */
|
||||||
|
ReadBigEndian16(pFile);
|
||||||
|
|
||||||
|
/* compute the data checksum */
|
||||||
|
u_int32_t dataChecksum = 0;
|
||||||
|
for (u_int32_t i=0; i<dataSize; i+=2)
|
||||||
|
{
|
||||||
|
dataChecksum += ReadBigEndian16(pFile);
|
||||||
|
dataChecksum = (dataChecksum >> 1) | ((dataChecksum & 1) << 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compute the tag checksum */
|
||||||
|
u_int32_t tagChecksum = 0;
|
||||||
|
if (tagSize > 12)
|
||||||
|
{
|
||||||
|
/* skip the first 12 tag bytes */
|
||||||
|
for (int i=0; i<12; i++)
|
||||||
|
{
|
||||||
|
Read8(pFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u_int32_t i=12; i<tagSize; i+=2)
|
||||||
|
{
|
||||||
|
tagChecksum += ReadBigEndian16(pFile);
|
||||||
|
tagChecksum = (tagChecksum >> 1) | ((tagChecksum & 1) << 31);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* show the results */
|
||||||
|
printf(" stored data checksum: %08X\n", storedDataChecksum);
|
||||||
|
printf("computed data checksum: %08X\n", dataChecksum);
|
||||||
|
printf(" stored tag checksum: %08X\n", storedTagChecksum);
|
||||||
|
printf(" computed tag checksum: %08X\n", tagChecksum);
|
||||||
|
|
||||||
|
if (storedDataChecksum == dataChecksum && storedTagChecksum == tagChecksum)
|
||||||
|
{
|
||||||
|
printf("\nVerification succeeded, no errors.\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\nThe stored checksums do not match the computed checksums.\n");
|
||||||
|
printf("\nUpdate the stored checksums? (Y/N) ");
|
||||||
|
u_int8_t a = getchar();
|
||||||
|
if (a == 'y' || a =='Y')
|
||||||
|
{
|
||||||
|
/* read the whole file into memory */
|
||||||
|
u_int32_t bufSize = 0x54 + dataSize + tagSize;
|
||||||
|
u_int8_t* pBuffer = (u_int8_t*)malloc(bufSize);
|
||||||
|
if (pBuffer == 0)
|
||||||
|
{
|
||||||
|
printf("error: couldn't allocate %u bytes\n", bufSize);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fseek(pFile, 0, SEEK_SET);
|
||||||
|
fread(pBuffer, bufSize, 1, pFile);
|
||||||
|
fclose(pFile);
|
||||||
|
|
||||||
|
/* modify the checksums */
|
||||||
|
SetBigEndian32(&pBuffer[0x48], dataChecksum);
|
||||||
|
SetBigEndian32(&pBuffer[0x4C], tagChecksum);
|
||||||
|
|
||||||
|
/* write the modified file */
|
||||||
|
FILE *pFile = fopen(sourceFilename, "wb");
|
||||||
|
if (!pFile)
|
||||||
|
{
|
||||||
|
printf("error: could not re-open file for writing\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fwrite(pBuffer, bufSize, 1, pFile);
|
||||||
|
|
||||||
|
printf("%s was modified, checksums updated.\n", sourceFilename);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("%s was not modified.\n", sourceFilename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(pFile);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user