⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win_sys.c

📁 The source code of Doom legacy for windows
💻 C
📖 第 1 页 / 共 5 页
字号:
        KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,KEY_NUMLOCK,KEY_SCROLLLOCK,KEY_KEYPAD7,
        KEY_KEYPAD8,KEY_KEYPAD9,KEY_MINUSPAD,KEY_KEYPAD4,KEY_KEYPAD5,KEY_KEYPAD6,KEY_PLUSPAD,KEY_KEYPAD1,
        KEY_KEYPAD2,KEY_KEYPAD3,KEY_KEYPAD0,KEY_KPADDEL,      0,      0,      0,      KEY_F11,
        KEY_F12,0,          0,      0,      0,      0,      0,      0,
        0,          0,      0,      0,      0,      0,      0,      0,
        0,          0,      0,      0,      0,      0,      0,      0,
        0,          0,      0,      0,      0,      0,      0,      0,
        0,          0,      0,      0,      0,      0,      0,      0,

        //  0       1       2       3       4       5       6       7
        //  8       9       A       B       C       D       E       F

        0,          0,      0,      0,      0,      0,      0,      0,          //0x80
        0,          0,      0,      0,      0,      0,      0,      0,
        0,          0,      0,      0,      0,      0,      0,      0,
        0,          0,      0,      0,  KEY_ENTER,KEY_CTRL, 0,      0,
        0,          0,      0,      0,      0,      0,      0,      0,          //0xa0
        0,          0,      0,      0,      0,      0,      0,      0,
        0,          0,      0, KEY_KPADDEL, 0,KEY_KPADSLASH,0,      0,
        KEY_ALT,0,          0,      0,      0,      0,      0,      0,
        0,          0,      0,      0,      0,      0,      0,          KEY_HOME,               //0xc0
        KEY_UPARROW,KEY_PGUP,0,KEY_LEFTARROW,0,KEY_RIGHTARROW,0,KEY_END,
        KEY_DOWNARROW,KEY_PGDN, KEY_INS,KEY_DEL,0,0,0,0,
        0,          0,      0,KEY_LEFTWIN,KEY_RIGHTWIN,KEY_MENU, 0, 0,
        0,          0,      0,      0,      0,      0,      0,      0,          //0xe0
        0,          0,      0,      0,      0,      0,      0,      0,
        0,          0,      0,      0,      0,      0,      0,      0,
        0,          0,      0,      0,      0,      0,      0,      0
};

int pausepressed=0;

//  Return a key that has been pushed, or 0
//  (replace getchar() at game startup)
//
int I_GetKey (void)
{
    event_t   *ev;
        
    if (eventtail != eventhead)
    {
        ev = &events[eventtail];
        eventtail = (++eventtail)&(MAXEVENTS-1);
        if (ev->type == ev_keydown)
            return ev->data1;
        else
            return 0;
    }
    return 0;
}


// -----------------
// I_StartupKeyboard
// Installs DirectInput keyboard
// -----------------
#define DI_KEYBOARD_BUFFERSIZE          32              //number of data elements in keyboard buffer
void I_StartupKeyboard()
{
    DIPROPDWORD dip;

    //faB: make sure the app window has the focus or
    //     DirectInput acquire keyboard won't work
    if ( hWndMain!=NULL )
    {
        SetFocus(hWndMain);
        ShowWindow(hWndMain, SW_SHOW);
        UpdateWindow(hWndMain);
    }

    //faB: detect error
    if (lpDIK != NULL) {
        CONS_Printf ("\2I_StartupKeyboard(): called twice\n");
        return;
    }

    CreateDevice2 (lpDI, &GUID_SysKeyboard, &lpDIK, NULL);

    if (lpDIK)
    {
        if (FAILED( lpDIK->lpVtbl->SetDataFormat (lpDIK, &c_dfDIKeyboard) ))
            I_Error ("Couldn't set keyboard data format");
            
        // create buffer for buffered data
        dip.diph.dwSize       = sizeof(dip);
        dip.diph.dwHeaderSize = sizeof(dip.diph);
        dip.diph.dwObj        = 0;
        dip.diph.dwHow        = DIPH_DEVICE;
        dip.dwData            = DI_KEYBOARD_BUFFERSIZE;
        if (FAILED( lpDIK->lpVtbl->SetProperty (lpDIK, DIPROP_BUFFERSIZE, &dip.diph)))
            I_Error ("Couldn't set keyboard buffer size");
    
        if (FAILED( lpDIK->lpVtbl->SetCooperativeLevel (lpDIK, hWndMain, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND)))
            I_Error ("Couldn't set keyboard coop level");

        //faB: it seems to FAIL if the window doesn't have the focus
        //BP: acquire it latter
        //if (FAILED( lpDIK->lpVtbl->Acquire (lpDIK) ))
        //    I_Error ("Couldn't acquire keyboard\n");
    }
    else
        I_Error ("Couldn't create keyboard input");

    I_AddExitFunc (I_ShutdownKeyboard);
    hacktics = 0;                       //faB: see definition
    keyboard_started = true;
}


// ------------------
// I_ShutdownKeyboard
// Release DirectInput keyboard.
// ------------------
static void I_ShutdownKeyboard()
{
    if (!keyboard_started)
        return;
        
    CONS_Printf ("I_ShutdownKeyboard()\n");
        
    if ( lpDIK )
    {
        lpDIK->lpVtbl->Unacquire (lpDIK);
        lpDIK->lpVtbl->Release (lpDIK);
        lpDIK = NULL;
    }

    keyboard_started = false;
}


// -------------------
// I_GetKeyboardEvents
// Get buffered data from the keyboard
// -------------------
static void I_GetKeyboardEvents (void)
{
    static  boolean         KeyboardLost = false;
    
    //faB: simply repeat the last pushed key every xx tics,
    //     make more user friendly input for Console and game Menus
    #define KEY_REPEAT_DELAY    (TICRATE/17)      // TICRATE tics, repeat every 1/3 second
    static  long            RepeatKeyTics = 0;
    static  BYTE            RepeatKeyCode;
    
    DIDEVICEOBJECTDATA      rgdod[DI_KEYBOARD_BUFFERSIZE];
    DWORD                   dwItems;
    DWORD                   d;
    HRESULT                 hr;
    int                     ch;
    
    event_t         event;
    
    if (!keyboard_started)
        return;
    
getBufferedData:
    dwItems = DI_KEYBOARD_BUFFERSIZE;
    hr = lpDIK->lpVtbl->GetDeviceData (lpDIK, sizeof(DIDEVICEOBJECTDATA),
                                       rgdod,
                                       &dwItems,
                                       0 );
    
    // If data stream was interrupted, reacquire the device and try again.
    if (hr == DIERR_INPUTLOST || hr==DIERR_NOTACQUIRED)
    {
        // why it succeeds to acquire just after I don't understand.. so I set the flag BEFORE
        KeyboardLost = true;
        
        hr = lpDIK->lpVtbl->Acquire (lpDIK);
        if (SUCCEEDED(hr))
            goto getBufferedData;
        return;
    }
    
    // we lost data, get device actual state to recover lost information
    if (hr==DI_BUFFEROVERFLOW)
    {
        //I_Error ("DI buffer overflow (keyboard)");
        //I_RecoverKeyboardState ();
        
        //hr = lpDIM->lpVtbl->GetDeviceState (lpDIM, sizeof(keys), &diMouseState);
    }
    
    // We got buffered input, act on it
    if (SUCCEEDED(hr))
    {
        // if we previously lost keyboard data, recover its current state
        if (KeyboardLost)
        {
            //faB: my current hack simply clear the keys so we don't have the last pressed keys
            // still active.. to have to re-trigger it is not much trouble for the user.
            memset (gamekeydown, 0, sizeof(gamekeydown));
            //CONS_Printf ("we lost it, we cleared stuff!\n");
            KeyboardLost = false;
        }
        
        // dwItems contains number of elements read (could be 0)
        for (d = 0; d < dwItems; d++)
        {
            // dwOfs member is DIK_* value
            // dwData member 0x80 bit set press down, clear is release
            
            if (rgdod[d].dwData & 0x80)
                event.type = ev_keydown;
            else
                event.type = ev_keyup;
            
            ch = rgdod[d].dwOfs & 0xFF;
            if (ASCIINames[ch]!=0)
                event.data1 = ASCIINames[ch];
            else
                event.data1 = ch + 0x80;
            
            D_PostEvent(&event);
        }

        //
        // Key Repeat
        //
        if (dwItems) {
            // new key events, so stop repeating key
            RepeatKeyCode = 0;
            RepeatKeyTics = hacktics + (KEY_REPEAT_DELAY*2);   //delay is trippled for first repeating key
            if (event.type == ev_keydown)       // use the last event!
                RepeatKeyCode = event.data1;
        }
        else {
            // no new keys, repeat last pushed key after some time
            if (RepeatKeyCode &&
                (hacktics - RepeatKeyTics) > KEY_REPEAT_DELAY)
            {
                event.type = ev_keydown;
                event.data1 = RepeatKeyCode;
                D_PostEvent (&event);

                RepeatKeyTics = hacktics;
            }
        }
    }
}


//
// Closes DirectInput
//
static void I_ShutdownDirectInput (void)
{
    if (lpDI!=NULL)
        lpDI->lpVtbl->Release (lpDI);
    lpDI = NULL;
}


//  This stuff should get rid of the exception and page faults when
//  Doom bugs out with an error. Now it should exit cleanly.
//
int  I_StartupSystem(void)
{
    HRESULT hr;

    // some 'more globals than globals' things to initialize here ?
    graphics_started = false;
    keyboard_started = false;
    sound_started = false;
    timer_started = false;
    cdaudio_started = false;
    
    I_DetectWin95 ();

    // check for OS type and version here ?
#ifdef NDEBUG
    signal(SIGABRT, signal_handler);
    signal(SIGFPE , signal_handler);
    signal(SIGILL , signal_handler);
    signal(SIGSEGV, signal_handler);
    signal(SIGTERM, signal_handler);
    signal(SIGINT , signal_handler);
#endif

    // create DirectInput - so that I_StartupKeyboard/Mouse can be called later on
    // from D_DoomMain just like DOS version
    hr = DirectInputCreate (myInstance, DIRECTINPUT_VERSION, &lpDI, NULL);

    if ( SUCCEEDED( hr ) )
        bDX0300 = FALSE;
    else
    {
        // try opening DirectX3 interface for NT compatibility
        hr = DirectInputCreate (myInstance, DXVERSION_NTCOMPATIBLE, &lpDI, NULL);

        if ( FAILED ( hr ) )
        {
            char* sErr;
            switch(hr)
            {
            case DIERR_BETADIRECTINPUTVERSION:
                sErr = "DIERR_BETADIRECTINPUTVERSION";
                break;
            case DIERR_INVALIDPARAM :
                sErr = "DIERR_INVALIDPARAM";
                break;
            case DIERR_OLDDIRECTINPUTVERSION :
                sErr = "DIERR_OLDDIRECTINPUTVERSION";
                break;
            case DIERR_OUTOFMEMORY :
                sErr = "DIERR_OUTOFMEMORY";
                break;
            default:
                sErr = "UNKNOWN";
                break;
            }
            I_Error ("Couldn't create DirectInput (reason: %s)", sErr);
        }
        else
            CONS_Printf ("\2Using DirectX3 interface\n");

        // only use DirectInput3 compatible structures and calls
        bDX0300 = TRUE;
    }
    I_AddExitFunc (I_ShutdownDirectInput);
    return 0;
}


//  Closes down everything. This includes restoring the initial
//  pallete and video mode, and removing whatever mouse, keyboard, and
//  timer routines have been installed.
//
//  NOTE : Shutdown user funcs. are effectively called in reverse order.
//
void I_ShutdownSystem()
{
    int c;
    
    for (c=MAX_QUIT_FUNCS-1; c>=0; c--)
    {
        if (quit_funcs[c])
            (*quit_funcs[c])();
    }
}


// ---------------
// I_SaveMemToFile
// Save as much as iLength bytes starting at pData, to
// a new file of given name. The file is overwritten if it is present.
// ---------------
void I_SaveMemToFile (unsigned char* pData, unsigned long iLength, char* sFileName)
{
    HANDLE  fileHandle;
    DWORD   bytesWritten;
    fileHandle = CreateFile (sFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
    if (fileHandle == INVALID_HANDLE_VALUE)
    {
        I_Error ("SaveMemToFile");
    }
    WriteFile (fileHandle, pData, iLength, &bytesWritten, NULL);
    CloseHandle (fileHandle);
}

// my god how win32 suck
typedef BOOL (WINAPI *MyFunc)(LPCSTR RootName, PULARGE_INTEGER pulA, PULARGE_INTEGER pulB, PULARGE_INTEGER pulFreeBytes); 

void I_GetDiskFreeSpace(INT64 *freespace)
{
static MyFunc pfnGetDiskFreeSpaceEx=NULL;
static boolean testwin95 = false;

    INT64 usedbytes;

    if(!testwin95)
    {
        HINSTANCE h = LoadLibraryA("kernel32.dll"); 

        if (h) { 
             pfnGetDiskFreeSpaceEx = (MyFunc)GetProcAddress(h,"GetDiskFreeSpaceExA"); 
             FreeLibrary(h); 
        }
        testwin95 = true;
    } 
    if (pfnGetDiskFreeSpaceEx) { 
        if (!pfnGetDiskFreeSpaceEx(NULL,(PULARGE_INTEGER)freespace,(PULARGE_INTEGER)&usedbytes,NULL)) 
            *freespace = MAXINT;
    } 
    else
    {       
        ULONG SectorsPerCluster, BytesPerSector, NumberOfFreeClusters;
        ULONG TotalNumberOfClusters;
        GetDiskFreeSpace(NULL, &SectorsPerCluster, &BytesPerSector, 
                               &NumberOfFreeClusters, &TotalNumberOfClusters);
        *freespace = BytesPerSector*SectorsPerCluster*NumberOfFreeClusters;
    }
}

char *I_GetUserName(void)
{
static char username[MAXPLAYERNAME];
     char  *p;
     int   ret;
     ULONG i=MAXPLAYERNAME;
     ret = GetUserName(username,&i);
     if(!ret)
     {
         if((p=getenv("USER"))==NULL)
             if((p=getenv("user"))==NULL)
                 if((p=getenv("USERNAME"))==NULL)
                     if((p=getenv("username"))==NULL)
                         return NULL;
         strncpy(username,p,MAXPLAYERNAME);
     }
     if( strcmp(username,"")==0 )
         return NULL;
     return username;
}

int  I_mkdir(const char *dirname, int unixright)
{
    return mkdir(dirname);
    //TODO: should implement ntright under nt ...
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -