/* * rawrite98.c Write a binary image to diskette * Version 1.3 * Copyright (c) KATO Takenori, 1995, 1996, 2000. 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 as * the first lines of this file unmodified. * 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. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. * * This source code is specific to BORLAND C++ 5.0 small model. */ /* * History: * Version 1.3: * Fixed the bug in DMA boundary check. * BC++ 3 -> BC++ 5 * Version 1.2: * Supported 1.44MB diskette * Verions 1.1: * Fixed bugs. */ #include #include #include #include #if __BORLANDC__ < 0x400 #include #else #define _BIOS_NECPC #include #endif #include #include #include /* error code */ #define ECM 0x0010 #define EDB 0x0020 #define EEN 0x0030 #define EEC 0x0040 #define EOR 0x0050 #define ENR 0x0060 #define ENW 0x0070 #define EDE 0x00A0 #define END 0x00C0 #define EMA 0x00E0 #define ENoFile 0x1000 #define EUnsupport 0x2000 #define ENo1MIF 0x3000 #define ENoMem 0x4000 #define ENoFDD 0x5000 #define MEDIA_1200 0 #define MEDIA_1200_A 1 #define MEDIA_1440 2 #define MAXMEDIATYPE 3 struct mediainfo_t { unsigned char da; int nsec; char* size; }; struct mediainfo_t minfo[] = { /* Order might be important. See testmediatype() routine */ {0x90, 15, "1.2MB"}, /* 1.2MB on 1MB I/F */ {0x10, 15, "1.2MB"}, /* 1.2MB on 720KB I/F */ {0x30, 18, "1.4MB"}, /* 1.4MB on 1MB I/F */ }; void errormsg(int errorcode, char* fname) { switch(errorcode) { case ECM: fprintf(stderr, "Control Mark\n"); break; case EDB: fprintf(stderr, "DMA Boundary\n"); break; case EEN: fprintf(stderr, "End of Cylinder\n"); break; case EEC: fprintf(stderr, "Equipment Check\n"); break; case EOR: fprintf(stderr, "Over Run\n"); break; case ENR: fprintf(stderr, "Not Ready\n"); break; case ENW: fprintf(stderr, "Not Writable\n"); break; case EDE: fprintf(stderr, "Data Error\n"); break; case END: fprintf(stderr, "No Data\n"); break; case EMA: fprintf(stderr, "Missing Address mark\n"); break; case ENoFile: fprintf(stderr, "File not found: %s\n", fname); break; case ENo1MIF: fprintf(stderr, "Device not configured\n"); break; case EUnsupport: fprintf(stderr, "Unsupported media type\n"); break; case ENoMem: fprintf(stderr, "Not enough memory\n"); break; case ENoFDD: fprintf(stderr, "Not FDD\n"); break; default: fprintf(stderr, "Unknown Error 0x%0x\n", errorcode); break; } } /* test media type */ int testmediatype(unsigned char duda, int verbose) { #if __BORLANDC__ < 0x400 struct diskinfo dp; #else union REGS regs; #endif int retcode; int seclen; int i; for (i = 0; i < MAXMEDIATYPE; i++) { #if __BORLANDC__ < 0x400 dp.cmd = 0x5a; /* read ID */ dp.devtype = (duda & 0x0f) | minfo[i].da; dp.cylnum = 0; dp.headnum = 0; retcode = pc98disk(&dp); seclen = dp.seclen; #else regs.h.ah = 0x7a; regs.h.al = (duda & 0x0f) | minfo[i].da; regs.h.cl = 0; regs.h.dh = 0; int86(0x1b, ®s, ®s); if (regs.x.cflag) retcode = 0xff00 | regs.h.ah; else retcode = 0; seclen = regs.h.ch; #endif if ((retcode & 0xff00) == 0) { if (verbose) printf("\nFound %s diskette.\n", minfo[i].size); if ((seclen & 0xff) == 2) { /* No error and 512 bytes/sector */ return i; } else { return EUnsupport; } } } /* XXX */ if ((retcode & 0xff00) != 0) return retcode; /* Disk BIOS Error */ if ((seclen & 0xff) != 2) return EUnsupport; /* Not 512 bytes/sector */ /* NOT REACHED */ return -1; } int writedata(char *buffer, FILE* fp, unsigned char duda, int type, int verbose) { #if __BORLANDC__ < 0x400 struct diskinfo dp; #else unsigned char disk_result[32]; struct diskinfo_t dinfo; #endif int cylinder, head; int flag, retcode; flag = 0; head = cylinder = 0; while (cylinder < 80) { if (fread(buffer, 512, minfo[type].nsec, fp) < minfo[type].nsec) flag = 1; if (verbose) printf("C:%02d H:%02d\n", cylinder, head); #if __BORLANDC__ < 0x400 dp.cmd = 0xd5; dp.devtype = duda; dp.datalen = 512 * minfo[type].nsec; dp.seclen = 2; dp.cylnum = cylinder; dp.headnum = head; dp.secnum = 1; dp.databuf = buffer; retcode = pc98disk(&dp); #else dinfo.command = _CMD_SEEK | _CMD_RETRY | _CMD_MF | _CMD_MT; dinfo.drive = duda; dinfo.head = head; dinfo.cylinder = cylinder; dinfo.data_len = 512 * minfo[type].nsec; dinfo.sector_len = 2; dinfo.sector = 1; dinfo.nsectors = minfo[type].nsec; dinfo.buffer = MK_FP(_DS, buffer); dinfo.result = MK_FP(_DS, &disk_result); retcode = _bios_disk(_DISK_WRITE, &dinfo); #endif if (retcode & 0xff00) { errormsg(retcode & 0x00f0, ""); return 1; } if (flag == 1) break; head++; head &= 1; if (head == 0) cylinder++; } return 0; } int main(int argc, char* argv[]) { char fname[MAXPATH]; char *buffer, *abuffer; int drive, type, verbose; unsigned char duda; unsigned char far* dosparameter; FILE* fp; printf("RaWrite(98) 1.3 - Write disk file to raw diskette\n"); printf("(C)Copyright KATO Takenori, 1995, 1996, 2000.\n"); printf("All rights reserved.\n\n"); if (strcmp(argv[argc - 1], "-v") == 0) { argc--; verbose = 1; } else { verbose = 0; } if (argc < 2) { printf("Enter source file name: "); scanf("%s", fname); } else strncpy(fname, argv[1], MAXPATH); _fmode = O_BINARY; if ((fp = fopen(fname, "r")) == NULL) { errormsg(ENoFile, fname); return 1; } if (argc < 3) { printf("Enter destination drive: "); scanf("%s", fname); } else strncpy(fname, argv[2], 1); drive = fname[0]; drive = toupper(drive) - 'A'; /* Get DA/UA */ dosparameter = (unsigned char far*)MK_FP(0x60, 0x6c + drive); duda = *dosparameter; /* Is it FDD? */ switch (duda & 0xf0) { case 0x90: case 0xf0: case 0x30: /* Yes, nothing to do */ break; default: fclose(fp); errormsg(ENoFDD, ""); return 1; } /* We need to check unit number */ if ((duda & 0x0f) > 3) { fclose(fp); errormsg(ENoFDD, ""); return 1; } printf("Please insert a formatted diskette into drive %c and " "press RETURN key : ", drive + 'A'); (void)flushall(); (void)fgetc(stdin); /* Check Media type */ type = testmediatype(duda, verbose); if (type == EUnsupport) { /* This program support 1200KB and 1440KB diskette */ fclose(fp); errormsg(EUnsupport, ""); return 1; } if (type & 0xff00) { /* Disk BIOS error */ fclose(fp); errormsg(type & 0xf0, ""); return 1; } /* OK, adjust DU/DA */ duda &= 0x0f; duda |= minfo[type].da; if ((abuffer = buffer = malloc(18 * 512 * 2)) == NULL) { fclose(fp); errormsg(ENoMem, ""); return 1; } /* Check DMA boundary */ if ((_DS + ((unsigned int)buffer >> 4) & 0x0fff) > 0xdc0) buffer += 18 * 512; if (writedata(buffer, fp, duda, type, verbose)) { fclose(fp); free(abuffer); printf("Terminated by error.\n"); return 1; } fclose(fp); free(abuffer); printf("Done.\n"); return 0; }