/**********************************************************************/ /* 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 #include #include #include #include #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"); ////}