📄 pm.c
字号:
/****************************************************************************** SciTech OS Portability Manager Library** ========================================================================** The contents of this file are subject to the SciTech MGL Public* License Version 1.0 (the "License"); you may not use this file* except in compliance with the License. You may obtain a copy of* the License at http://www.scitechsoft.com/mgl-license.txt** Software distributed under the License is distributed on an* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or* implied. See the License for the specific language governing* rights and limitations under the License.** The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.** The Initial Developer of the Original Code is SciTech Software, Inc.* All Rights Reserved.** ========================================================================** Language: ANSI C* Environment: 16/32 bit DOS** Description: Implementation for the OS Portability Manager Library, which* contains functions to implement OS specific services in a* generic, cross platform API. Porting the OS Portability* Manager library is the first step to porting any SciTech* products to a new platform.*****************************************************************************/#include "pmapi.h"#include "drvlib/os/os.h"#include "ztimerc.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <dos.h>#include <conio.h>#ifdef DJGPP#include <unistd.h>#include <sys/nearptr.h>#else#include <direct.h>#endif#ifdef __BORLANDC__#pragma warn -par#endif/*--------------------------- Global variables ----------------------------*/typedef struct { int oldMode; int old50Lines; } DOS_stateBuf;#define MAX_RM_BLOCKS 10static struct { void *p; uint tag; } rmBlocks[MAX_RM_BLOCKS];static uint VESABuf_len = 1024; /* Length of the VESABuf buffer */static void *VESABuf_ptr = NULL; /* Near pointer to VESABuf */static uint VESABuf_rseg; /* Real mode segment of VESABuf */static uint VESABuf_roff; /* Real mode offset of VESABuf */static void (PMAPIP fatalErrorCleanup)(void) = NULL;ushort _VARAPI _PM_savedDS = 0;#ifdef DOS4GWstatic ulong PDB = 0,*pPDB = NULL;#endif/*----------------------------- Implementation ----------------------------*/void MTRR_init(void);ulong _ASMAPI _PM_getPDB(void);void PMAPI PM_init(void){#ifndef REALMODE MTRR_init();#endif}ibool PMAPI PM_haveBIOSAccess(void){ return true; }long PMAPI PM_getOSType(void){ return _OS_DOS; }int PMAPI PM_getModeType(void){#if defined(REALMODE) return PM_realMode;#elif defined(PM286) return PM_286;#elif defined(PM386) return PM_386;#endif}void PMAPI PM_backslash(char *s){ uint pos = strlen(s); if (s[pos-1] != '\\') { s[pos] = '\\'; s[pos+1] = '\0'; }}void PMAPI PM_setFatalErrorCleanup( void (PMAPIP cleanup)(void)){ fatalErrorCleanup = cleanup;}void PMAPI PM_fatalError(const char *msg){ if (fatalErrorCleanup) fatalErrorCleanup(); fprintf(stderr,"%s\n", msg); exit(1);}static void ExitVBEBuf(void){ if (VESABuf_ptr) PM_freeRealSeg(VESABuf_ptr); VESABuf_ptr = 0;}void * PMAPI PM_getVESABuf(uint *len,uint *rseg,uint *roff){ if (!VESABuf_ptr) { /* Allocate a global buffer for communicating with the VESA VBE */ if ((VESABuf_ptr = PM_allocRealSeg(VESABuf_len, &VESABuf_rseg, &VESABuf_roff)) == NULL) return NULL; atexit(ExitVBEBuf); } *len = VESABuf_len; *rseg = VESABuf_rseg; *roff = VESABuf_roff; return VESABuf_ptr;}int PMAPI PM_int386(int intno, PMREGS *in, PMREGS *out){ PMSREGS sregs; PM_segread(&sregs); return PM_int386x(intno,in,out,&sregs);}/* Routines to set and get the real mode interrupt vectors, by making * direct real mode calls to DOS and bypassing the DOS extenders API. * This is the safest way to handle this, as some servers try to be * smart about changing real mode vectors. */void PMAPI _PM_getRMvect(int intno, long *realisr){ RMREGS regs; RMSREGS sregs; PM_saveDS(); regs.h.ah = 0x35; regs.h.al = intno; PM_int86x(0x21, ®s, ®s, &sregs); *realisr = ((long)sregs.es << 16) | regs.x.bx;}void PMAPI _PM_setRMvect(int intno, long realisr){ RMREGS regs; RMSREGS sregs; PM_saveDS(); regs.h.ah = 0x25; regs.h.al = intno; sregs.ds = (int)(realisr >> 16); regs.x.dx = (int)(realisr & 0xFFFF); PM_int86x(0x21, ®s, ®s, &sregs);}void PMAPI _PM_addRealModeBlock(void *mem,uint tag){ int i; for (i = 0; i < MAX_RM_BLOCKS; i++) { if (rmBlocks[i].p == NULL) { rmBlocks[i].p = mem; rmBlocks[i].tag = tag; return; } } PM_fatalError("To many real mode memory block allocations!");}uint PMAPI _PM_findRealModeBlock(void *mem){ int i; for (i = 0; i < MAX_RM_BLOCKS; i++) { if (rmBlocks[i].p == mem) return rmBlocks[i].tag; } PM_fatalError("Could not find prior real mode memory block allocation!"); return 0;}const char * PMAPI PM_getCurrentPath(void){ static char cwd[256]; return getcwd(cwd,sizeof(cwd));}char PMAPI PM_getBootDrive(void){ return 'C'; }const char * PMAPI PM_getVBEAFPath(void){ return "c:\\"; }const char * PMAPI PM_getNucleusPath(void){ static char path[256]; char *env; if ((env = getenv("NUCLEUS_PATH")) != NULL) return env; if ((env = getenv("WINBOOTDIR")) != NULL) { strcpy(path,env); strcat(path,"\\system\\nucleus"); return path; } return "c:\\nucleus";}const char * PMAPI PM_getNucleusConfigPath(void){ static char path[256]; strcpy(path,PM_getNucleusPath()); PM_backslash(path); strcat(path,"config"); return path;}const char * PMAPI PM_getUniqueID(void){ return "DOS"; }const char * PMAPI PM_getMachineName(void){ return "DOS"; }int PMAPI PM_kbhit(void){ return kbhit();}int PMAPI PM_getch(void){ return getch();}PM_HWND PMAPI PM_openConsole(PM_HWND hwndUser,int device,int xRes,int yRes,int bpp,ibool fullScreen){ /* Not used for DOS */ (void)hwndUser; (void)device; (void)xRes; (void)yRes; (void)bpp; (void)fullScreen; return 0;}int PMAPI PM_getConsoleStateSize(void){ return sizeof(DOS_stateBuf);}void PMAPI PM_saveConsoleState(void *stateBuf,PM_HWND hwndConsole){ RMREGS regs; DOS_stateBuf *sb = stateBuf; /* Save the old video mode state */ regs.h.ah = 0x0F; PM_int86(0x10,®s,®s); sb->oldMode = regs.h.al & 0x7F; sb->old50Lines = false; if (sb->oldMode == 0x3) { regs.x.ax = 0x1130; regs.x.bx = 0; regs.x.dx = 0; PM_int86(0x10,®s,®s); sb->old50Lines = (regs.h.dl == 42 || regs.h.dl == 49); } (void)hwndConsole;}void PMAPI PM_changeResolution(PM_HWND hwndConsole,int xRes,int yRes,int bpp){ /* Not used for DOS */ (void)hwndConsole; (void)xRes; (void)yRes; (void)bpp;}void PMAPI PM_setSuspendAppCallback(int (_ASMAPIP saveState)(int flags)){ /* Not used for DOS */ (void)saveState;}void PMAPI PM_restoreConsoleState(const void *stateBuf,PM_HWND hwndConsole){ RMREGS regs; const DOS_stateBuf *sb = stateBuf; /* Retore 50 line mode if set */ if (sb->old50Lines) { regs.x.ax = 0x1112; regs.x.bx = 0; PM_int86(0x10,®s,®s); } (void)hwndConsole;}void PMAPI PM_closeConsole(PM_HWND hwndConsole){ /* Not used for DOS */ (void)hwndConsole;}void PMAPI PM_setOSCursorLocation(int x,int y){ uchar *_biosPtr = PM_getBIOSPointer(); PM_setByte(_biosPtr+0x50,x); PM_setByte(_biosPtr+0x51,y);}void PMAPI PM_setOSScreenWidth(int width,int height){ uchar *_biosPtr = PM_getBIOSPointer(); PM_setWord(_biosPtr+0x4A,width); PM_setWord(_biosPtr+0x4C,width*2); PM_setByte(_biosPtr+0x84,height-1); if (height > 25) { PM_setWord(_biosPtr+0x60,0x0607); PM_setByte(_biosPtr+0x85,0x08); } else { PM_setWord(_biosPtr+0x60,0x0D0E); PM_setByte(_biosPtr+0x85,0x016); }}void * PMAPI PM_mallocShared(long size){ return malloc(size);}int PMAPI PM_mapShared(void *ptr){ (void)ptr; return 0;}void PMAPI PM_freeShared(void *ptr){ free(ptr);}#define GetRMVect(intno,isr) *(isr) = ((ulong*)rmZeroPtr)[intno]#define SetRMVect(intno,isr) ((ulong*)rmZeroPtr)[intno] = (isr)ibool PMAPI PM_doBIOSPOST( ushort axVal, ulong BIOSPhysAddr, void *mappedBIOS, ulong BIOSLen){ static int firstTime = true; static uchar *rmZeroPtr; long Current10,Current6D,Current42; RMREGS regs; RMSREGS sregs; /* Create a zero memory mapping for us to use */ if (firstTime) { rmZeroPtr = PM_mapPhysicalAddr(0,0x7FFF,true); firstTime = false; } /* Remap the secondary BIOS to 0xC0000 physical */ if (BIOSPhysAddr != 0xC0000L || BIOSLen > 32768) { /* DOS cannot virtually remap the BIOS, so we can only work if all * the secondary controllers are identical, and we then use the * BIOS on the first controller for all the remaining controllers. * * For OS'es that do virtual memory, and remapping of 0xC0000 * physical (perhaps a copy on write mapping) should be all that * is needed. */ return false; } /* Save current handlers of int 10h and 6Dh */ GetRMVect(0x10,&Current10); GetRMVect(0x6D,&Current6D); /* POST the secondary BIOS */ GetRMVect(0x42,&Current42); SetRMVect(0x10,Current42); /* Restore int 10h to STD-BIOS */ regs.x.ax = axVal; PM_callRealMode(0xC000,0x0003,®s,&sregs); /* Restore current handlers */ SetRMVect(0x10,Current10); SetRMVect(0x6D,Current6D); /* Second the primary BIOS mappin 1:1 for 0xC0000 physical */ if (BIOSPhysAddr != 0xC0000L) { /* DOS does not support this */ (void)mappedBIOS; } return true;}void PMAPI PM_sleep(ulong milliseconds){ ulong microseconds = milliseconds * 1000L; LZTimerObject tm; LZTimerOnExt(&tm); while (LZTimerLapExt(&tm) < microseconds) ; LZTimerOffExt(&tm);}int PMAPI PM_getCOMPort(int port){ switch (port) { case 0: return 0x3F8; case 1: return 0x2F8; } return 0;}int PMAPI PM_getLPTPort(int port){ switch (port) { case 0: return 0x3BC; case 1: return 0x378; case 2: return 0x278; } return 0;}PM_MODULE PMAPI PM_loadLibrary( const char *szDLLName){ (void)szDLLName; return NULL;}void * PMAPI PM_getProcAddress( PM_MODULE hModule, const char *szProcName){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -