//############################################################################ //## ## //## MSSSYS.C ## //## ## //## Windows MSS support routines ## //## ## //## 16-bit protected-mode source compatible with MSC 7.0 ## //## 32-bit protected-mode source compatible with MSC 9.0 ## //## ## //## Version 1.00 of 15-Feb-95: Derived from DLLLOAD.C V1.12 ## //## ## //## Author: John Miles ## //## ## //############################################################################ //## ## //## Copyright (C) RAD Game Tools, Inc. ## //## ## //## Contact RAD Game Tools at 425-893-4300 for technical support. ## //## ## //############################################################################ #if defined(_XENON) || (_XBOX_VER == 200) || defined(_XBOX) #include #elif defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(__NT__) || defined(__WIN32__) #define WIN32_LEAN_AND_MEAN #define WIN32_EXTRA_LEAN #define STRICT #include #endif #include "stdlib.h" #include "stdio.h" #include "mss.h" #include "imssapi.h" #ifdef IS_WIN16 #include static int win31=0; static int GetWin31() { U32 ver; if (GetWinFlags()&0x4000) return(-1); ver=GetVersion(); if ((LOBYTE(LOWORD(ver))>=3) && (HIBYTE(LOWORD(ver))>=95)) return(-2); return(1); } BOOL DPMISetSelectorLimit (UINT selector, DWORD dwLimit) { BOOL bRetVal=TRUE; // If the limit is >= 1MB, we need to make the limit a mulitple // of the page size or DPMISetSelectorLimit will fail. if( dwLimit >= 0x100000 ) dwLimit |= 0x0FFF; __asm { mov ax, 0008h mov bx, selector mov cx, word ptr [dwLimit+2] mov dx, word ptr [dwLimit] int 31h jnc success mov bRetVal, FALSE success: } return bRetVal; } void AIL_apply_fixup_clone_ref(void FAR * FAR *src) { U16 sel=HIWORD(*src); U32 limit=GetSelectorLimit(sel)-32768L; SetSelectorBase(sel,GetSelectorBase(sel) + 32768L); DPMISetSelectorLimit(HIWORD(*src),limit); *src = MAKELP(HIWORD(*src), LOWORD(*src) - 32768U); } // --------------------------------------------------------------------------- // ptr_clone // // Make copy of selector:offset far pointer, where selector's base address // may be freely modified without corrupting original pointer // // Cloned pointer is guaranteed to address at least 32K without further fixups // // Cloned pointer's selector must be freed with ptr_free()! // // --------------------------------------------------------------------------- void FAR *AIL_ptr_alloc_clone(void const FAR *src) { void FAR *ptr; ptr = (void FAR *) (((UINTa)(AllocSelector(HIWORD(src))) << 16) + LOWORD(src)); AIL_ptr_fixup_clone(ptr); return ptr; } // --------------------------------------------------------------------------- // ptr_adjust // // WARNING: Alters the base address of *ptr -- may be applied ONLY // to a cloned pointer! // --------------------------------------------------------------------------- void AIL_ptr_inc_clone_ref(void FAR * FAR *ptr, U32 offset) { void FAR *dest = *ptr; while (offset > 32767) { dest = (void FAR *) ((U8 FAR *) dest + 32768L); AIL_ptr_fixup_clone(dest); offset -= 32768; } dest = (void FAR *) ((U8 FAR *) dest + offset); AIL_ptr_fixup_clone(dest); *ptr = dest; } // --------------------------------------------------------------------------- // AIL_ptr_dif // --------------------------------------------------------------------------- S32 AIL_ptr_dif(void const FAR *p1, void const FAR *p2) { if (HIWORD(p1)==HIWORD(p2)) return((SINTa)((UINTa)LOWORD(p1))-(SINTa)((UINTa)LOWORD(p2))); return (SINTa)(((SINTa)(GetSelectorBase(HIWORD(p1)) + LOWORD(p1))) - ((SINTa)(GetSelectorBase(HIWORD(p2)) + LOWORD(p2)))); } extern void WINAPI AIL_memcpydb(void FAR*dst, void const FAR*src,S32 len); void AIL_memmove(void FAR *d, void const FAR *s, S32 len) { U32 saddr = AIL_ptr_lin_addr(s); U32 daddr = AIL_ptr_lin_addr(d); if (saddr==daddr) return; if (saddr > daddr) { AIL_memcpy(d,s,len); } else { if ((saddr+len)sizeof(LINK))?size:sizeof(LINK); next = &first; blk_size=allocsize; while (blk_size<32768) blk_size<<=1; do { while ((sel = LOWORD(GlobalDosAlloc(blk_size))) != 0) { cur = (LINK FAR *) MAKELONG(0, sel); *next = cur; cur->selector = sel; cur->next = NULL; next = &cur->next; } blk_size >>= 1; } while (blk_size >= allocsize); } if (size<4) size=4; // // Now allocate requested memory block and GlobalPageLock() it // h = GlobalAlloc(GMEM_FIXED | GMEM_SHARE | GMEM_ZEROINIT, size+16); //jkr: alloc 16 bytes extra for Win32s support GlobalFix(h); if (!GlobalPageLock(h)) { ptr = NULL; } else { ptr = GlobalLock(h); } // // Finally, walk through list of GlobalDosAlloc() blocks, returning // them to the lower-1MB heap // cur = first; while (cur != NULL) { temp = cur->next; GlobalDosFree(cur->selector); cur = temp; } // // Return the pointer to the allocated block // if (ptr) { *((U32 FAR*)ptr)=((U32)ptr)+16; // jkr: hide 16:16 pointer so Win32s can find it later *(((U32 FAR*)ptr)+1)=((U32)ptr)+16; // jkr: hide it twice *(((U32 FAR*)ptr)+3)=0x5753534d; // jkr: hide a marker return(((U8 FAR*)ptr)+16); // jkr: return adjusted pointer } else return(0); #endif } void AILCALL AIL_API_mem_free_lock(void FAR *ptr) { if (ptr != NULL) { #ifdef IS_WIN32API mss_free( ptr ); #else HANDLE h; if (AIL_background()) addtobackfree(ptr); else { checkforbackfrees(); if (*(((U32 FAR*)ptr)-1)!=0x5753534d) { // jkr: validate pointer MessageBox(0,"Attempted to free a bad pointer.","Error from MSS",MB_OK); return; } *(((U32 FAR*)ptr)-1)=0; //jkr: clear marker h = (HANDLE) GlobalHandle(SELECTOROF(ptr)); //jkr: don't need to subtract 16 because the selector is the same GlobalUnlock(h); GlobalPageUnlock(h); GlobalUnfix(h); GlobalFree(h); } #endif } } //############################################################################ //## ## //## Write file at *buf of length len ## //## ## //## Overwrites any existing file ## //## ## //## Returns 0 on error, else 1 ## //## ## //############################################################################ S32 AILCALL AIL_API_file_write(char const FAR *filename, void const FAR *buf, U32 len) { #ifdef IS_WIN32API HANDLE handle; U32 nbytes; disk_err = 0; handle = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (handle == INVALID_HANDLE_VALUE) { disk_err = AIL_CANT_WRITE_FILE; AIL_set_error("Unable to create file."); return 0; } if ((!WriteFile(handle, buf, len, (DWORD*)&nbytes, NULL)) || (nbytes != len)) { CloseHandle(handle); disk_err = AIL_DISK_FULL; AIL_set_error("Unable to write to file (disk full?)."); return 0; } CloseHandle(handle); return 1; #else U32 i; S16 handle; U16 readamt; disk_err = 0; handle = _lcreat(filename, 0); if (handle==-1) { disk_err = AIL_CANT_WRITE_FILE; AIL_set_error("Unable to create file."); return 0; } while (len) { readamt=(U16) ((len >= (32768-512)) ? (32768-512) : len); i = _lwrite(handle,buf,readamt); if (i == -1) { disk_err = AIL_CANT_WRITE_FILE; _lclose(handle); return 0; } if (i != readamt) { disk_err = AIL_DISK_FULL; AIL_set_error("Unable to write to file (disk full?)."); _lclose(handle); return 0; } len -= readamt; buf = AIL_ptr_add(buf,readamt); } _lclose(handle); return 1; #endif } //############################################################################ //## ## //## Write wave file at *buf of length len ## //## ## //## Overwrites any existing file ## //## ## //## Returns 0 on error, else 1 ## //## ## //############################################################################ S32 AILCALL AIL_API_WAV_file_write(char const FAR *filename, void const FAR *buf, U32 len, S32 rate, S32 format) { WAVEOUT wo; AIL_memcpy(&wo.riffmark,"RIFF",4); wo.rifflen=len+sizeof(WAVEOUT)-8; AIL_memcpy(&wo.wavemark,"WAVE",4); AIL_memcpy(&wo.fmtmark,"fmt ",4); wo.fmtlen=16; wo.fmttag=WAVE_FORMAT_PCM; wo.channels=(S16)((format&DIG_F_STEREO_MASK)?2:1); wo.sampersec=rate; wo.bitspersam=(S16)((format&DIG_F_16BITS_MASK)?16:8); wo.blockalign=(S16)(((S32)wo.bitspersam*(S32)wo.channels) / 8); wo.avepersec=(rate *(S32)wo.bitspersam*(S32)wo.channels) / 8; AIL_memcpy(&wo.datamark,"data",4); wo.datalen=len; { #ifdef IS_WIN32API HANDLE handle; U32 nbytes; disk_err = 0; handle = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (handle == INVALID_HANDLE_VALUE) { disk_err = AIL_CANT_WRITE_FILE; AIL_set_error("Unable to create file."); return 0; } WriteFile(handle,&wo,sizeof(wo),(DWORD*)&nbytes,0); if ((!WriteFile(handle, buf, len, (DWORD*)&nbytes, NULL)) || (nbytes != len)) { disk_err = AIL_DISK_FULL; AIL_set_error("Unable to write to file (disk full?)."); return 0; } CloseHandle(handle); return 1; #else U32 i; S16 handle; U16 readamt; disk_err = 0; handle = _lcreat(filename, 0); if (handle==-1) { disk_err = AIL_CANT_WRITE_FILE; AIL_set_error("Unable to create file."); return 0; } _lwrite(handle,&wo,sizeof(wo)); while (len) { readamt=(U16) ((len >= (32768-512)) ? (32768-512) : len); i = _lwrite(handle,buf,readamt); if (i == -1) { disk_err = AIL_CANT_WRITE_FILE; _lclose(handle); return 0; } if (i != readamt) { disk_err = AIL_DISK_FULL; AIL_set_error("Unable to write to file (disk full?)."); _lclose(handle); return 0; } len -= readamt; buf = AIL_ptr_add(buf,readamt); } _lclose(handle); return 1; #endif } } S32 _cdecl AIL_sprintf (char FAR *dest, char const FAR *fmt, ...) { S32 len; va_list ap; va_start(ap, fmt); len=vsprintf(dest, fmt, ap); va_end (ap); return( len ); }