/************************************************************************\ ** ** ** GrIP Prototype API Interface Library ** ** for ** ** DJGPP ** ** ** ** Revision 1.00 ** ** ** ** COPYRIGHT: ** ** ** ** (C) Copyright Advanced Gravis Computer Technology Ltd 1995. ** ** All Rights Reserved. ** ** ** ** DISCLAIMER OF WARRANTIES: ** ** ** ** The following [enclosed] code is provided to you "AS IS", ** ** without warranty of any kind. You have a royalty-free right to ** ** use, modify, reproduce and distribute the following code (and/or ** ** any modified version) provided that you agree that Advanced ** ** Gravis has no warranty obligations and shall not be liable for ** ** any damages arising out of your use of this code, even if they ** ** have been advised of the possibility of such damages. This ** ** Copyright statement and Disclaimer of Warranties may not be ** ** removed. ** ** ** ** HISTORY: ** ** ** ** 0.102 Jul 12 95 David Bollo Initial public release on ** ** GrIP hardware ** ** 0.200 Aug 10 95 David Bollo Added Gravis Loadable Library ** ** support ** ** 0.201 Aug 11 95 David Bollo Removed Borland C++ support ** ** for maintenance reasons ** ** 1.00 Nov 1 95 David Bollo First official release as ** ** part of GrIP SDK ** ** ** \************************************************************************/ #include #include "allegro.h" #include "grip.h" /* Global Thunking Data */ GRIP_THUNK GRIP_Thunk; static int GRIP_Thunked = 0; static int GRIP_CS; static int GRIP_DS; #if defined(GRIP_DEBUG) static short GRIP_ES; #endif #ifndef ALLEGRO_DJGPP #define _farpokew(ds, addr, value) *(short *)(addr) = (value) #endif #define DPMI_AllocDOS(a, b) (__dpmi_allocate_dos_memory(a, b) << 4) #define DPMI_FreeDOS(a) __dpmi_free_dos_memory(a) #define DPMI_AllocSel() __dpmi_allocate_ldt_descriptors(1) #define DPMI_FreeSel(a) __dpmi_free_ldt_descriptor(a) unsigned char _DPMI_SetCodeAR(unsigned short sel); unsigned char _DPMI_SetDataAR(unsigned short sel); static unsigned char DPMI_SetBounds(unsigned short sel, unsigned long base, unsigned short lm) { if (__dpmi_set_segment_base_address(sel, base) == -1) return -1; if (__dpmi_set_segment_limit(sel, lm - 1) == -1) return -1; return 0; } GRIP_BOOL _GrLink(GRIP_BUF image, GRIP_VALUE size) { unsigned short img_off; /* Offset of binary image */ unsigned short img_size; /* Size of binary image */ unsigned char img_check; /* Checksum of binary image */ unsigned long memory; /* Image memory */ GRIP_BUF_C header; /* Image header */ GRIP_BUF_C core; /* Image core */ int i; /* Check for duplicate GrLink calls */ if (GRIP_Thunked) return 0; /* Sanity check the inputs */ if (image == 0 || size < 16) return 0; /* Check the image header for the proper signature bytes */ header = (GRIP_BUF_C) image; if (header[0] != 'D' || header[1] != 'B') return 0; /* Extract the image offsets from the header */ img_off = ((header[2] & 0x0F) << 12) | ((header[3] & 0x0F) << 8) | ((header[4] & 0x0F) << 4) | ((header[5] & 0x0F)); img_size = ((header[6] & 0x0F) << 12) | ((header[7] & 0x0F) << 8) | ((header[8] & 0x0F) << 4) | ((header[9] & 0x0F)); img_check = ((header[10] & 0x0F) << 4) | ((header[11] & 0x0F)); /* Compute the start of image core */ if (size < ((img_off + img_size) << 4)) return 0; core = header + (img_off << 4); /* Verify the checksum */ for (i = 0; i < (img_size << 4); i++) img_check ^= core[i]; if (img_check != 0) return 0; /* Allocate memory for the core */ memory = (unsigned long)DPMI_AllocDOS(img_size, &GRIP_DS); if (!memory) return 0; /* Copy the image */ dosmemput(core, img_size << 4, memory); /* Allocate a code selector for the core */ GRIP_CS = DPMI_AllocSel(); if (GRIP_CS == 0) { DPMI_FreeDOS(GRIP_DS); return 0; } if (DPMI_SetBounds(GRIP_CS, memory, img_size << 4) != 0) { DPMI_FreeSel(GRIP_CS); DPMI_FreeDOS(GRIP_DS); return 0; } if (_DPMI_SetCodeAR(GRIP_CS) != 0) { DPMI_FreeSel(GRIP_CS); DPMI_FreeDOS(GRIP_DS); return 0; } /* Prepare the thunking layer */ for (i = 0; i < (int)sizeof(GRIP_THUNK); i++) GRIP_Thunk[i] = ((GRIP_BUF_C) core)[i]; *(GRIP_BUF_S) (GRIP_Thunk + 0x02) = 0; *(GRIP_BUF_S) (GRIP_Thunk + 0x06) = GRIP_CS; *(GRIP_BUF_S) (GRIP_Thunk + 0x0C) = GRIP_CS; /* Allocate a debugging selector if GRIP_DEBUG is defined */ #if defined(GRIP_DEBUG) /* I don't know what this does... at least it compiles okay */ GRIP_ES = DPMI_AllocSel(); if (GRIP_ES == 0) { DPMI_FreeSel(GRIP_CS); DPMI_FreeDOS(GRIP_DS); return 0; } if (DPMI_SetBounds(GRIP_ES, 0xB0000, 80 * 25 * 2) != 0) { DPMI_FreeSel(GRIP_ES); DPMI_FreeSel(GRIP_CS); DPMI_FreeDOS(GRIP_DS); return 0; } if (DPMI_SetDataAR(GRIP_ES) != 0) { DPMI_FreeSel(GRIP_ES); DPMI_FreeSel(GRIP_CS); DPMI_FreeDOS(GRIP_DS); return 0; } _farpokew(_dos_ds, memory + 0x12, 0xB000); _farpokew(_dos_ds, memory + 0x16, GRIP_ES); #else _farpokew(_dos_ds, memory + 0x12, 0); _farpokew(_dos_ds, memory + 0x16, 0); #endif /* Save the data selector */ _farpokew(_dos_ds, memory + 0x10, 0); _farpokew(_dos_ds, memory + 0x14, GRIP_DS); /* Complete the link */ if (_Gr__Link() == 0) { #if defined(GRIP_DEBUG) DPMI_FreeSel(GRIP_ES); #endif DPMI_FreeSel(GRIP_CS); DPMI_FreeDOS(GRIP_DS); return 0; } GRIP_Thunked = 1; return 1; } GRIP_BOOL _GrUnlink(void) { /* Check that the library has been loaded */ if (!GRIP_Thunked) return 0; /* Unlink the library */ _Gr__Unlink(); /* Free the library memory */ #if defined(GRIP_DEBUG) if (DPMI_FreeSel(GRIP_ES) != 0) return 0; #endif if (DPMI_FreeSel(GRIP_CS) != 0) return 0; if (DPMI_FreeDOS(GRIP_DS) != 0) return 0; GRIP_Thunked = 0; return 1; }