home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1995 November
/
PCWK1195.iso
/
inne
/
podstawy
/
dos
/
format
/
2m30src.exe
/
2MF.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-06
|
50KB
|
1,386 lines
/*───────────────────────────────────────────────────────────────────\
│ │
│ █████ █ █ █▀▀▀▀ │
│ █ ██ ██ █ │
│ █████ █ █ █ █▀▀ │
│ █ █ █ █ │
│ █████ █ █ █ │
│ │
│ 2MF.C 3.0 - UTILIDAD DE FORMATEO DE DISQUETES 2M │
│ │
│ (C) 1993-1995 Ciriaco García de Celis. │
│ │
│ - Para cualquier Turbo C o Borland C en modelo de memoria LARGE. │
│ - Este programa se compila abriendo un proyecto e introduciendo │
│ en él 2MF.C y 2MFKIT.OBJ │
│ - Importante: no activar ciertas optimizaciones que no lo están │
│ por defecto (como la de alineamiento a palabra o la de salto). │
│ │
│ - NOTA: Las funciones de bajo nivel que acceden directamente a │
│ la controladora de disquetes no son indispensables, tan │
│ sólo se emplean para producir menos ruido al detectar │
│ la introducción de un nuevo disquete en la unidad. │
│ │
│ Este programa detecta además la presencia de una posible │
│ utilidad de intercambio de unidades A:-B: llamada FDSWAP │
│ para que en caso de estar activado dicho intercambio sea │
│ posible acceder a la unidad física correspondiente. │
│ │
\───────────────────────────────────────────────────────────────────*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <bios.h>
#include <time.h>
#include <alloc.h>
#include <conio.h>
#include <io.h>
#include <fcntl.h>
#define CARDWARE 100 /* nº discos formateados antes del aviso */
#define MAXSECT 46 /* máximo número de sectores por pista */
#define MAXFAT 6128 /* mayor FAT de 12 bits posible */
#define BOOT2M 80 /* bytes principales del Boot */
#define FD_DATA 0x3F5 /* registro de datos del 765 */
#define FD_STATUS 0x3F4 /* registro principal de estado del 765 */
#define FD_DOR 0x3F2 /* registro de salida digital */
#define FD_DIR 0x3F7 /* registro de entrada digital (RD) */
#define FD_DCR 0x3F7 /* registro de control del disquete (WR) */
typedef struct { /* sector arranque disquetes 2M */
unsigned char Salto[3], IdSis[8];
short BytesSect;
char SectCluster;
short SectReserv;
char NumFats;
short FichRaiz, NumSect;
char MediaId;
short SectFat, SectPista, Caras;
long Especiales, Sect32;
char Unidad, Reservado, Flag;
long NumSerie;
char Titulo[11], TipoFat[8];
char Flags;
char CheckSum;
char VersionFmt, FlagWr, VelPista0, VelPistaX;
short OffsetJmp, OffsetPista0, OffsetPistaX, OffsetListaTam;
unsigned short FechaF;
unsigned short HoraF;
char Resto[512-BOOT2M]; /* depende del tamaño de lo anterior */
} Boot;
typedef struct { /* entrada de directorio */
char Etiqueta[11];
char Tipo;
char Reservado[10];
int Hora;
int Fecha;
char Resto[6];
} Root;
typedef struct { /* parámetros en línea de comandos */
int Unidad, UnidadLogica,
HD, ED, TipoFmt,
NoVerify, MarcaPoco,
Pistas, FichRaiz, Silencioso, NoPausa, NoTecla, X, Y, G,
Tipoetiq, NoFlash, Rapido;
char Volumen[12];
} Parametros;
int HablaSp (void),
Hay2m (void),
Hay2mBoot (void),
FdswapOn (void),
TipoDrive (int),
EsperarCambioDisco (int, int),
infdc (void),
ValeDensidad (Boot *, Parametros *),
FormatearDisco (Boot *,unsigned char far *,unsigned char far *,
Parametros *, long *, int *),
MarcaFat (int, int, Boot *, int, int, unsigned char far *,
unsigned char far *, long *),
InicializaDisco (int, Boot *, unsigned char far *,
unsigned char far *);
void Ayuda (void),
ProcesarParametros (int, char **, Parametros *),
DetectaMedio (Parametros *, Boot *),
CrearSector0 (Boot *, Parametros),
DiagnosticoError (int),
InformeDisco (Boot *, Parametros *, long, int),
IncrementarEtiqueta (Parametros *),
SonidoSube (void),
SonidoBaja (void),
SonidoError (void),
SonidoOn (void),
SonidoOff (void),
Sonido (int),
posicionar (int, int),
outfdc (unsigned char),
EsperarInt (void),
CardWare (char *, int);
extern BootHDPrg, BootHDPrgLong, BootDDPrg, BootDDPrgLong,
Boot2mCode, Boot2mLong,
biosdsk (int, int, int, int, int, int, void far *);
void interrupt NuevaInt24 (void);
extern void PicoRetardo (void), interrupt (*ViejaInt24) (void);
int sp; /* 1-español 0-inglés */
unsigned long far *cbios=MK_FP(0x40, 0x6C); /* reloj del sistema */
unsigned char far *irq6=MK_FP(0x40, 0x3E); /* flag BIOS de IRQ6 */
void main (int argc, char **argv)
{
Boot sector0;
Parametros cmd;
int salir, result, sg, detectar, tec;
long bytes_err, dir;
unsigned char far *buffer; /* para contener toda una pista */
unsigned char far *fat; /* para contener toda la FAT */
int disquetes=0; /* nº discos formateados */
void interrupt
(*ViejaInt24) (void);
sp=HablaSp(); /* determinar idioma del país */
ProcesarParametros (argc, argv, &cmd);
if (!Hay2m())
if (!Hay2mBoot()) {
if (sp)
printf(" 2M ó 2MX 3.0 no está instalado, imposible formatear.\n");
else
printf(" 2M or 2MX 3.0 is not installed, impossible to format.\n");
exit(128);
}
else {
if (sp)
printf(" Modo SuperBOOT: instale 2M para dar formato.\n");
else
printf(" SuperBOOT mode: needed to install 2M to format.\n");
exit(127);
}
if (((fat=farmalloc( (unsigned long) MAXFAT))==NULL) ||
((buffer=farmalloc( (unsigned long) MAXSECT<<10))==NULL)) {
if (sp) printf(" Memoria insuficiente.\n");
else printf(" Insufficient memory.\n");
exit(126);
}
/* Definir el buffer para que no cruce una frontera de DMA */
dir = ((unsigned long) FP_SEG(buffer) <<4) + FP_OFF(buffer);
if ((dir >> 16) != ((dir + ((unsigned long) MAXSECT << 9)) >> 16))
buffer+=(unsigned long) MAXSECT << 9;
if (!cmd.NoPausa) {
if (sp)
printf(" Pulsa INTRO para formatear en");
else
printf(" Press ENTER to format on");
printf(" %c:", cmd.UnidadLogica+'A');
tec=getch(); if (!tec) tec=getch()<<8;
salir = (tec!=13);
}
else
salir=0;
/* si no se indica densidad detectarla */
detectar = (cmd.HD==-1);
/* formateo de múltiples disquetes */
while (!salir) {
if (detectar) DetectaMedio (&cmd, §or0);
CrearSector0 (§or0, cmd);
if (!cmd.Silencioso) SonidoSube();
switch (result=FormatearDisco (§or0, fat, buffer, &cmd,
&bytes_err, &sg)) {
case 0: InformeDisco (§or0, &cmd, bytes_err, sg);
if (!cmd.Silencioso) SonidoBaja();
if (cmd.Tipoetiq==2) IncrementarEtiqueta (&cmd);
disquetes++;
break;
case 1: DiagnosticoError (result);
break;
default: DiagnosticoError (result);
if (!cmd.Silencioso) SonidoError(); break;
}
if (cmd.NoTecla)
salir=1;
else {
if (sp)
printf("\n Introduce otro disquete para formatear en");
else
printf("\n Please insert another disk to format in");
printf(" %c:", cmd.UnidadLogica+'A');
if (!EsperarCambioDisco(cmd.Unidad, cmd.NoFlash)) salir=1;
}
}
printf("\r \r");
ViejaInt24=getvect(0x24);
setvect (0x24, NuevaInt24); /* evitar error crítico */
CardWare (argv[0], disquetes); /* intentar actualizar 2MF.EXE */
setvect (0x24, ViejaInt24);
}
void ProcesarParametros (int argc, char **argv, Parametros *cmd)
{
unsigned char drv[128];
int pm, error=0, hlp=0, id=1, disco;
union REGS r;
struct SREGS s;
cmd->Unidad=cmd->TipoFmt=cmd->ED=cmd->NoVerify=cmd->MarcaPoco=\
cmd->FichRaiz=cmd->Silencioso=cmd->NoFlash=\
cmd->NoPausa=cmd->NoTecla=cmd->Tipoetiq=cmd->Rapido=0;
cmd->HD=-1; cmd->Pistas=82;
cmd->X=cmd->Y=cmd->G=-1;
for (pm=1; pm<argc; pm++)
if (strstr(&argv[pm][1], "/")!=NULL) error=-1; /* parámetros unidos */
if (!error) {
for (pm=1; pm<argc; pm++) {
if ((strstr(argv[pm],"/L")!=NULL) || (strstr(argv[pm],"/l")!=NULL)) {
strncpy (cmd->Volumen, &argv[pm][3], 11);
cmd->Volumen[11]=0;
while (strlen(cmd->Volumen)<11) strcat(cmd->Volumen, " ");
cmd->Tipoetiq=1;
continue;
}
else if ((strstr(argv[pm],"/V")!=NULL) || (strstr(argv[pm],"/v")!=NULL)) {
strncpy (cmd->Volumen, &argv[pm][3], 11);
cmd->Volumen[11]=0;
while (strlen(cmd->Volumen)<11) strcat(cmd->Volumen, " ");
cmd->Tipoetiq=2;
continue;
}
strupr (argv[pm]);
if (strstr(argv[pm],"/?")!=NULL) hlp++;
else if ((strstr(argv[pm],"/H")!=NULL) && (strlen(argv[pm])==2)) hlp++;
else if (strstr(argv[pm],":")!=NULL)
for (disco='A'; disco <= 'Z'; disco++) {
drv[0]=disco; drv[1]=':'; drv[2]=0;
if ((strstr(argv[pm], drv)!=NULL) &&
(strstr(argv[pm], "/")==NULL)) cmd->Unidad=*argv[pm]-'A';
}
else if (strstr(argv[pm],"/HD")!=NULL) cmd->HD=1;
else if (strstr(argv[pm],"/DD")!=NULL) cmd->HD=0;
else if (strstr(argv[pm],"/D0")!=NULL) cmd->HD=2;
else if (strstr(argv[pm],"/D1")!=NULL) cmd->HD=3;
else if (strstr(argv[pm],"/F")!=NULL) cmd->TipoFmt=0;
else if (strstr(argv[pm],"/M")!=NULL) cmd->TipoFmt=1;
else if (strstr(argv[pm],"/ED")!=NULL) cmd->ED=1;
else if (strstr(argv[pm],"/N")!=NULL) cmd->NoVerify=1;
else if (strstr(argv[pm],"/W")!=NULL) cmd->MarcaPoco=1;
else if (strstr(argv[pm],"/T")!=NULL)
cmd->Pistas = atoi (&argv[pm][3]);
else if (strstr(argv[pm],"/R")!=NULL)
cmd->FichRaiz = atoi (&argv[pm][3]);
else if (strstr(argv[pm],"/S")!=NULL) { cmd->Silencioso=1; id++; }
else if (strstr(argv[pm],"/K")!=NULL) cmd->NoPausa=1;
else if (strstr(argv[pm],"/J")!=NULL) cmd->NoTecla=1;
else if (strstr(argv[pm],"/Z")!=NULL) cmd->NoFlash=1;
else if (strstr(argv[pm],"/X")!=NULL) cmd->X=atoi(&argv[pm][3]);
else if (strstr(argv[pm],"/Y")!=NULL) cmd->Y=atoi(&argv[pm][3]);
else if (strstr(argv[pm],"/G")!=NULL) cmd->G=atoi(&argv[pm][3]);
else if (strstr(argv[pm],"/I")!=NULL) { sp^=1; id++; }
else if (strstr(argv[pm],"/Q")!=NULL) cmd->Rapido++;
else error=1;
}
}
cmd->UnidadLogica = cmd->Unidad;
if (cmd->Unidad > 1) {
r.x.ax = 0x440D; r.x.bx = cmd->Unidad+1; r.x.cx = 0x860;
s.ds = r.x.si = FP_SEG (drv);
r.x.dx = r.x.di = FP_OFF (drv); drv[0]=0;
intdosx (&r, &r, &s);
if ((!(r.x.flags & 1)) && (
(drv[6]=='2'+'M') || (drv[6]=='2'+'M'+1)
)
) cmd->Unidad = drv[6] - ('2'+'M'); /* unidad 2MGUI */
}
if (cmd->ED && (cmd->HD!=1)) cmd->HD=1; /* /DD ó /Dx + /E = /E */
if ((argc<=1) || (argc==id)) hlp++;
if (hlp) Ayuda();
if (sp)
printf("\n2MF 3.0 - Utilidad de formateo de disquetes 2M (ESC Salir)\n");
else
printf("\n2MF 3.0 - Format utility program for 2M diskettes (ESC Aborts)\n");
if (error==1) {
if (sp)
printf(" Error de sintaxis. Ejecute 2MF /?.\n");
else
printf(" Incorrect parameter(s). Execute 2MF /?.\n");
exit (2);
}
if (error==-1) {
if (sp)
printf(" Error: Los parámetros deben separarse por espacios.\n");
else
printf(" Error: Parameters must be separated by blank spaces.\n");
exit (2);
}
if (cmd->Unidad > 1) {
if (sp)
printf(" La unidad lógica indicada no es una disquetera.\n");
else
printf(" Logical drive indicated does not is a diskette drive.\n");
exit (2);
}
if (TipoDrive(cmd->Unidad)==0) {
if (sp)
printf(" La unidad física indicada no existe.\n");
else
printf(" Physical drive indicated does not exist.\n");
exit (2);
}
if ((TipoDrive(cmd->Unidad)!=2) && (TipoDrive(cmd->Unidad)<4)) {
if (sp)
printf(" La unidad indicada no es de alta densidad.\n");
else
printf(" Drive indicated it is not high density one.\n");
exit (2);
}
if ((TipoDrive(cmd->Unidad)<5) && (cmd->ED==1)) {
if (sp)
printf(" Necesaria unidad de 2.88M para formato ED.\n");
else
printf(" Needs a 2.88M drive to perform ED format.\n");
exit (2);
}
if ((cmd->Pistas<80) || (cmd->Pistas>86)) {
if (sp)
printf(" Error: Número de pistas incorrecto.\n");
else
printf(" Error: Incorrect number of tracks.\n");
exit (2);
}
if (cmd->FichRaiz && ((cmd->FichRaiz<1) || (cmd->FichRaiz>240))) {
if (sp)
printf(" Error: Nº de ficheros en directorio raiz erróneo.\n");
else
printf(" Error: Bad number of files in root directory.\n");
exit (2);
}
}
void Ayuda()
{
if (sp) {
printf("\n\n"
" 2MF 3.0 - UTILIDAD ESTANDAR DE FORMATEO DE DISQUETES PARA 2M\n"
" (C) 1993-1995 Ciriaco García de Celis - Grupo Universitario de Informática\n"
" C/Renedo, 2, 4-C; 47005 Valladolid (España) - ciri@gui.uva.es - 2:341/21.8\n\n"
" 2MF U: [/HD|DD|ED] [/F|M] [/N] [/L|V=etiq] [/S] [/Z] [/R=nn] [/T=nn] [/K] [/J]\n\n"
" Este programa formatea disquetes a una mayor capacidad y/o velocidad de la\n"
" normal. Para que estos nuevos disquetes funcionen debe estar instalado 2M en\n"
" memoria. Alternativamente, si son de alta densidad se pueden dejar dentro de\n"
" la unidad A: y reinicializar el ordenador, que botará pese a todo del disco\n"
" duro y podrá acceder a los disquetes 2M sin problemas en lectura/escritura.\n\n"
" /HD Formateo en alta densidad (por defecto si 2MF no detecta la densidad).\n"
" /DD Fuerza el formateo en doble densidad (aunque 2MF quizá la detecte).\n"
" /ED Formatear disquetes de 3½-ED (3608K por defecto o 3772K indicando /M).\n"
" /F Disquetes rápidos y seguros -por defecto- (5¼:820-1476K, 3½:984-1804K).\n"
" /M Formatear disquetes a la máxima capacidad (5¼:902-1558K, 3½:1066-1886K).\n"
" /N No verificar el disquete destino (peligroso en modo /M).\n"
" /L Poner etiqueta de volúmen al disco destino (minúsculas permitidas).\n"
" /V Etiqueta incremental en series de discos (si termina en número).\n"
" /S Funcionamiento silencioso /Z Evitar parpadeo de LED de disco.\n"
" /R Elegir nº ficheros raíz (1-240) /T Cambiar número de pistas (80-86).\n"
" /K No realizar pausa inicial /J No realizar pausa final.\n");
}
else {
printf("\n\n"
" 2MF 3.0 - STANDARD FORMAT UTILITY FOR 2M DISKETTES\n"
" (C) 1993-1995 Ciriaco García de Celis - Grupo Universitario de Informática\n"
" C/Renedo, 2, 4-C; 47005 Valladolid (Spain) - ciri@gui.uva.es - 2:341/21.8\n\n"
" 2MF U: [/HD|DD|ED] [/F|M] [/N] [/L|V=label] [/S][/Z] [/R=nn] [/T=nn] [/K][/J]\n\n"
" This program formats diskettes at a higher capacity and/or speed than the\n"
" normal ones. 2M must be installed on memory to provide support for the new\n"
" diskettes. Also, high-density diskettes can be left into A: drive and then\n"
" computer can be rebooted: really it will boot from hard disk and after this\n"
" moment 2M diskettes will be supported in the standard read-write operation.\n\n"
" /HD High density format (by default if 2MF can't detect diskette density).\n"
" /DD Request a double-density format (but 2MF perhaps can detect DD disk).\n"
" /ED Formats 3.5-ED diskettes at 3608K (or 3772K if /M option enabled).\n"
" /F Fast and reliable diskettes -by default- (5¼:820-1476K, 3½:984-1804K).\n"
" /M Formats diskettes up to maximum capacity (5¼:902-1558K, 3½:1066-1886K).\n"
" /N Do not verify target diskette (dangerous in /M mode).\n"
" /L Sets diskette volume label (case sensitive).\n"
" /V Automatic sequencing of labels (if specified one is number terminated).\n"
" /S Tells 2MF not to make sound effects /Z Turn disk LED «flashing» off.\n"
" /R Sets root entries number (1-240) /T Sets number of tracks (80-86).\n"
" /K No initial pause before formatting /J No end pause after formatting.\n");
}
exit (1);
}
int Hay2m() /* devolver 1 si 2M está instalado */
{
int entrada, instalado=0;
union REGS r; struct SREGS s;
for (entrada=0xc0; (entrada<=0xff) && (!instalado); entrada++) {
r.x.ax=entrada << 8; s.es=0x1492; r.x.di=0x1992;
int86x (0x2f, &r, &r, &s);
if (r.x.ax==0xFFFF)
if ((peek(s.es,r.x.di-4)==9002) && (peek(s.es,r.x.di-2)==10787))
if (strstr (MK_FP(s.es, r.x.di),"2M:3.0")) instalado=1;
if (strstr (MK_FP(s.es, r.x.di),"2MX:3.0")) instalado=1;
}
return (instalado);
}
int Hay2mBoot() /* devolver 1 si 2M instalado en modo SuperBOOT */
{
return (strstr(MK_FP(((unsigned) peek(0x40, 0x13) * 64), 4),
"2M-STV")!=NULL);
}
int FdswapOn() /* devolver 1 si FDSWAP 1.1+ está instalado y activo */
{
int entrada, instalado=0;
union REGS r; struct SREGS s;
for (entrada=0xc0; (entrada<=0xff) && (!instalado); entrada++) {
r.x.ax=entrada << 8; s.es=0x1492; r.x.di=0x1992;
int86x (0x2f, &r, &r, &s);
if (r.x.ax==0xFFFF)
if ((peek(s.es,r.x.di-4)==9002) && (peek(s.es,r.x.di-2)==10787))
if (strstr (MK_FP(s.es, r.x.di),":FDSWAP:")) instalado=1;
}
return ((instalado) && (peekb(s.es, peek(s.es,r.x.di-6)-1)==1));
}
void CrearSector0 (Boot *s0, Parametros cmd)
{
unsigned tipo, tabla, i, j, k, m, t, s, tam, ini, fin, inc;
char id[8]="2M-STV00", ch, sum, far *p;
struct time h;
struct date f;
static unsigned char infofis [2][3][2][4][20] =
{{{{{10,176,7,0,1,1}, {9,80,1,1}, /* 5¼-DD /F */
{5,100,3,1,1} },
{{11,176,7,1,1,1}, {9,80,1,1}, /* /M */
{32,4,5,3,1,4,2,0}, {4,2,4,3,0} }},
{{{18,224,7,0,0,0}, {16,60,1,1}, /* 5¼-HD /F */
{9,50,3,1,2} },
{{19,224,7,1,0,0}, {17,25,1,2}, /* /M */
{53,3,6,4,1,5,2,6,3}, {4,4,2,4,4,3} }},
{{{0,0,0,0,0,0}, {0,0,0,0}, /* no usado */
{0,0,0,0,0}, },
{{14,192,7,1,2,1}, {9,80,1,1}, /* 3½-DD /D1 */
{38,2,4,3,1,4,2}, {4,3,4,4} }}},
{{{{12,192,7,0,2,1}, {9,80,1,1}, /* 3½-DD /F */
{6,100,3,1,1} },
{{13,192,7,1,2,1}, {9,80,1,1}, /* /M */
{38,5,6,3,1,4,2,0,0}, {4,2,4,4,0,0} }},
{{{22,224,7,0,0,0}, {19,70,1,1}, /* 3½-HD /F */
{11,40,3,1,2} },
{{23,224,7,1,0,0}, {19,70,1,1}, /* /M */
{64,3,7,4,1,5,2,6,3,7}, {4,4,4,4,4,3,2} }},
{{{44,240,7,0,3,3}, {36,108,1,1}, /* 3½-ED /F */
{11,126,4,1,2} },
{{46,240,7,1,3,3}, {36,108,1,1}, /* /M */
{127,5,12,1,7,2,8,3,9,4,10,5,11,6,12},
{4,4,4,4,4,4,4,4,4,4,4,3} }}}};
/* Significado de la tabla /F:
{SectLogPistaX, fichraiz, verFmt, flagWr, velpista0, velpistaX},
{sectpista0, GAP3pista0, primsectpista0, interleavepista0},
{SectFisPistaX, GAP3pistaX, tamsectpistaX, /X, /Y}
Significado de la tabla /M:
{SectLogPistaX, fichraiz, verFmt, flagWr, velpista0, velpistaX},
{sectpista0, GAP3pista0, primsectpista0, interleavepista0},
{Sectpreformat, GAP3pistaX, SectFisPistaX, sects numerados...},
{tamaños de sectores por orden...}
*/
if ((cmd.HD==2) && (TipoDrive(cmd.Unidad)>=4)) {
cmd.HD=0; tabla=0; tipo=0;
infofis[0][0][cmd.TipoFmt][0][4]=2; /* 3½-DD a 250 Kbps */
infofis[0][0][cmd.TipoFmt][0][5]=2;
}
else if ((cmd.HD==3) && (TipoDrive(cmd.Unidad)>=4)) {
cmd.HD=tipo=0;
cmd.TipoFmt=1; tabla=2; /* 3½-DD con 1148K */
}
else {
if (cmd.HD>1) cmd.HD=0;
tabla=cmd.HD+cmd.ED; /* seleccionar tabla de datos */
if (TipoDrive(cmd.Unidad)<3)
tipo=0; /* 5¼ */
else
tipo=1; /* 3½ */
}
ch=1+cmd.HD;
if (TipoDrive(cmd.Unidad)>2) ch+=2; if (!cmd.TipoFmt) ch+=4;
if (cmd.ED) ch=10-cmd.TipoFmt;
id[6]=(ch/10)+'0'; id[7]=(ch % 10)+'0'; strncpy (s0->IdSis, id, 8);
s0->BytesSect=512;
s0->SectCluster = s0->SectReserv = 1; s0->NumFats=2;
if (cmd.ED) s0->SectCluster=2;
if (!cmd.FichRaiz)
s0->FichRaiz=infofis[tipo][tabla][cmd.TipoFmt][0][1];
else
if (cmd.FichRaiz % 16)
s0->FichRaiz=((cmd.FichRaiz >> 4) + 1) << 4;
else
s0->FichRaiz=cmd.FichRaiz;
if (ch==6)
s0->MediaId=0xF0; /* compatible SCANDISK */
else
s0->MediaId=0xFA; /* compatible SCANDISK */
s0->SectPista=infofis[tipo][tabla][cmd.TipoFmt][0][0];
s0->Caras=2;
s0->NumSect=cmd.Pistas*s0->Caras*s0->SectPista;
j = 3 * (s0->NumSect - (s0->FichRaiz>>4) - 1);
k = 6 + 1024 * s0->SectCluster;
s0->SectFat = j/k; if (j % k) s0->SectFat++;
s0->Unidad = s0->Reservado = 0; s0->Especiales = s0->Sect32 = 0L;
s0->Flag=0x29; randomize();
for (i=0; i<4; i++)
s0->NumSerie = (s0->NumSerie<<8) | (unsigned char) random(32767);
if (cmd.Tipoetiq)
strncpy (s0->Titulo, cmd.Volumen, 11);
else
strncpy (s0->Titulo, "NO NAME ", 11);
strncpy (s0->TipoFat, "FAT12 ", 8);
s0->VersionFmt=infofis[tipo][tabla][cmd.TipoFmt][0][2];
s0->FlagWr=infofis[tipo][tabla][cmd.TipoFmt][0][3];
s0->VelPista0=infofis[tipo][tabla][cmd.TipoFmt][0][4];
s0->VelPistaX=infofis[tipo][tabla][cmd.TipoFmt][0][5];
s0->Flags=1; /* Fecha y hora de formateo almacenada */
gettime (&h); getdate (&f);
s0->FechaF=((f.da_year-1980)<<9) | (f.da_mon<<5) | f.da_day;
s0->HoraF=(h.ti_hour<<11) | (h.ti_min<<5) | (h.ti_sec>>1);
tam=BOOT2M; /* lo que precede a la primera tabla */
s0->OffsetPista0=tam;
s0->Resto[0]=infofis[tipo][tabla][cmd.TipoFmt][1][0];
s0->Resto[1]=infofis[tipo][tabla][cmd.TipoFmt][1][1];
ch=infofis[tipo][tabla][cmd.TipoFmt][1][2];
inc=infofis[tipo][tabla][cmd.TipoFmt][1][3];
ini=tam+2; fin=ini+s0->Resto[0]; k=0;
for (i=j=0; j<s0->Resto[0]; j++) {
s0->Salto[ini+i]=ch++; if (ch>s0->Resto[0]) ch=1;
i+=inc; if (ini+i>=fin) i=++k;
}
ini=fin; s0->OffsetPistaX=ini;
if (!s0->FlagWr) {
k=infofis[tipo][tabla][cmd.TipoFmt][2][0]; j=5;
for (i=0; i<j; i++)
s0->Salto[ini+i]=infofis[tipo][tabla][cmd.TipoFmt][2][i];
if (cmd.X!=-1) s0->Salto[ini+3]=cmd.X;
if (cmd.Y!=-1) s0->Salto[ini+4]=cmd.Y;
}
else {
k=infofis[tipo][tabla][cmd.TipoFmt][2][2]; j=(k+1)*3;
for (i=0; i<3; i++)
s0->Salto[ini+i]=infofis[tipo][tabla][cmd.TipoFmt][2][i];
m=129;
for (i=3; i<=k*3; i+=3) {
s0->Salto[ini+i]=m;
s=infofis[tipo][tabla][cmd.TipoFmt][2][i/3+2];
s0->Salto[ini+i+1]=s;
t=infofis[tipo][tabla][cmd.TipoFmt][3][s-1];
switch (t) {
case 0: m+=1; break; case 1: m+=2; break;
case 2: m+=3; break; case 3: m+=6; break;
case 4: m+=11; break; case 5: m+=22; break;
}
s0->Salto[ini+i+2]=t;
}
}
if (cmd.G!=-1) s0->Salto[ini+1]=cmd.G;
fin=ini+j;
ini=fin; s0->OffsetListaTam=ini;
if (!s0->FlagWr)
for (i=0; i<k; i++)
s0->Salto[ini+i]=infofis[tipo][tabla][cmd.TipoFmt][2][2];
else
for (i=0; i<k; i++)
s0->Salto[ini+i]=infofis[tipo][tabla][cmd.TipoFmt][3][i];
fin=ini+k;
ini=fin; s0->OffsetJmp=ini;
s0->Salto[0]=0xE9;
s0->Salto[1]=(ini-3) % 256; s0->Salto[2]=(ini-3) >> 8;
if (cmd.HD == 0) {
p=(char far *) &BootDDPrg; k=BootDDPrgLong; }
else {
p=(char far *) &BootHDPrg; k=BootHDPrgLong; }
for (i=0; (i<k) && (ini+i<509); i++) s0->Salto[ini+i]=*p++;
fin=ini+i;
for (i=fin; i<510; i++) s0->Salto[i]=0;
if (fin<497) strncpy (&s0->Salto[496], "Made in Spain", 13);
s0->Salto[509]=0; s0->Salto[510]=0x55; s0->Salto[511]=0xAA;
for (sum=0, j=64; j<ini; j++) sum+=s0->Salto[j]; /* checksum */
s0->CheckSum=-sum;
}
void DetectaMedio (Parametros *cmd, Boot *sector0)
{
int sg;
if (sp)
printf("\r Determinando densidad del disquete... ");
else
printf("\r Detecting diskette media density... ");
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
/* simular cambio de disco para inicialización plena de 2M */
biosdsk (5, cmd->Unidad, 0, 0, 0xFF, 0x7F, NULL);
biosdsk (2, cmd->Unidad, 0, 0, 1, 1, (unsigned char far *) sector0);
for (sg=0; sg<2; sg++) {
if (TipoDrive(cmd->Unidad)==2) /* en 5¼ intento pacífico */ {
cmd->HD=1; sg=2;
sg=biosdsk (0, cmd->Unidad, 0, 0, 0, 0, NULL);
sg=biosdsk (2, cmd->Unidad, 0, 0, 1, 1, (void *) sector0);
if (sg==6) /* cambio de disco */
sg=biosdsk (2, cmd->Unidad, 0, 0, 1, 1, (void *) sector0);
if (sg) break;
if ((peekb (0x40, 0x8B) >> 6)!=0) cmd->HD=0; break;
}
cmd->ED=0; cmd->HD=1;
if ((sg=ValeDensidad (sector0, cmd))==0) break; /* vale HD */
if (kbhit()) if (getch()==27) break;
if ((sg==3) || (sg==6) || (sg==128)) break; /* error */
cmd->HD=0;
if (!ValeDensidad (sector0, cmd)) break; /* vale DD */
cmd->HD=1; if (kbhit()) if (getch()==27) break;
cmd->HD=2;
if (!ValeDensidad (sector0, cmd)) break; /* vale D0 */
cmd->HD=1; if (kbhit()) if (getch()==27) break;
cmd->ED=1;
if (!ValeDensidad (sector0, cmd)) break; /* vale ED */
cmd->HD=1; cmd->ED=0; if (kbhit()) if (getch()==27) break;
}
if (kbhit()) getch(); /* posible código de 2 bytes */
}
int ValeDensidad (Boot *sector0, Parametros *cmd)
{
CrearSector0 (sector0, *cmd);
biosdsk (0, cmd->Unidad, 0, 0, 0, 0, NULL);
biosdsk (5, cmd->Unidad, 0, 0, 0, 0x7F,
(unsigned char far *) sector0);
return (biosdsk (2, cmd->Unidad, 0, 0,
cmd->HD==1?15:cmd->ED==1?36:9, 1,
(unsigned char far *) sector0));
}
int FormatearDisco (sector0, fat, buffer, cmd, bytes_def, segundos)
Boot *sector0;
unsigned char far *fat;
unsigned char far *buffer;
Parametros *cmd;
long *bytes_def;
int *segundos;
{
unsigned long dir, tiempo, rest, tini, hist[86], i, fase, fases;
int cilindros, cilindro, cabezal, intento, error=1, spista, t;
if (cmd->Rapido)
if (sp)
printf("\r AVISO: ¡El formateo rápido no verifica!\n");
else
printf("\r WARNING: Quick Format does not verifies!\n");
if (cmd->G!=-1)
if (sp)
printf("\r AVISO: ¡Valor de GAP alterado con opción /G!\n");
else
printf("\r WARNING: GAP value modified with /G switch!\n");
if (cmd->HD==3)
if (sp)
printf("\r AVISO: ¡Parámetro indocumentado /D1 activo!\n");
else
printf("\r WARNING: Undocumented /D1 switch activated!\n");
if (cmd->MarcaPoco)
if (sp)
printf("\r AVISO: ¡Parámetro indocumentado /W activo!\n");
else
printf("\r WARNING: Undocumented /W switch activated!\n");
if ((cmd->X!=-1) || (cmd->Y!=-1))
if (sp)
printf("\r AVISO: ¡Parámetro indocumentado /X ó /Y activo!\n");
else
printf("\r WARNING: Undocumented /X or /Y switch activated!\n");
if (sp)
printf("\r Formateo de disquete ");
else
printf("\r Formatting ");
switch (TipoDrive (cmd->Unidad)) {
case 2: printf("%s", cmd->HD==1?"5¼-1.2M":"5¼-360K"); break;
case 4: printf("%s", cmd->HD==1?"3½-1.44M":"3½-720K"); break;
default: if (cmd->ED) printf("3½-2.88M");
else printf("%s", cmd->HD==1?"3½-1.44M":"3½-720K");
}
if (sp)
printf(" en %c: con %dK \n",
cmd->UnidadLogica+'A', sector0->NumSect>>1);
else
printf(" diskette on %c: with %dK \n",
cmd->UnidadLogica+'A', sector0->NumSect>>1);
for (i=0; i<MAXFAT; i++) fat[i]=0; /* poner a 0 la futura FAT */
fat[0]=sector0->MediaId; fat[1]=fat[2]=0xFF;
for (i=0; i < ((unsigned long) MAXSECT <<9); i++) buffer[i]=0;
cilindros=sector0->NumSect/(sector0->SectPista*sector0->Caras);
spista=sector0->SectPista; *bytes_def=0L;
fases=1L*cilindros*sector0->Caras*(1+(1-cmd->NoVerify)+sector0->FlagWr);
fase=0L;
tini=*cbios;
for (cilindro=0; cilindro < cilindros ; cilindro++) {
for (cabezal=0; cabezal<sector0->Caras; cabezal++) {
for (intento=0; intento<3; intento++) {
if (sp)
printf("\r Cilindro %2d - Cara %d [F-] %3lu%%",
cilindro, cabezal, fase*100/fases);
else
printf("\r Cylinder %2d - Side %d [F-] %3lu%%",
cilindro, cabezal, fase*100/fases);
if (error) biosdsk (0, cmd->Unidad, 0, 0, 0, 0, NULL);
t=0; while (bioskey(1)) t=bioskey(0);
if ((t & 0xFF)==0x1B) { error=1; goto AbortFormat; }
else if (((t==0x1000) || (cmd->Rapido)) && (cilindro>1))
goto FinFormat;
error=biosdsk (5, cmd->Unidad, cabezal,
cilindro, 0, 0x7F, (unsigned char far *) sector0);
if (sector0->FlagWr==1) if (!error && (cilindro | cabezal)) {
printf ("\b\b\b\b\b\b\b\b\bI-] %3lu%%",(fase+1)*100/fases);
error=biosdsk (3, cmd->Unidad, cabezal | 0x80,
cilindro, 1, spista, buffer);
}
if (!error&&(!cmd->NoVerify||(cmd->NoVerify && cilindro<2))) {
printf ("\b\b\b\b\b\b\b\b\b-V] %3lu%%",
(fase+1+sector0->FlagWr)*100/fases);
error=biosdsk (2, cmd->Unidad, cabezal,
cilindro, 1, spista, buffer);
}
if (!error) break;
}
if (error)
if ((error==128) || (error==3) || (error==6))
goto AbortFormat; /* error fatal */
else
if (!MarcaFat(cmd->Unidad, cmd->MarcaPoco, sector0,
cilindro, cabezal, fat, buffer, bytes_def))
goto AbortFormat; /* error en áreas del sistema */
fase+=(1+(1-cmd->NoVerify)+sector0->FlagWr);
}
hist[cilindro]=*cbios;
tiempo=(*cbios-tini)*10/182;
printf(" [%2lu:%02lu ]", tiempo/60, tiempo % 60);
if (cilindro>5) {
rest=(*cbios-hist[cilindro-5])*(cilindros-cilindro)*10/910;
printf("\b+%2lu:%02lu =%2lu:%02lu ]", rest/60, rest % 60,
(tiempo+rest)/60, (tiempo+rest) % 60);
}
if (!error && (cilindro>79)) /* verificar siempre aquí */ {
error=biosdsk (2, cmd->Unidad, 0, cilindro-1, 1, spista, buffer);
if (error) { /* no soportadas tantas pistas */
cilindros=cilindro; cilindro-=2;
biosdsk (0, cmd->Unidad, 0, 0, 0, 0, NULL);
}
}
}
if (cmd->Pistas!=cilindros) { /* no soportadas tantas pistas */
t=cmd->Pistas;
cmd->Pistas=cilindros; /* nº pistas correcto */
CrearSector0 (sector0, *cmd); /* sector de arranque final */
cmd->Pistas=t; /* restaurar parámetro */
}
FinFormat: error=InicializaDisco(cmd->Unidad, sector0, fat, buffer);
AbortFormat: printf("\r"); for (i=0; i<79; i++) printf(" ");
*segundos=(*cbios-tini)*10/182;
return (error);
}
void InformeDisco (s0, cmd, bd, tiempo)
Boot *s0;
Parametros *cmd;
long bd;
int tiempo;
{
unsigned long st, ua, bt;
int cilindros;
char label[12];
st = s0->NumSect - s0->NumFats * s0->SectFat
- s0->SectReserv - (s0->FichRaiz>>4);
ua = st / (unsigned long) s0->SectCluster; bt = st*512L;
cilindros=s0->NumSect/(s0->SectPista*s0->Caras);
strncpy (label, s0->Titulo, 11); label[11]=0;
if (sp) {
printf ("\r Tiempo transcurrido formateando %2d:%02d\n",
tiempo/60, tiempo % 60);
printf (" Volúmen con número de serie %04X-%04X",
(int) (s0->NumSerie >> 16), (int) s0->NumSerie);
if (strstr(label, "NO NAME ")==NULL)
printf (" y etiqueta %11s\n", label);
else
printf("\n");
printf ("%9d ficheros permitidos en el raíz.\n",
s0->FichRaiz);
printf ("%9d unidades de asignación.\n", ua);
printf ("%9d bytes por unidad de asignación.\n",
s0->SectCluster*512);
printf ("%9lu bytes totales en el disco.\n", bt);
printf ("%9lu bytes en sectores defectuosos.\n", bd);
printf ("%9lu bytes disponibles en el disco.\n", bt-bd);
if (cilindros!=cmd->Pistas)
printf(" Aviso: formateado con %dK (esta unidad sólo"
" soporta %d pistas).\n", s0->NumSect>>1, cilindros);
}
else {
printf ("\r Time elapsed in the process %2d:%02d\n",
tiempo/60, tiempo % 60);
printf (" Volume serial number is %04X-%04X",
(int) (s0->NumSerie >> 16), (int) s0->NumSerie);
if (strstr(label, "NO NAME ")==NULL)
printf (" labeled %11s\n", label);
else
printf("\n");
printf ("%9d file capacity of root directory.\n",
s0->FichRaiz);
printf ("%9d total clusters on disk.\n", ua);
printf ("%9d bytes per cluster.\n",
s0->SectCluster*512);
printf ("%9lu total bytes on disk.\n", bt);
printf ("%9lu bytes on bad sectors.\n", bd);
printf ("%9lu bytes available on disk.\n", bt-bd);
if (cilindros!=cmd->Pistas)
printf(" Note: formatted with %dK (this drive supports"
" only %d tracks).\n", s0->NumSect>>1, cilindros);
}
}
void IncrementarEtiqueta (Parametros *cmd)
{
int j=10;
while ((cmd->Volumen[j]==' ') && j) j--;
while (j)
if ((cmd->Volumen[j] >= '0') && (cmd->Volumen[j] <= '8')) {
cmd->Volumen[j]++;
break;
}
else if (cmd->Volumen[j] == '9') {
cmd->Volumen[j]='0';
j--;
}
else break;
}
void DiagnosticoError (int codigo)
{
if (sp) {
switch (codigo) {
case 1: printf("\r Formateo interrumpido por el usuario.");
break;
case 2: printf("\r La densidad seleccionada es incorrecta.");
break;
case 3: printf("\r Disquete protegido contra escritura.");
break;
case 6:
case 128: printf("\r Unidad no preparada (¿puerta abierta?).");
break;
default: printf("\r Anomalía general: ¿densidad incorrecta?.");
break;
}
}
else {
switch (codigo) {
case 1: printf("\r Format aborted by user.");
break;
case 2: printf("\r Selected density is incorrect.");
break;
case 3: printf("\r Diskette is write-protected.");
break;
case 6:
case 128: printf("\r Drive not ready (door open?).");
break;
default: printf("\r General failure: incorrect density?.");
break;
}
}
printf(" \n");
}
int MarcaFat (unidad, modosuave, sector0, cil, cab, fat, buffer, bytes_mal)
Boot *sector0;
int unidad, modosuave, cil, cab;
unsigned char far *fat;
unsigned char far *buffer;
long *bytes_mal;
{
unsigned malclus, i, ini, tamsys;
tamsys = sector0->NumFats*sector0->SectFat+(sector0->FichRaiz>>4)+1;
for (i=1; i<=sector0->SectPista; i++) {
ini=(cil*sector0->Caras+cab)*sector0->SectPista+i-1;
if (modosuave)
malclus=biosdsk (2, unidad, cab, cil, i, 1, buffer);
else
malclus=1; /* por defecto marcar la pista entera */
if (malclus) {
if (ini<tamsys) break; /* error en áreas del sistema */
*bytes_mal+=sector0->SectCluster*512L;
ini-=tamsys; ini=ini/sector0->SectCluster+2;
if (ini % 2) { /* posición impar */
fat [ini*3/2] = fat [ini*3/2] & 0x0F | 0x70;
fat [ini*3/2+1] = 0xFF;
}
else { /* posición par */
fat [ini*3/2] = 0xF7;
fat [ini*3/2+1] = fat [ini*3/2+1] & 0xF0 | 0x0F;
}
ini=0x7FFF;
}
}
return (ini>=tamsys);
}
int TipoDrive (int unidad)
{
union REGS r;
r.h.ah=8; r.h.dl=unidad; int86 (0x13, &r, &r);
if (r.x.flags & 1) { r.h.ah=8; r.h.dl=unidad; int86 (0x13, &r, &r);}
return ((unsigned char) r.h.bl);
}
InicializaDisco (unidad, sector0, fat1, buffer)
int unidad;
Boot *sector0;
unsigned char far *fat1;
unsigned char far *buffer;
{
unsigned char far *p;
int sectpista0=sector0->Salto[sector0->OffsetPista0],
spraiz=sector0->SectFat*2+1,
psr, nsr, cab, cil, error;
Root raiz;
struct time h;
struct date f;
memset (buffer, 0, (unsigned long) MAXSECT << 9);
memset (&raiz, 0, sizeof (raiz));
if (strstr(sector0->Titulo, "NO NAME ")==NULL) {
strncpy (raiz.Etiqueta, sector0->Titulo, 11);
raiz.Tipo=0x28;
gettime (&h); getdate (&f);
raiz.Fecha=((f.da_year-1980)<<9) | (f.da_mon<<5) | f.da_day;
raiz.Hora=(h.ti_hour<<11) | (h.ti_min<<5) | (h.ti_sec>>1);
}
p=buffer;
memcpy (p, sector0, 512); /* BOOT físico */
p+=512;
memcpy (p, fat1, sector0->SectFat*512); /* FAT1 (la 2 emulada) */
p+=sector0->SectFat<<9;
memcpy (p, sector0, 512); /* BOOT virtual */
if (sector0->SectPista>=15) /* HD */ {
p+=512;
memcpy (p, &Boot2mCode, Boot2mLong); /* código SuperBOOT */
}
p=buffer+(spraiz<<9);
memcpy (p, &raiz, sizeof(raiz)); /* 1ª entrada ROOT */
biosdsk (0, unidad, 0, 0, 0, 0, NULL);
error=biosdsk(3, unidad, 0x80, 0, 1, sectpista0, buffer);
if (!error) {
memset (buffer, 0, (unsigned long) MAXSECT << 9); /* ROOT */
memcpy (buffer, &raiz, sizeof(raiz));
psr = (spraiz % sector0->SectPista) + 1;
nsr = sector0->SectPista - psr + 1;
cil = 0; cab = spraiz/sector0->SectPista;
error=biosdsk(3, unidad, cab, cil, psr, nsr, buffer);
if (nsr < sector0->FichRaiz) {
memset (buffer, 0, sizeof(raiz)); cab++; if (cab>1) { cab=0; cil++;}
error=biosdsk(3, unidad, cab, cil, 1, sector0->SectPista, buffer);
}
}
return (error);
}
void SonidoSube()
{
int frec=50;
SonidoOn();
while (frec<5000) {
Sonido (frec); PicoRetardo(); Sonido (frec+1000); PicoRetardo();
frec+=10;
}
SonidoOff();
}
void SonidoBaja()
{
int frec=6000;
SonidoOn();
while (frec>1050) {
Sonido (frec); PicoRetardo(); Sonido (frec-1000); PicoRetardo();
frec-=10;
}
SonidoOff();
}
void SonidoError()
{
int frec1=50, frec2=6000;
SonidoOn();
while (frec1<5000) {
Sonido (frec1); PicoRetardo(); Sonido (frec1+1000); PicoRetardo();
Sonido (frec2); PicoRetardo(); Sonido (frec2-1000); PicoRetardo();
frec1+=10; frec2-=10;
}
SonidoOff();
}
void SonidoOn()
{
disable(); outportb (0x61, inportb (0x61) | 3); enable();
outportb (0x43, 182); /* preparar canal 2 */
}
void SonidoOff()
{
disable(); outportb (0x61, inportb (0x61) & 0xFC); enable();
}
void Sonido (int frecuencia)
{
unsigned periodo;
periodo=1193180L/frecuencia;
outportb (0x42, periodo & 0xFF); outportb (0x42, periodo >> 8);
}
int EsperarCambioDisco (int disquetera, int flash)
{
int i, unidad, tec;
long hora, iter;
unidad=disquetera;
if (FdswapOn()) unidad^=1; /* unidades intercambiadas por FDSWAP */
while (kbhit()) (void) getch(); /* limpiar buffer teclado */
pokeb(0x40,0x3F, peekb(0x40, 0x3F) & 0xF0); /* "motores apagados" */
do { /* esperar que retiren el disquete */
hora=*cbios+5;
while (*cbios<hora);
outportb (FD_DOR, (1<<(unidad+4)) | unidad | 4+8); /* encender */
i=inportb (FD_DIR); /* leer línea de cambio */
outportb (FD_DOR, unidad | 4+8); /* apagar motor */
i = (i >> 7) | kbhit();
} while (!i);
if (flash) /* intento de bajar la línea de cambio */
iter=2000000000L;
else
iter=8L;
while (i && !kbhit()) { /* y parpadeo del LED */
hora=*cbios+6;
pokeb (0x40, 0x40, 0xFF); /* para BIOS pelmas no estándar */
outportb (FD_DOR,(1<<(unidad+4)) | unidad | 4+8); /* encender */
pokeb(0x40,0x3F, peekb(0x40, 0x3F) | (1<<unidad));
posicionar (unidad, 1);
while ((*cbios<hora) && !kbhit());
posicionar (unidad, 0);
i = inportb (FD_DIR) >> 7; /* leer línea de cambio */
if (i && !iter) {
outportb (FD_DOR, unidad | 4+8); /* apagar motor */
pokeb(0x40,0x3F, peekb(0x40, 0x3F) & 0xF0);
hora+=12;
while ((*cbios<hora) && !kbhit());
}
if (iter) iter--;
}
/* simular cambio de disco para anular efecto de bajada de línea */
biosdsk (5, disquetera, 0, 0, 0xFF, 0x7F, NULL); /* función de 2M */
/* 3 segundos para detención del motor */
pokeb (0x40, 0x40, 54);
if (kbhit()) tec=getch(); else tec=13; if (!tec) tec=getch()<<8;
return ((tec & 0xFF)==13);
}
void posicionar (int unidad, int cilindro) /* mover cabezal */
{
outfdc (0xF); /* comando 'Seek' */
outfdc (unidad); /* byte 1 de dicho comando */
outfdc (cilindro);
EsperarInt(); /* esperar interrupción */
outfdc (8); /* comando 'leer estado de interrupciones' */
(void) infdc(); (void) infdc();
}
void outfdc (unsigned char dato) /* enviar byte al FDC */
{ /* no esperando más de 440 ms */
int i=0, rd;
long t;
do {
i++; t=*cbios;
while ((t==*cbios) && ((rd=inportb(FD_STATUS)>>7)==0));
} while ((i<8) && !rd);
if (rd) outportb (FD_DATA, dato);
}
int infdc() /* leer byte del FDC */
{ /* no esperando más de 440 ms */
int i=0, rd;
long t;
do {
i++; t=*cbios;
while ((t==*cbios) && ((rd=inportb(FD_STATUS)>>7)==0));
} while ((i<8) && !rd);
if (rd) return (inportb (FD_DATA)); else return (-1); /* fallo */
}
void EsperarInt() /* Esperar interrupción no más de 2 seg. */
{
int i=0;
long t;
do {
i++; t=*cbios;
while ((t==*cbios) && !(*irq6 & 0x80));
} while ((i<37) && !(*irq6 & 0x80));
*irq6=*irq6 & 0x7F;
}
void CardWare (char *nfich, int discos)
{
int fich, aviso=0, lcad;
unsigned int i, contador;
struct ftime fechahora;
unsigned char chk[10],
cmp[]="Cnt",
num[]="00000",
cw[]="000";
lcad=strlen(cmp)+2;
if ((fich=open(nfich, O_BINARY | O_RDWR))==-1) return;
if (getftime (fich, &fechahora)==-1) { close(fich); return; }
if (lseek (fich, -lcad, SEEK_END)==-1) { close(fich); return; }
if (read (fich, chk, lcad)==-1) { close(fich); return; }
chk[lcad-2]=0;
if (strcmp(chk, cmp)) /* contador no inicializado */ {
write (fich, cmp, strlen(cmp));
contador=0; write (fich, &contador, sizeof(unsigned int));
if (discos) discos--;
}
if (lseek (fich, -2L, SEEK_END)==-1) { close(fich); return; }
if (read (fich, &contador, 2)==-1) { close(fich); return; }
for (i=contador+1; i<=contador+discos; i++)
if (((i % CARDWARE)==0) && (i>99)) aviso++; /* pasada frontera */
contador+=discos;
if (lseek (fich, -2L, SEEK_END)==-1) { close(fich); return; }
if (write (fich, &contador, 2)==-1) { close(fich); return; }
flushall();
setftime (fich, &fechahora);
close (fich);
num[0]=contador / 10000 + '0'; contador%=10000;
num[1]=contador / 1000 + '0'; contador%=1000;
num[2]=contador / 100 + '0'; contador%=100;
num[3]=contador / 10 + '0'; contador%=10;
num[4]=contador+'0';
i=CARDWARE;
cw[0]=i / 100 + '0'; i%=100;
cw[1]=i / 10 + '0'; i%=10;
cw[2]=i+'0';
if (aviso)
if (sp) {
clrscr();
textcolor (LIGHTCYAN + BLINK); textbackground (BLUE);
gotoxy (27, 5);
cputs(" ¡¡AVISO MUY IMPORTANTE!! ");
textcolor (LIGHTRED); textbackground (BLACK);
gotoxy (15,7); cputs ("Esta copia de 2MF ya ha formateado ");
textcolor (YELLOW);
if (num[0]!='0') cputs (num);
else if (num[1]!='0') cputs (&num[1]);
else cputs (&num[2]);
textcolor (LIGHTRED);
cputs (" disquetes.");
gotoxy (15,8); cputs ("Recuerda que 2M es un programa ");
textcolor (LIGHTGREEN); cputs ("CardWare"); textcolor (LIGHTRED);
cputs (". Si aún");
gotoxy (15,9); cputs ("no has enviado tu ");
textcolor (LIGHTMAGENTA); cputs ("tarjeta postal"); textcolor (LIGHTRED);
cputs (" al autor, no");
gotoxy (15,10); cputs ("deberías continuar utilizando estos discos.");
gotoxy (15,12); cputs ("Si ya la has enviado, estoy ");
textcolor (LIGHTCYAN); cputs ("muy contento"); textcolor (LIGHTRED);
cputs (" contigo");
gotoxy (15,13); cputs ("y dentro de otros ");
cputs (cw); cputs(" volveré a felicitarte.");
gotoxy (15,15); textcolor (LIGHTGREEN); cputs ("¡Suerte!");
textcolor (WHITE);
gotoxy (1,17);
}
else {
clrscr();
textcolor (LIGHTCYAN + BLINK); textbackground (BLUE);
gotoxy (27, 5);
cputs(" ¡¡VERY IMPORTANT NOTICE!! ");
textcolor (LIGHTRED); textbackground (BLACK);
gotoxy (15,7); cputs ("This 2MF program has already formatted ");
textcolor (YELLOW);
if (num[0]!='0') cputs (num);
else if (num[1]!='0') cputs (&num[1]);
else cputs (&num[2]);
textcolor (LIGHTRED);
cputs (" disks.");
gotoxy (15,8); cputs ("Remember that 2M is a ");
textcolor (LIGHTGREEN); cputs ("CardWare"); textcolor (LIGHTRED);
cputs (" program. If you");
gotoxy (15,9); cputs ("haven't send still your ");
textcolor (LIGHTMAGENTA); cputs ("postcard"); textcolor (LIGHTRED);
cputs (" to the author,");
gotoxy (15,10); cputs ("you musn't continue on using this diskettes.");
gotoxy (15,12); cputs ("If you have send it yet, I'm ");
textcolor (LIGHTCYAN); cputs ("very happy"); textcolor (LIGHTRED);
cputs (" with you");
gotoxy (15,13); cputs ("and within next "); cputs (cw); cputs(" ones I will thank you again.");
gotoxy (15,15); textcolor (LIGHTGREEN); cputs ("Good luck!");
textcolor (WHITE);
gotoxy (1,17);
}
}
int HablaSp() /* devolver 1 si mensajes en castellano */
{
union REGS r; struct SREGS s;
char info[64];
int i, idioma, spl[]={54, 591, 57, 506, 56, 593, 503, 34, 63, 502,
504, 212, 52, 505, 507, 595, 51, 80, 508, 598, 58, 3, 0};
idioma=0; /* supuesto el inglés */
if (_osmajor>=3) {
r.x.ax=0x3800; s.ds=FP_SEG(info); r.x.dx=FP_OFF(info);
intdosx (&r, &r, &s);
i=0; while (spl[i++]) if (spl[i-1]==r.x.bx) idioma=1;
}
return (idioma);
}