630 lines
13 KiB
Plaintext
Executable File
Vendored
630 lines
13 KiB
Plaintext
Executable File
Vendored
#define VERSION "1.01"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <mem.h>
|
|
#include <dos.h>
|
|
|
|
|
|
|
|
union REGS regs;
|
|
struct SREGS sregs;
|
|
|
|
|
|
struct MZ700BootStruct
|
|
{
|
|
unsigned char Type;
|
|
char Signature[6];
|
|
char Name[11];
|
|
unsigned short StartAddress;
|
|
unsigned short FileSize;
|
|
unsigned char Dummy[8];
|
|
unsigned short SectorAddress;
|
|
};
|
|
|
|
|
|
struct MZ700DirectoryStruct
|
|
{
|
|
unsigned char FileType; // 0x00 -> 1
|
|
char FileName[17]; // 0x01 ... 0x11 -> 17
|
|
unsigned char LockFlag; // 0x12 -> 1
|
|
unsigned char DummyFlag; // 0x13 -> 1
|
|
unsigned short FileSize; // 0x14 ... 0x15 -> 2
|
|
unsigned short LoadAddress; // 0x16 ... 0x17 -> 2
|
|
unsigned short ExecAddress; // 0x18 ... 0x19 -> 2
|
|
char Dummy[4]; // 0x1A ... 0x1D -> 4
|
|
unsigned short SectorAddress; // 0x1E ... 0x1F -> 2
|
|
};
|
|
|
|
|
|
struct CMTHeader
|
|
{
|
|
unsigned char Attribute;
|
|
char Name[17];
|
|
unsigned short Size;
|
|
unsigned short LoadAddress;
|
|
unsigned short ExecAddress;
|
|
char Comment[104];
|
|
};
|
|
|
|
|
|
|
|
|
|
char FileTypes[][4] = {
|
|
"???",
|
|
"OBJ",
|
|
"BTX",
|
|
"BSD",
|
|
"BRD",
|
|
"RB ",
|
|
"???",
|
|
"LIB",
|
|
"???",
|
|
"???",
|
|
"SYS",
|
|
"GR "
|
|
};
|
|
|
|
|
|
|
|
unsigned char DiskParameters[11] =
|
|
{0xDF, 0x02, 0x25, 0x01, 16, 0x4E, 0xFF, 0x6C, 0xE5, 100, 8};
|
|
// {0xDF, 0x02, 0x25, 0x02, 18, 0x1B, 0xFF, 0x6C, 0xF6, 100, 8}; /* 1.44MB */
|
|
|
|
|
|
char *ErrorMsg[] =
|
|
{
|
|
"success",
|
|
"invalid function",
|
|
"address mark not found",
|
|
"disk write-protected",
|
|
"sector not found / read error",
|
|
"reset faild",
|
|
"data did not verify correctly",
|
|
"disk changed",
|
|
"drive parameter activity failed",
|
|
"DMA overrun",
|
|
"data boundary error",
|
|
"bad sector detected",
|
|
"bad track detected",
|
|
"unsupported track or invalid media",
|
|
"invalid number of sectors",
|
|
"control data address mark detected",
|
|
"DMA arbitration level out of range",
|
|
"uncorrectable CRC or ECCerror",
|
|
"data ECC corrected"
|
|
};
|
|
|
|
|
|
unsigned char SectorBuffer[1024];
|
|
|
|
unsigned char Drive;
|
|
unsigned char Cylinder;
|
|
unsigned char Head;
|
|
unsigned char Sector;
|
|
|
|
|
|
unsigned int OrgInt1EOffset;
|
|
unsigned int OrgInt1ESegment;
|
|
|
|
|
|
|
|
|
|
void Error(unsigned char Index)
|
|
{
|
|
printf("Error: %02X - ", Index);
|
|
if(Index < 0x12) printf("%s\n", ErrorMsg[Index]);
|
|
if(Index == 0x80) puts("No disc in drive!");
|
|
|
|
exit(1);
|
|
}
|
|
|
|
|
|
|
|
|
|
void ShowSectorBuffer(void)
|
|
{
|
|
unsigned char ByteCounter;
|
|
unsigned char LineCounter;
|
|
int Counter;
|
|
|
|
|
|
Counter = 0;
|
|
|
|
for(LineCounter = 0; LineCounter < 16; LineCounter++)
|
|
{
|
|
printf("\n%04X : ", Counter);
|
|
for(ByteCounter = 0; ByteCounter < 16; ByteCounter++)
|
|
{
|
|
printf("%02X ", SectorBuffer[Counter + ByteCounter]);
|
|
}
|
|
printf(" ");
|
|
for(ByteCounter = 0; ByteCounter < 16; ByteCounter++)
|
|
{
|
|
printf("%c", iscntrl(SectorBuffer[Counter]) ? ' ' : SectorBuffer[Counter]);
|
|
Counter++;
|
|
}
|
|
}
|
|
puts("");
|
|
}
|
|
|
|
|
|
|
|
|
|
int ResetFloppy(char Drive)
|
|
{
|
|
regs.h.ah = 0;
|
|
regs.h.dl = Drive;
|
|
|
|
int86(0x13, ®s, ®s);
|
|
|
|
return(regs.h.ah);
|
|
}
|
|
|
|
|
|
|
|
|
|
int ReadSector(char Drive, char Cylinder, char Head, char Sector)
|
|
{
|
|
int Counter;
|
|
|
|
|
|
if(Head == 0) Head = 1;
|
|
else Head = 0;
|
|
|
|
|
|
regs.h.ah = 0x02;
|
|
Counter = 3;
|
|
|
|
while((regs.h.ah != 0) && (Counter != 0))
|
|
{
|
|
regs.h.ah = 0x02;
|
|
regs.h.al = 1;
|
|
regs.h.ch = Cylinder;
|
|
regs.h.cl = Sector;
|
|
regs.h.dh = Head;
|
|
regs.h.dl = Drive;
|
|
|
|
sregs.es = FP_SEG(SectorBuffer);
|
|
regs.x.bx = FP_OFF(SectorBuffer);
|
|
|
|
int86x(0x13, ®s, ®s, &sregs);
|
|
Counter--;
|
|
}
|
|
|
|
for(Counter = 0; Counter < sizeof(SectorBuffer); Counter++)
|
|
SectorBuffer[Counter] = ~SectorBuffer[Counter];
|
|
|
|
return(regs.x.ax);
|
|
}
|
|
|
|
|
|
|
|
void SaveInt1E(void)
|
|
{
|
|
OrgInt1EOffset = peek(0x0000, 0x1E * 4);
|
|
OrgInt1ESegment = peek(0x0000, 0x1E * 4 + 2);
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetInt1E(unsigned char Type)
|
|
{
|
|
Type++;
|
|
asm cli;
|
|
poke(0x0000, 0x1E * 4, FP_OFF(DiskParameters));
|
|
poke(0x0000, 0x1E * 4 + 2, FP_SEG(DiskParameters));
|
|
asm sti;
|
|
}
|
|
|
|
|
|
|
|
|
|
void ResetInt1E(void)
|
|
{
|
|
asm cli;
|
|
poke(0x0000, 0x1E * 4, OrgInt1EOffset);
|
|
poke(0x0000, 0x1E * 4 + 2, OrgInt1ESegment);
|
|
asm sti;
|
|
}
|
|
|
|
|
|
|
|
|
|
void ShowDirectory(void)
|
|
{
|
|
unsigned char SectorCounter;
|
|
unsigned char Counter;
|
|
unsigned char C, H, S;
|
|
struct MZ700BootStruct *Boot;
|
|
struct MZ700DirectoryStruct *Entry;
|
|
char FileName[18];
|
|
unsigned int Result;
|
|
// unsigned short LastUsedSector;
|
|
|
|
|
|
puts("");
|
|
|
|
Result = ReadSector(Drive, 0, 0, 1);
|
|
Result = Result >> 8;
|
|
if(Result != 0) Error(Result);
|
|
Boot = (struct MZ700BootStruct *) SectorBuffer;
|
|
memcpy(FileName, Boot->Signature, 6);
|
|
FileName[6] = '\0';
|
|
if((Boot->Type == 3) && (strcmp(FileName, "IPLPRO") == 0))
|
|
{
|
|
puts("Floppy is bootable:");
|
|
puts("");
|
|
|
|
memcpy(FileName, Boot->Name, 11);
|
|
if(strchr(FileName, 0x0D) != NULL) *strchr(FileName, 0x0D) = '\0';
|
|
else FileName[11] = '\0';
|
|
|
|
printf(" %-17s OBJ %5u ", FileName, Boot->FileSize);
|
|
S = Boot->SectorAddress % 16 + 1;
|
|
H = (Boot->SectorAddress / 16) % 2;
|
|
C = Boot->SectorAddress / 16 / 2;
|
|
printf(" %4u (%2u %u %2u)\n", Boot->SectorAddress, C, H, S);
|
|
}
|
|
else
|
|
{
|
|
puts("Floppy is not bootable.");
|
|
}
|
|
|
|
puts("");
|
|
puts("Directory:");
|
|
puts("");
|
|
puts(" Name Type Size Lock Load Exec Pos ( C H S)");
|
|
puts("");
|
|
|
|
for(SectorCounter = 1; SectorCounter < 17; SectorCounter++)
|
|
{
|
|
ReadSector(Drive, 0, 1, SectorCounter);
|
|
|
|
|
|
|
|
for(Counter = 0; Counter < 256 / 32; Counter++)
|
|
{
|
|
Entry = (struct MZ700DirectoryStruct *) &SectorBuffer[Counter * sizeof(struct MZ700DirectoryStruct)];
|
|
|
|
// if((SectorCounter == 1) && (Counter == 0)) LastUsedSector = Entry->SectorAddress;
|
|
|
|
if((Entry->FileType > 0) && (Entry->FileType < 0x80))
|
|
{
|
|
memcpy(FileName, Entry->FileName, 17);
|
|
if(strchr(FileName, 0x0D) != NULL) *strchr(FileName, 0x0D) = '\0';
|
|
else FileName[17] = '\0';
|
|
|
|
printf(" %-17s %s %5u %c %04X %04X", FileName, FileTypes[Entry->FileType], Entry->FileSize, Entry->LockFlag ? 'X' : ' ', Entry->LoadAddress, Entry->ExecAddress);
|
|
S = Entry->SectorAddress % 16 + 1;
|
|
H = (Entry->SectorAddress / 16) % 2;
|
|
C = Entry->SectorAddress / 16 / 2;
|
|
printf(" %4u (%2u %u %2u)\n", Entry->SectorAddress, C, H, S);
|
|
}
|
|
}
|
|
}
|
|
// printf("\nLast used Sector: %u\n\n", LastUsedSector);
|
|
}
|
|
|
|
|
|
|
|
|
|
void CopyFDToMZF(char *FileName)
|
|
{
|
|
char MZFFileName[13];
|
|
char EntryFileName[18];
|
|
unsigned char SectorCounter, Counter;
|
|
FILE *MZFFile;
|
|
struct MZ700DirectoryStruct *Entry;
|
|
struct CMTHeader MZFHeader;
|
|
unsigned char C, H, S;
|
|
unsigned short WriteSize;
|
|
unsigned int Result;
|
|
|
|
|
|
S = 0;
|
|
|
|
Result = ReadSector(Drive, 0, 0, 1); // BootSector
|
|
Result = Result >> 8;
|
|
if(Result != 0) Error(Result);
|
|
SectorBuffer[33] = '\0'; // emergency stop
|
|
if(strstr(SectorBuffer, FileName) != NULL)
|
|
{
|
|
Entry = (struct MZ700DirectoryStruct *) SectorBuffer;
|
|
S = Entry->SectorAddress % 16 + 1;
|
|
H = (Entry->SectorAddress / 16) % 2;
|
|
C = Entry->SectorAddress / 16 / 2;
|
|
Entry->FileType = 1;
|
|
}
|
|
else
|
|
{
|
|
for(SectorCounter = 1; (SectorCounter < 17) && (S == 0); SectorCounter++)
|
|
{
|
|
ReadSector(Drive, 0, 1, SectorCounter);
|
|
|
|
for(Counter = 0; (Counter < 256 / 32) && (S == 0); Counter++)
|
|
{
|
|
Entry = (struct MZ700DirectoryStruct *) &SectorBuffer[Counter * sizeof(struct MZ700DirectoryStruct)];
|
|
if((Entry->FileType > 0) && (Entry->FileType < 0x80))
|
|
{
|
|
memcpy(EntryFileName, Entry->FileName, 17);
|
|
if(strchr(EntryFileName, 0x0D) != NULL) *strchr(EntryFileName, 0x0D) = '\0';
|
|
else EntryFileName[17] = '\0';
|
|
if(strcmp(FileName, EntryFileName) == 0)
|
|
{
|
|
S = Entry->SectorAddress % 16 + 1;
|
|
H = (Entry->SectorAddress / 16) % 2;
|
|
C = Entry->SectorAddress / 16 / 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(S != 0)
|
|
{
|
|
memset(MZFFileName, 0, sizeof(MZFFileName));
|
|
strncpy(MZFFileName, FileName, 8);
|
|
strcat(MZFFileName, ".MZF");
|
|
printf("%s found save it as %s\n", FileName, MZFFileName);
|
|
MZFFile = fopen(MZFFileName , "wb");
|
|
memset(&MZFHeader, 0, sizeof(MZFHeader));
|
|
if(Entry->FileType == 0x02) MZFHeader.Attribute = 0x05;
|
|
else MZFHeader.Attribute = Entry->FileType;
|
|
memcpy(MZFHeader.Name, Entry->FileName, 17);
|
|
MZFHeader.Size = Entry->FileSize;
|
|
strcat(MZFHeader.Comment, "by MZFDTool");
|
|
|
|
if((Entry->FileType == 0x01) && (Entry->LoadAddress == 0x0000))
|
|
{
|
|
MZFHeader.Comment[24] = 0x21;
|
|
MZFHeader.Comment[25] = 0x30;
|
|
MZFHeader.Comment[26] = 0x11;
|
|
|
|
MZFHeader.Comment[27] = 0x01;
|
|
MZFHeader.Comment[28] = 0x10;
|
|
MZFHeader.Comment[29] = 0x00;
|
|
|
|
MZFHeader.Comment[30] = 0x11;
|
|
MZFHeader.Comment[31] = 0xF0;
|
|
MZFHeader.Comment[32] = 0xCF;
|
|
|
|
MZFHeader.Comment[33] = 0xED;
|
|
MZFHeader.Comment[34] = 0xB0;
|
|
|
|
MZFHeader.Comment[35] = 0xC3;
|
|
MZFHeader.Comment[36] = 0xF0;
|
|
MZFHeader.Comment[37] = 0xCF;
|
|
|
|
|
|
|
|
MZFHeader.Comment[40] = 0x21;
|
|
MZFHeader.Comment[41] = 0x00;
|
|
MZFHeader.Comment[42] = 0x12;
|
|
|
|
MZFHeader.Comment[43] = 0x01;
|
|
MZFHeader.Comment[44] = (unsigned char) Entry->FileSize & 0xFF;
|
|
MZFHeader.Comment[45] = Entry->FileSize >> 8;
|
|
|
|
MZFHeader.Comment[46] = 0x11;
|
|
MZFHeader.Comment[47] = 0x00;
|
|
MZFHeader.Comment[48] = 0x00;
|
|
|
|
MZFHeader.Comment[49] = 0xD3;
|
|
MZFHeader.Comment[50] = 0xE0;
|
|
|
|
MZFHeader.Comment[51] = 0xED;
|
|
MZFHeader.Comment[52] = 0xB0;
|
|
|
|
MZFHeader.Comment[53] = 0xC3;
|
|
MZFHeader.Comment[54] = 0x00;
|
|
MZFHeader.Comment[55] = 0x00;
|
|
|
|
MZFHeader.LoadAddress = 0x1200;
|
|
MZFHeader.ExecAddress = 0x1120;
|
|
}
|
|
else
|
|
{
|
|
MZFHeader.LoadAddress = Entry->LoadAddress;
|
|
MZFHeader.ExecAddress = Entry->ExecAddress;
|
|
}
|
|
fwrite(&MZFHeader, sizeof(MZFHeader), 1, MZFFile);
|
|
|
|
while(MZFHeader.Size != 0)
|
|
{
|
|
WriteSize = 256;
|
|
if(MZFHeader.Size < WriteSize) WriteSize = MZFHeader.Size;
|
|
MZFHeader.Size = MZFHeader.Size - WriteSize;
|
|
ReadSector(Drive, C, H, S);
|
|
fwrite(SectorBuffer, WriteSize, 1, MZFFile);
|
|
S++;
|
|
if(S == 17)
|
|
{
|
|
S = 1;
|
|
if(H == 0) H = 1;
|
|
else
|
|
{
|
|
C++;
|
|
H = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(MZFFile);
|
|
}
|
|
else
|
|
{
|
|
puts("");
|
|
printf("%s not found!\n", FileName);
|
|
puts("");
|
|
puts("Remember that capital letters are differenced!");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void CopyMZFToFD(char *FileName)
|
|
{
|
|
printf("Not implemented yet (%s)\n", FileName);
|
|
}
|
|
|
|
|
|
|
|
|
|
void Copy(char *FileName)
|
|
{
|
|
if((strstr(FileName, ".MZF") == NULL) && (strstr(FileName, ".mzf") == NULL)) CopyFDToMZF(FileName);
|
|
else CopyMZFToFD(FileName);
|
|
}
|
|
|
|
|
|
|
|
|
|
void ShowMap(void)
|
|
{
|
|
unsigned short UsedSectors;
|
|
unsigned short Counter;
|
|
unsigned char BitCounter;
|
|
// unsigned char BitMask;
|
|
unsigned short BitMask;
|
|
unsigned short *SectorsPerTrack;
|
|
unsigned char StartTrack;
|
|
unsigned int Result;
|
|
|
|
|
|
puts("");
|
|
|
|
Result = ReadSector(Drive, 0, 0, 16);
|
|
Result = Result >> 8;
|
|
if(Result != 0) Error(Result);
|
|
UsedSectors = SectorBuffer[3] * 256 + SectorBuffer[4];
|
|
StartTrack = SectorBuffer[5];
|
|
|
|
printf("Volume: %c%c%c Used Sectors: %4u\n\n", SectorBuffer[0], SectorBuffer[1], SectorBuffer[2], UsedSectors);
|
|
puts("");
|
|
|
|
puts(" 1111111");
|
|
puts("Track ( C H S) 1234567890123456");
|
|
puts("");
|
|
|
|
for(Counter = StartTrack; Counter <= 80; Counter++)
|
|
{
|
|
printf(" %3d (%2d %s 1) ", Counter, (Counter - 1) / 2, (Counter - 1) % 2 ? "1" : "0");
|
|
BitMask = 0x0001;
|
|
SectorsPerTrack = (unsigned short *) &SectorBuffer[6 + 2 * (Counter - StartTrack)];
|
|
|
|
for(BitCounter = 0; BitCounter < 16; BitCounter++)
|
|
{
|
|
if(*SectorsPerTrack & BitMask) printf("X");
|
|
else printf("-");
|
|
BitMask = BitMask << 1;
|
|
}
|
|
puts("");
|
|
}
|
|
|
|
puts("");
|
|
}
|
|
|
|
|
|
|
|
|
|
void Init(void)
|
|
{
|
|
memset(SectorBuffer, 0, sizeof(SectorBuffer));
|
|
Drive = 0;
|
|
Cylinder = 0;
|
|
Head = 0;
|
|
Sector = 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Usage(void)
|
|
{
|
|
puts("usage: mzfdtool dir [DRIVE:]");
|
|
puts(" map [DRIVE:]");
|
|
puts(" copy [DRIVE:] FILENAME");
|
|
puts(" DRIVE: C H S");
|
|
puts("");
|
|
exit(1);
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
unsigned int Result;
|
|
|
|
|
|
printf("\nMZFDTool V %s (c) 2002 by BKK\n\n", VERSION);
|
|
|
|
if(argc == 1) Usage();
|
|
|
|
Init();
|
|
|
|
SetInt1E(0);
|
|
|
|
ResetFloppy(Drive);
|
|
|
|
if(strcmp(argv[1], "dir") == 0)
|
|
{
|
|
if(argc == 3)
|
|
if(toupper(argv[2][0]) == 'B') Drive = 1;
|
|
ShowDirectory();
|
|
}
|
|
else
|
|
{
|
|
if(strcmp(argv[1], "copy") == 0)
|
|
{
|
|
if(argc == 4)
|
|
{
|
|
if(toupper(argv[2][0]) == 'B') Drive = 1;
|
|
Copy(argv[3]);
|
|
}
|
|
else Copy(argv[2]);
|
|
}
|
|
else
|
|
{
|
|
if(strcmp(argv[1], "map") == 0)
|
|
{
|
|
if(argc == 3)
|
|
if(toupper(argv[2][0]) == 'B') Drive = 1;
|
|
ShowMap();
|
|
}
|
|
else
|
|
{
|
|
if(argc < 3) exit(1);
|
|
|
|
if(toupper(argv[1][0]) == 'B') Drive = 1;
|
|
Cylinder = atoi(argv[2]);
|
|
Head = atoi(argv[3]);
|
|
Sector = atoi(argv[4]);
|
|
|
|
printf("Drive: %c CHS: %u %u %u\n", Drive ? 'B' : 'A', Cylinder, Head, Sector);
|
|
|
|
// Set_Floppy_Medis_Type();
|
|
|
|
Result = ReadSector(Drive, Cylinder, Head, Sector);
|
|
Result = Result >> 8;
|
|
|
|
if(Result == 0) ShowSectorBuffer();
|
|
else Error(Result);
|
|
}
|
|
}
|
|
}
|
|
|
|
ResetInt1E();
|
|
ResetFloppy(Drive);
|
|
|
|
return(0);
|
|
} |