403 lines
20 KiB
C++
403 lines
20 KiB
C++
/**********************************************************************/
|
||
/* E M M C */
|
||
/*--------------------------------------------------------------------*/
|
||
/* Tarea : contiene algunas funciones para acceder a la */
|
||
/* memoria EMS (Expanded Memory) */
|
||
/*--------------------------------------------------------------------*/
|
||
/* Autor : MICHAEL TISCHER */
|
||
/* desarrollado el: 30.08.1988 */
|
||
/* £ltimo update : 29.01.1995 */
|
||
/*--------------------------------------------------------------------*/
|
||
/* modelo de memoria: alguno con puntero FAR a los datos, es */
|
||
/* decir Compact, Large o Huge */
|
||
/**********************************************************************/
|
||
|
||
/*== enlazar archivos Include =======================================*/
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <conio.h>
|
||
#include <dos.h>
|
||
#include "EMMC.h"
|
||
|
||
/*== Typedefs ========================================================*/
|
||
|
||
typedef unsigned char BYTE; /*nos construimos un byte*/
|
||
typedef unsigned int WORD;
|
||
typedef BYTE BOOL; /*como BOOLEAN en Pascal*/
|
||
|
||
/*== Macros ==========================================================*/
|
||
|
||
/*-- MK_FP crea de una direcci¢n de segmento y Offset un -------------*/
|
||
/*-- puntero FAR a un objeto -------*/
|
||
|
||
#ifdef MK_FP /*¨ya se defini¢ MK_FP?*/
|
||
#undef MK_FP
|
||
#endif
|
||
#define MK_FP(seg, ofs) ((void far *) ((unsigned long) (seg)<<16|(ofs)))
|
||
|
||
/*-- PAGE_ADR devuelve un puntero a la p gina f¡sica X dentro del ----*/
|
||
/*-- Page-Frame de la memoria EMS ----*/
|
||
|
||
#define PAGE_ADR(x) ((void *) MK_FP(ems_frame_seg() + ((x) << 10), 0))
|
||
|
||
/*== Constantes ======================================================*/
|
||
|
||
#define TRUE 1 /*Constantes para el trabajo con BOOL*/
|
||
#define FALSE 0
|
||
|
||
#define EMS_INT 0x67 /*n£mero de interrupci¢n para acceder a la EMM*/
|
||
#define EMS_ERR -1 /*se devuelve en caso de error*/
|
||
|
||
/*== variables globales===============================================*/
|
||
|
||
BYTE emm_ec; /*aqu¡ se guardan los c¢digos de error EMM*/
|
||
|
||
/***********************************************************************/
|
||
/* Funci¢n : E M S _ I N S T */
|
||
/**--------------------------------------------------------------------**/
|
||
/* Tarea : Determina si hay instalada memoria EMS, y un */
|
||
/* driver EMS (EMM) asociado. */
|
||
/* Par metro entrada: ninguno */
|
||
/* Valor de retorno : TRUE, si hay memoria EMS instalada, sino */
|
||
/* FALSE. */
|
||
/************************************************************************/
|
||
|
||
BOOL ems_inst()
|
||
{
|
||
static char emm_name[] = { 'E', 'M', 'M', 'X', 'X', 'X', 'X', '0' };
|
||
union REGS regs; /*reg. de proc. para la llamada de interr.*/
|
||
struct SREGS sregs; /*reg. de segm. para la llamada de interr.*/
|
||
|
||
/*-- Construir puntero a nombre en cabecera de un contr. de disp. --*/
|
||
|
||
regs.x.ax = 0x3567; /*n§ de func.: obtener vector int. 0x67*/
|
||
intdosx(®s, ®s, &sregs); /*llamar la interr. del DOS 0x21*/
|
||
return !memcmp( MK_FP(sregs.es, 10), emm_name, sizeof emm_name );
|
||
}
|
||
|
||
/************************************************************************/
|
||
/* Funci¢n : E M S _ N U M _ P A G E */
|
||
/**--------------------------------------------------------------------**/
|
||
/* Tarea : Obtiene el n§ total de p ginas EMS. */
|
||
/* Par metro entrada: ninguno */
|
||
/* Valor de retorno : EMS_ERR en caso de error, sino el n£mero de */
|
||
/* p ginas EMS. */
|
||
/************************************************************************/
|
||
int ems_num_page()
|
||
{
|
||
union REGS regs; /*reg. de proc. para la llamada de interr.*/
|
||
|
||
regs.h.ah = 0x42; /*n£mero de funci¢n: obtener n£mero de p ginas*/
|
||
int86(EMS_INT, ®s, ®s); /*llamar EMM*/
|
||
if ((int) (emm_ec = regs.h.ah)) /*¨ha aparecido un error?*/
|
||
return(EMS_ERR); /*S¡, mostrar error*/
|
||
else /*no hay error*/
|
||
return( regs.x.dx ); /*devolver n£mero total de p ginas*/
|
||
}
|
||
|
||
/**********************************************************************/
|
||
/* Funci¢n : E M S _ F R E E _ P A G E */
|
||
/**--------------------------------------------------------------------**/
|
||
/* Tarea : Obtiene la cantidad de p ginas EMS libres. */
|
||
/* Par metro entrada: ninguno */
|
||
/* Valor de retorno : EMS_ERR en caso de error, sino el n£mero de */
|
||
/* p ginas EMS libres. */
|
||
/***********************************************************************/
|
||
|
||
int ems_free_page()
|
||
{
|
||
union REGS regs; /*reg. de proc. para la llamada de interr.*/
|
||
|
||
regs.h.ah = 0x42; /*n£mero de funci¢n: obtener n£mero de p ginas*/
|
||
int86(EMS_INT, ®s, ®s); /*llamar EMM*/
|
||
if ((int) (emm_ec = regs.h.ah)) /*¨ha aparecido un error?*/
|
||
return(EMS_ERR); /*S¡, mostrar error*/
|
||
else /*no hay error*/
|
||
return( regs.x.bx ); /*devolver n£mero de p ginas libres*/
|
||
}
|
||
|
||
/**********************************************************************/
|
||
/* Funci¢n : E M S _ F R A M E _ S E G */
|
||
/**--------------------------------------------------------------------**/
|
||
/* Tarea : Obtiene la dir. de segmento del EMS-Page-Frame */
|
||
/* Par metro entrada: ninguno */
|
||
/* Valor de retorno : EMS_ERR en caso de error, sino la direcci¢n de */
|
||
/* segmento del Page-Frame. */
|
||
/***********************************************************************/
|
||
|
||
WORD ems_frame_seg()
|
||
{
|
||
union REGS regs; /*reg. de proc. para la llamada de interr.*/
|
||
|
||
regs.h.ah = 0x41; /*n§ de funci¢n: obt.dir.segm. Page-Frame*/
|
||
int86(EMS_INT, ®s, ®s); /*llamar EMM*/
|
||
if ((int) (emm_ec = regs.h.ah)) /*¨ha aparecido un error?*/
|
||
return(EMS_ERR); /*S¡, mostrar error*/
|
||
else /*no hay error*/
|
||
return( regs.x.bx ); /*devolver direcci¢n de segmento*/
|
||
}
|
||
|
||
/**********************************************************************/
|
||
/* Funci¢n : E M S _ A L L O C */
|
||
/**--------------------------------------------------------------------**/
|
||
/* Tarea : Aloja el n£mero de p ginas indicado y devuelve */
|
||
/* un Handle para acceder a estas p ginas. */
|
||
/* */
|
||
/* Par metro entrada: PAGES : el n£mero de p ginas a alojar */
|
||
/* (de 16 KBytes cada uno) */
|
||
/* Valor de retorno : EMS_ERR en caso de error, sino el Handle EMS. */
|
||
/***********************************************************************/
|
||
|
||
int ems_alloc(int pages)
|
||
{
|
||
union REGS regs; /*reg. de proc. para la llamada de interr.*/
|
||
|
||
regs.h.ah = 0x43; /*n£mero de funci¢n: aljar p ginas*/
|
||
regs.x.bx = pages; /*fijar n£mero de p ginas a alojar*/
|
||
int86(EMS_INT, ®s, ®s); /*llamar EMM*/
|
||
if ((int) (emm_ec = regs.h.ah)) /*¨ha aparecido un error?*/
|
||
return(EMS_ERR); /*S¡, mostrar error*/
|
||
else /*no hay error*/
|
||
return( regs.x.dx ); /*devolver Handle-EMS*/
|
||
}
|
||
|
||
/**********************************************************************/
|
||
/* Funci¢n : E M S _ M A P */
|
||
/**--------------------------------------------------------------------**/
|
||
/* Tarea : Proyecta una de las p ginas alojadas bajo */
|
||
/* el Handle indicado, a un p gina f¡sica del */
|
||
/* del Page-Frame. */
|
||
/* Par metro entrada: HANDLE: el Handle devuelto por EMS_ALLOC */
|
||
/* LOGP : la p gina l¢gica (0 a n-1) */
|
||
/* PHYSP : la p gina f¡sica (0 a 3) */
|
||
/* Valor de retorno : FALSE en caso de error, sino TRUE. */
|
||
/***********************************************************************/
|
||
|
||
BOOL ems_map(int handle, int logp, BYTE physp)
|
||
{
|
||
union REGS regs; /*reg. de proc. para la llamada de interr.*/
|
||
|
||
regs.h.ah = 0x44; /*n£mero de funci¢n: fijar Maping*/
|
||
regs.h.al = physp; /*fijar p gina f¡sica*/
|
||
regs.x.bx = logp; /*fijar p gina l¢gica*/
|
||
regs.x.dx = handle; /*fijar Handle EMS*/
|
||
int86(EMS_INT, ®s, ®s); /*llamar EMM*/
|
||
return (!(emm_ec = regs.h.ah));
|
||
}
|
||
|
||
/**********************************************************************/
|
||
/* Funci¢n : E M S _ F R E E */
|
||
/**--------------------------------------------------------------------**/
|
||
/* Tarea : Devuelve la memoria alojada bajo un Handle */
|
||
/* de nuevo. */
|
||
/* Par metro entrada: HANDLE: el Handle devuelto por EMS_ALLOC */
|
||
/* Valor de retorno : FALSE en caso de error, sino TRUE. */
|
||
/***********************************************************************/
|
||
BOOL ems_free(int handle)
|
||
{
|
||
union REGS regs; /*reg. de proc. para la llamada de interr.*/
|
||
|
||
regs.h.ah = 0x45; /*n£mero de funci¢n: liberar p ginas*/
|
||
regs.x.dx = handle; /*fijar Handle EMS*/
|
||
int86(EMS_INT, ®s, ®s); /*llamar EMM*/
|
||
return (!(emm_ec = regs.h.ah)); /*si AH contiene 0, todo est ok*/
|
||
}
|
||
|
||
/**********************************************************************/
|
||
/* Funci¢n : E M S _ V E R S I O N */
|
||
/**--------------------------------------------------------------------**/
|
||
/* Tarea : Obtiene el n£mero de versi¢n EMM. */
|
||
/* Par metro entrada: ninguno */
|
||
/* Valor de retorno : EMS_ERR en caso de error, sino el n£mero de */
|
||
/* versi¢n EMM. */
|
||
/* Info : En el n£mero de versi¢n, 10 est por 1.0, 11 */
|
||
/* por 1.1, 34 por 3.4, etc. */
|
||
/***********************************************************************/
|
||
|
||
BYTE ems_version()
|
||
{
|
||
union REGS regs; /*reg. de proc. para la llamada de interr.*/
|
||
|
||
regs.h.ah = 0x46; /*n£mero de funci¢n: obtener versi¢n EMS*/
|
||
int86(EMS_INT, ®s, ®s); /*llamar EMM*/
|
||
if ((int) (emm_ec = regs.h.ah)) /*¨ha aparecido un error?*/
|
||
return(EMS_ERR); /*S¡, mostrar error*/
|
||
else /*sin error, calcula n£mero de versi¢n de cifra BCD*/
|
||
return( (regs.h.al & 15) + (regs.h.al >> 4) * 10);
|
||
}
|
||
|
||
/**********************************************************************/
|
||
/* Funci¢n : E M S _ S A V E _ M A P */
|
||
/**--------------------------------------------------------------------**/
|
||
/* Tarea : Guarda la proyecci¢n (Mapping) entre p ginas */
|
||
/* l¢gicas y f¡sicas. */
|
||
/* Par metro entrada: HANDLE: el Handle devuelto por EMS_ALLOC */
|
||
/* Valor de retorno : FALSE en caso de error, sino TRUE. */
|
||
/***********************************************************************/
|
||
|
||
BOOL ems_save_map(int handle)
|
||
{
|
||
union REGS regs; /*reg. de proc. para la llamada de interr.*/
|
||
|
||
regs.h.ah = 0x47; /*n£mero de funci¢n: guardar Mapping*/
|
||
regs.x.dx = handle; /*fijar Handle EMS*/
|
||
int86(EMS_INT, ®s, ®s); /*llamar EMM*/
|
||
return (!(emm_ec = regs.h.ah)); /*si AH contiene 0, todo est ok*/
|
||
}
|
||
|
||
/**********************************************************************/
|
||
/* Funci¢n : E M S _ R E S T O R E _ M A P */
|
||
/**--------------------------------------------------------------------**/
|
||
/* Tarea : Recupera una proyecci¢n entre p ginas l¢gicas */
|
||
/* y f¡sicas guardada anteriormente mediante */
|
||
/* EMS_SAVE_MAP. */
|
||
/* Par metro entrada: HANDLE: el Handle devuelto por EMS_ALLOC */
|
||
/* Valor de retorno : FALSE en caso de error, sino TRUE. */
|
||
/***********************************************************************/
|
||
|
||
BOOL ems_restore_map(int handle)
|
||
{
|
||
union REGS regs; /*reg. de proc. para la llamada de interr.*/
|
||
|
||
regs.h.ah = 0x48; /*n£mero de funci¢n: Recuperar Mapping*/
|
||
regs.x.dx = handle; /*fijar Handle EMS*/
|
||
int86(EMS_INT, ®s, ®s); /*llamar EMM*/
|
||
return (!(emm_ec = regs.h.ah)); /*si AH contiene 0, todo est ok*/
|
||
}
|
||
|
||
/**********************************************************************/
|
||
/* Funci¢n : P R I N T _ E R R */
|
||
/**--------------------------------------------------------------------**/
|
||
/* Tarea : Visualiza un mensaje de error EMS en la pantalla */
|
||
/* y termina el programa. */
|
||
/* Par metro entrada: ninguno */
|
||
/* Valor de retorno : ninguno */
|
||
/* Info : Esta funci¢n s¢lo se puede llamar si durante */
|
||
/* la llamada anterior de una funci¢n del EMM */
|
||
/* ha aparecido un error. */
|
||
/***********************************************************************/
|
||
|
||
void print_err()
|
||
{
|
||
static char nid[] = "no identificable";
|
||
static char *err_vec[] =
|
||
{ "Error en el driver EMS (EMM destruido)", /*0x80*/
|
||
"Error en el hardware EMS", /*0x81*/
|
||
nid, /*0x82*/
|
||
"Handle EMM no v lido", /*0x83*/
|
||
"funci¢n EMS llamada no existe", /*0x84*/
|
||
"no quedan Handles EMS disponibles", /*0x85*/
|
||
"Error al guardar o recuperar el Mapping", /*0x86*/
|
||
"m s p ginas pedidas de las que existen f¡sicamente", /*0x87*/
|
||
"m s p ginas pedidas de las que quedan libres", /*0x88*/
|
||
"pedidad cero p ginas", /*0x89*/
|
||
"p gina l¢gica no pertenece al Handle", /*0x8A*/
|
||
"n£mero de p gina f¡sico no v lido", /*0x8B*/
|
||
"Zona de memoria mapping est llena", /*0x8C*/
|
||
"Guardado del mapping ya se realiz¢", /*0x8D*/
|
||
"Recuperar el mapping sin guardarlo previamente"
|
||
};
|
||
|
||
printf("\nATENCION! Error al acceder a la memoria EMS!r\n");
|
||
printf(" ... %s\n", (emm_ec<0x80 || emm_ec>0x8E) ?
|
||
nid : err_vec[emm_ec-0x80]);
|
||
exit( 1 ); /*terminar programa con c¢digo de error*/
|
||
}
|
||
|
||
/**********************************************************************/
|
||
/* Funci¢n : V R _ A D R */
|
||
/**------------------------------------------------------------------**/
|
||
/* Tarea : Devuelve un puntero a la RAM de v¡deo. */
|
||
/* Par metro entrada: ninguno */
|
||
/* Valor de retorno : Puntero VOID a la RAM de v¡deo. */
|
||
/**********************************************************************/
|
||
|
||
void *vr_adr()
|
||
{
|
||
union REGS regs; /*reg. de proc. para la llamada de interr.*/
|
||
|
||
regs.h.ah = 0x0f; /*n£mero de funci¢n:obtener modo de v¡deo*/
|
||
int86(0x10, ®s, ®s); /*llamar interrupci¢n de la BIOS de v¡deo*/
|
||
return ( MK_FP((regs.h.al==7) ? 0xb000 : 0xb800, 0) );
|
||
}
|
||
|
||
|
||
/**********************************************************************/
|
||
/** PROGRAMA PRINCIPAL **/
|
||
/**********************************************************************/
|
||
////
|
||
////void main()
|
||
////{
|
||
//// int pagenum, /*n£mero de p ginas EMS*/
|
||
//// handle, /*Handle para acceder a la memoria EMS*/
|
||
//// i; /*contador de bucle*/
|
||
//// WORD pageseg ; /*direcci¢n de segmento del Page-Frame*/
|
||
//// BYTE emmver; /*n£mero de versi¢n de la EMM*/
|
||
////
|
||
//// printf("EMMC - (c) 1988, 92 by MICHAEL TISCHER\n\n");
|
||
//// if ( ems_inst() ) /*¨Est instalada la memoria EMS?*/
|
||
//// { /*Si*/
|
||
//// /*-- Visualizar informaciones sobre la memoria EMS ----------------*/
|
||
////
|
||
//// if ( (int) (emmver = ems_version()) == EMS_ERR) /*Obten. n§ versi¢n*/
|
||
//// print_err(); /*Error: visualizar men. error y term. el programa*/
|
||
//// else /*no hay error*/
|
||
//// printf("N£mero de versi¢n EMM : %d.%d\n",
|
||
//// emmver/10, emmver%10);
|
||
////
|
||
//// if ( (pagenum = ems_num_page()) == EMS_ERR) /*obten. n§ p ginas*/
|
||
//// print_err(); /*Error: vis. men. de error y terminar el programa*/
|
||
//// printf("N£mero de p ginas EMS : %d (%d KByte)\n",
|
||
//// pagenum, pagenum << 4);
|
||
////
|
||
//// if ( (pagenum = ems_free_page()) == EMS_ERR)
|
||
//// print_err(); /*Error: vis. men. error y terminar el programa*/
|
||
//// printf("... libres : %d (%d KByte)\n",
|
||
//// pagenum, pagenum << 4);
|
||
////
|
||
//// if ( (int) (pageseg = ems_frame_seg()) == EMS_ERR)
|
||
//// print_err(); /*Error: vis. men. error y terminar el programa*/
|
||
//// printf("Direcc. segmento del Page-Frame: %X\n", pageseg);
|
||
////
|
||
//// printf("\nAhora se aloja una p gina de la memoria EMS, y el con-\n");
|
||
//// printf("tenido de la pantalla de la RAM de v¡deo se copia a\n");
|
||
//// printf("esta p gina.\n");
|
||
//// printf(" ... por favor pulse una tecla\n");
|
||
//// getch(); /*esperar una tecla*/
|
||
////
|
||
//// /*-- alojar una p gina y poyectar sobre la primera p gina l¢gica --*/
|
||
//// /*-- en el Page-Frame ---*/
|
||
////
|
||
//// if ( (handle = ems_alloc(1)) == EMS_ERR)
|
||
//// print_err(); /*Error: vis. men. error y terminar el programa*/
|
||
//// if ( !ems_map(handle, 0, 0) ) /*fijar Mapping*/
|
||
//// print_err(); /*Error: vis. men. de error y terminar el programa*/
|
||
////
|
||
//// /*-- Copiar 4000 bytes de la RAM de v¡deo a la memoria EMS ----*/
|
||
////
|
||
//// memcpy(PAGE_ADR(0), vr_adr(), 4000);
|
||
////
|
||
//// for (i=0; i<24; ++i) /*borrar la pantalla*/
|
||
//// printf("\n");
|
||
////
|
||
//// printf("El antiguo contenido de la pantalla ha sido borrado y\n");
|
||
//// printf("con ello se ha perdido. Pero como ha sido guardado en\n");
|
||
//// printf("la memoria EMS, se puede volver a copiar de all¡ a la\n");
|
||
//// printf("RAM de v¡deo.\n");
|
||
//// printf(" ... por favor pulse una tecla\n");
|
||
//// getch(); /*esperar una tecla*/
|
||
////
|
||
//// /*-- copiar de nuevo el contenido de la RAM de v¡deo de la memo----*/
|
||
//// /*-- ria EMS y devolver la memoria EMS alojada ----*/
|
||
////
|
||
//// memcpy(vr_adr(), PAGE_ADR(0), 4000); /*copiar la V-RAM de vuelta*/
|
||
//// if ( !ems_free(handle) ) /*liberar memoria*/
|
||
//// print_err(); /*Error: vis. men. error y terminar el programa*/
|
||
//// printf("FIN");
|
||
//// }
|
||
//// else /*el driver EMS no se descubri¢*/
|
||
//// printf("ATENCION: No hay memoria EMS instalada.\n");
|
||
////}
|