/* * rawrite98.c Write a binary image to diskette * Version 1.2 * Copyright (c) KATO Takenori, 1995, 1996. 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++ 3.1 small model. */ /* * History: * Version 1.2: * support 1.44MB diskette * Verions 1.1: * bug fix */ #include #include #include #include #include #include #include /* error code */ #define ECM 0x10 #define EDB 0x20 #define EEN 0x30 #define EEC 0x40 #define EOR 0x50 #define ENR 0x60 #define ENW 0x70 #define EDE 0xA0 #define END 0xC0 #define EMA 0xE0 #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; }; struct mediainfo_t minfo[] = { /* Order might be important. See testmediatype() routine */ {0x90, 15}, /* 1.2MB on 1MB I/F */ {0x10, 15}, /* 1.2MB on 720KB I/F */ {0x30, 18}, /* 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) { struct diskinfo dp; int retcode; int i; for (i = 0; i < MAXMEDIATYPE; i++) { dp.cmd = 0x5a; /* read ID */ dp.devtype = (duda & 0x0f) | minfo[i].da; dp.cylnum = 0; dp.headnum = 0; retcode = pc98disk(&dp); if (((retcode & 0xff00) == 0) && ((dp.seclen & 0xff) == 2)) { /* No error and 512 bytes/sector */ return i; } } if ((retcode & 0xff00) != 0) return (retcode & 0x00ff); /* Disk BIOS Error */ if ((dp.seclen & 0xff) != 2) return -1; /* Not 512 bytes/sector */ /* NOT REACHED */ return -1; } int writedata(char *buffer, FILE* fp, unsigned char duda, int type) { struct diskinfo dp; 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; 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); if (retcode & 0xff00) { errormsg(retcode & 0x00f0, ""); return 1; } if (flag == 1) break; head++; head &= 1; if (head == 0) cylinder++; } return 0; } int main(void) { char fname[MAXPATH]; char *buffer, *abuffer; int count, drive, type; unsigned char duda; unsigned char far* dosparameter; FILE* fp; printf("RaWrite(98) 1.2 - Write disk file to raw diskette\n"); printf("(C)Copyright KATO Takenori, 1995, 1996.\n"); printf("All rights reserved.\n\n"); printf("Enter source file name: "); scanf("%s", fname); _fmode = O_BINARY; if ((fp = fopen(fname, "r")) == NULL) { errormsg(ENoFile, fname); return 1; } printf("Enter destination drive: "); scanf("%s", fname); 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; } /* Check DMA boundary */ if ((_DS + ((unsigned int)buffer >> 4) & 0x0fff) > 0xdc0) buffer += 18 * 512; 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); if (type == EUnsupport) { /* This program support 1200KB and 1440KB diskette */ fclose(fp); errormsg(EUnsupport, ""); return 1; } if (type == -1) { /* 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; } if (writedata(buffer, fp, duda, type)) { fclose(fp); free(abuffer); printf("Terminated by error.\n"); return 1; } fclose(fp); free(abuffer); printf("Done.\n"); return 0; }