diff --git a/stella/src/ui/cyberstella/DirectInput.cxx b/stella/src/ui/cyberstella/DirectInput.cxx index d09bb8056..431503424 100644 --- a/stella/src/ui/cyberstella/DirectInput.cxx +++ b/stella/src/ui/cyberstella/DirectInput.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: DirectInput.cxx,v 1.3 2003-11-13 00:25:07 stephena Exp $ +// $Id: DirectInput.cxx,v 1.4 2003-11-14 00:47:35 stephena Exp $ //============================================================================ #include "pch.hxx" @@ -43,7 +43,11 @@ bool DirectInput::initialize(HWND hwnd) IID_IDirectInput8, (void**)&mylpdi, NULL))) return false; - // initialize the keyboard + // We use buffered mode whenever possible, since it is more + // efficient than constantly getting a full state snapshot + // and analyzing it for state changes + + // Initialize the keyboard if(FAILED(mylpdi->CreateDevice(GUID_SysKeyboard, &myKeyboard, NULL))) return false; if(FAILED(myKeyboard->SetDataFormat(&c_dfDIKeyboard))) @@ -51,77 +55,91 @@ bool DirectInput::initialize(HWND hwnd) if(FAILED(myKeyboard->SetCooperativeLevel(hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) return false; - DIPROPDWORD dipdw; - dipdw.diph.dwSize = sizeof(DIPROPDWORD); - dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); - dipdw.diph.dwObj = 0; - dipdw.diph.dwHow = DIPH_DEVICE; - dipdw.dwData = 256; - if(FAILED(myKeyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph))) + DIPROPDWORD k_dipdw; + k_dipdw.diph.dwSize = sizeof(DIPROPDWORD); + k_dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + k_dipdw.diph.dwObj = 0; + k_dipdw.diph.dwHow = DIPH_DEVICE; + k_dipdw.dwData = 64; + if(FAILED(myKeyboard->SetProperty(DIPROP_BUFFERSIZE, &k_dipdw.diph))) return false; if(FAILED(myKeyboard->Acquire())) return false; - // Make sure to reset the event buffer - myEventBufferPos = 0; + // Initialize the mouse + if(FAILED(mylpdi->CreateDevice(GUID_SysMouse, &myMouse, NULL))) + return false; + if(FAILED(myMouse->SetDataFormat(&c_dfDIMouse2))) + return false; + if(FAILED(myMouse->SetCooperativeLevel(hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) + return false; // DISCL_FOREGROUND | DISCL_EXCLUSIVE + + DIPROPDWORD m_dipdw; + m_dipdw.diph.dwSize = sizeof(DIPROPDWORD); + m_dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + m_dipdw.diph.dwObj = 0; + m_dipdw.diph.dwHow = DIPH_DEVICE; + m_dipdw.dwData = 64; + if(FAILED(myMouse->SetProperty(DIPROP_BUFFERSIZE, &m_dipdw.diph))) + return false; + + if(FAILED(myMouse->Acquire())) + return false; return true; } -void DirectInput::update() +bool DirectInput::getKeyEvents(DIDEVICEOBJECTDATA* keyEvents, + DWORD* numKeyEvents) { HRESULT hr; - if(myKeyboard != NULL) + // Make sure the keyboard has been initialized + if(myKeyboard == NULL) + return false; + + // Check for keyboard events + hr = myKeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), + keyEvents, numKeyEvents, 0 ); + + if(hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED) { - DIDEVICEOBJECTDATA keyEvents[256]; - DWORD numKeyEvents = 256; + hr = myKeyboard->Acquire(); + if(hr == DIERR_OTHERAPPHASPRIO) + return false; hr = myKeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), - keyEvents, &numKeyEvents, 0 ); - - if(hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED) - { - hr = myKeyboard->Acquire(); - if(hr == DIERR_OTHERAPPHASPRIO) - return; - - hr = myKeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), - keyEvents, &numKeyEvents, 0 ); - } - - // add these new key events to the event buffer - for(unsigned int i = 0; i < numKeyEvents; i++ ) - { - uInt32 j = myEventBufferPos; - if(j < 100) - { - myEventBuffer[j].type = (keyEvents[i].dwData & 0x80) ? KEY_DOWN : KEY_UP; - myEventBuffer[j].key.key = keyEvents[i].dwOfs; - myEventBuffer[j].key.state = (myEventBuffer[j].type == KEY_DOWN) ? 1 : 0; - myEventBufferPos++; - } - else // if we run out of room, then ignore new events - { - myEventBufferPos = 100; - break; - } - } + keyEvents, numKeyEvents, 0 ); } - // else check mouse + + return true; } -bool DirectInput::pollEvent(DI_Event* event) +bool DirectInput::getMouseEvents(DIDEVICEOBJECTDATA* mouseEvents, + DWORD* numMouseEvents) { - // Pump the event buffer and return if a new event is found - if(myEventBufferPos > 0) - { - *event = myEventBuffer[--myEventBufferPos]; - return true; - } - else + HRESULT hr; + + // Make sure the mouse has been initialized + if(myMouse == NULL) return false; + + // Check for mouse events + hr = myMouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), + mouseEvents, numMouseEvents, 0 ); + + if(hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED) + { + hr = myMouse->Acquire(); + if(hr == DIERR_OTHERAPPHASPRIO) + return false; + + hr = myMouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), + mouseEvents, numMouseEvents, 0 ); + } + + return true; } void DirectInput::cleanup() diff --git a/stella/src/ui/cyberstella/DirectInput.hxx b/stella/src/ui/cyberstella/DirectInput.hxx index d65ab39fe..48ad3be39 100644 --- a/stella/src/ui/cyberstella/DirectInput.hxx +++ b/stella/src/ui/cyberstella/DirectInput.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: DirectInput.hxx,v 1.4 2003-11-13 00:25:07 stephena Exp $ +// $Id: DirectInput.hxx,v 1.5 2003-11-14 00:47:35 stephena Exp $ //============================================================================ #ifndef DIRECT_INPUT_HXX @@ -28,34 +28,14 @@ class DirectInput DirectInput(); ~DirectInput(); - public: - enum type_tt { KEY_DOWN, KEY_UP }; - - struct KeyboardEvent - { - uInt32 key; - uInt8 state; - }; - - struct DI_Event - { - type_tt type; - union - { - KeyboardEvent key; - }; - }; + bool getKeyEvents(DIDEVICEOBJECTDATA* keyEvents, DWORD* numKeyEvents); + bool getMouseEvents(DIDEVICEOBJECTDATA* mouseEvents, DWORD* numMouseEvents); bool initialize(HWND hwnd); void update(); - bool pollEvent(DI_Event* event); - private: - DI_Event myEventBuffer[100]; - uInt32 myEventBufferPos; - void cleanup(); static BOOL CALLBACK EnumDevicesProc(const DIDEVICEINSTANCE* lpddi, LPVOID pvRef ); diff --git a/stella/src/ui/cyberstella/FrameBufferWin32.cxx b/stella/src/ui/cyberstella/FrameBufferWin32.cxx index cf429c108..becf04d20 100644 --- a/stella/src/ui/cyberstella/FrameBufferWin32.cxx +++ b/stella/src/ui/cyberstella/FrameBufferWin32.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: FrameBufferWin32.cxx,v 1.2 2003-11-13 00:25:07 stephena Exp $ +// $Id: FrameBufferWin32.cxx,v 1.3 2003-11-14 00:47:35 stephena Exp $ //============================================================================ #include @@ -48,12 +48,14 @@ FrameBufferWin32::FrameBufferWin32() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FrameBufferWin32::~FrameBufferWin32() { +OutputDebugString("got here FrameBufferWin32::~FrameBufferWin32()"); cleanup(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameBufferWin32::cleanup() { +OutputDebugString("got here FrameBufferWin32::cleanup()"); if(m_piDDPalette) { m_piDDPalette->Release(); @@ -81,7 +83,7 @@ void FrameBufferWin32::cleanup() if(myHWND) { ::DestroyWindow( myHWND ); - +OutputDebugString("got here destroyed window"); // // Remove the WM_QUIT which will be in the message queue // so that the main window doesn't exit @@ -186,6 +188,7 @@ OutputDebugString("got here failed 4"); // // Get the best video mode for game width // +//int cx = 640; int cy = 480; int cx = 320; int cy = 240; ::SetRect( &m_rectScreen, 0, 0, cx, cy ); @@ -319,7 +322,7 @@ OutputDebugString("got here failed 12"); cleanup(); return false; } -OutputDebugString("got here init exited with true"); + // If we get this far, then assume that there were no problems return true; } @@ -459,57 +462,46 @@ LRESULT CALLBACK FrameBufferWin32::StaticWindowProc( } -BOOL FrameBufferWin32::WndProc( - UINT uMsg, - WPARAM wParam, - LPARAM lParam - ) +BOOL FrameBufferWin32::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) - { - case WM_ACTIVATE: - m_fActiveWindow = ( wParam != WA_INACTIVE ); - break; + switch (uMsg) + { + case WM_ACTIVATE: + m_fActiveWindow = (wParam != WA_INACTIVE); + break; - case WM_DESTROY: - ::PostQuitMessage( 0 ); - break; + case WM_DESTROY: + ::PostQuitMessage(0); + break; case WM_KEYDOWN: - switch ( (int)wParam ) - { - case VK_ESCAPE: - // - // Escape = Exit - // + switch((int)wParam) + { + case VK_ESCAPE: + ::PostMessage(myHWND, WM_CLOSE, 0, 0); - ::PostMessage( myHWND, WM_CLOSE, 0, 0 ); - break; - - } - break; + // For some braindead reason, the exit event must be handled + // here. Normally, an Escape event would be the same as any + // other and the Console would handle it. + // But since Windows insists on doing it this way, we have + // to make sure that the Escape event is still received by + // the core. + myConsole->eventHandler().sendEvent(Event::Quit, 1); + break; + } + break; case WM_PAINT: - { - PAINTSTRUCT ps; - ::BeginPaint( myHWND, &ps ); - ::EndPaint( myHWND, &ps ); - } - break; + PAINTSTRUCT ps; + ::BeginPaint( myHWND, &ps ); + ::EndPaint( myHWND, &ps ); + break; default: - // - // Unhandled message - // + return FALSE; + } - return FALSE; - } - - // - // Handled message - // - - return TRUE; + return TRUE; } HRESULT WINAPI FrameBufferWin32::EnumModesCallback( diff --git a/stella/src/ui/cyberstella/MainWin32.cxx b/stella/src/ui/cyberstella/MainWin32.cxx index 27438572e..e0f38f796 100644 --- a/stella/src/ui/cyberstella/MainWin32.cxx +++ b/stella/src/ui/cyberstella/MainWin32.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: MainWin32.cxx,v 1.1 2003-11-13 00:25:07 stephena Exp $ +// $Id: MainWin32.cxx,v 1.2 2003-11-14 00:47:35 stephena Exp $ //============================================================================ #define STRICT @@ -39,10 +39,12 @@ MainWin32::MainWin32(const uInt8* image, uInt32 size, const char* filename, Settings& settings, PropertiesSet& properties) : theSettings(settings), thePropertiesSet(properties), - myIsInitialized(false), theDisplay(NULL), theSound(NULL), - theInput(NULL) + theInput(NULL), + theMouseX(0), + thePaddleMode(0), + myIsInitialized(false) { // Setup the DirectX window theDisplay = new FrameBufferWin32(); @@ -58,13 +60,12 @@ MainWin32::MainWin32(const uInt8* image, uInt32 size, const char* filename, // theSound = new SoundWin32(); // else theSound = new Sound(); -/* if(!theSound) { cleanup(); return; } -*/ + // theSound->setSoundVolume(theSettings.getInt("volume")); // Create the 2600 game console @@ -138,16 +139,13 @@ DWORD MainWin32::run() for(;;) { - if( ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) + if(::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) { - if( msg.message == WM_QUIT ) - { -// theConsole->eventHandler().sendEvent(Event::Quit, 1); + if(msg.message == WM_QUIT) break; - } - ::TranslateMessage( &msg ); - ::DispatchMessage( &msg ); + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); } else if (theDisplay->windowActive()) { @@ -204,51 +202,85 @@ DWORD MainWin32::run() void MainWin32::UpdateEvents() { - // Update the input devices, and gather all pending events - theInput->update(); + DIDEVICEOBJECTDATA eventArray[64]; + DWORD numEvents; - const int nSize = _countof(keyList); - DirectInput::DI_Event event; - while(theInput->pollEvent(&event)) + // Check for keyboard events + numEvents = 64; + if(theInput->getKeyEvents(eventArray, &numEvents)) { - switch(event.type) + for(unsigned int i = 0; i < numEvents; i++ ) { - case DirectInput::KEY_DOWN: - case DirectInput::KEY_UP: - uInt32 key = event.key.key; - uInt8 state = event.key.state; + uInt32 key = eventArray[i].dwOfs; + uInt8 state = eventArray[i].dwData & 0x80 ? 1 : 0; - for(uInt32 i = 0; i < sizeof(keyList) / sizeof(Switches); ++i) - { - if(keyList[i].nVirtKey == key) - theConsole->eventHandler().sendKeyEvent(keyList[i].keyCode, state); - } - - break; - } + for(uInt32 i = 0; i < sizeof(keyList) / sizeof(Switches); ++i) + { + if(keyList[i].nVirtKey == key) + theConsole->eventHandler().sendKeyEvent(keyList[i].keyCode, state); + } + } } - - // - // I do this because an event may appear multiple times in the map - // and I don't want to undo a set i may have done earlier in the loop - // - - -// long rgKeyEventState[ nSize ]; -// ZeroMemory( rgKeyEventState, nSize * sizeof(StellaEvent::KeyCode) ); - - // Update keyboard -/* - if(m_pDirectKeyboard->Update() == S_OK) + // Check for mouse events + numEvents = 64; + if(theInput->getMouseEvents(eventArray, &numEvents)) { - for(int i = 0; i < nSize; ++i) + for(unsigned int i = 0; i < numEvents; i++ ) { - int state = (m_pDirectKeyboard->IsButtonPressed(keyList[i].nVirtKey)) ? 1 : 0; - theConsole->eventHandler().sendKeyEvent(keyList[i].keyCode, state); - } + Event::Type type = Event::LastType; + Int32 value; + switch(eventArray[i].dwOfs) + { + // Check for button press and release + case DIMOFS_BUTTON0: + case DIMOFS_BUTTON1: + case DIMOFS_BUTTON2: + case DIMOFS_BUTTON3: + case DIMOFS_BUTTON4: + case DIMOFS_BUTTON5: + case DIMOFS_BUTTON6: + case DIMOFS_BUTTON7: + value = (Int32) eventArray[i].dwData & 0x80 ? 1 : 0; + + if(thePaddleMode == 0) + type = Event::PaddleZeroFire; + else if(thePaddleMode == 1) + type = Event::PaddleOneFire; + else if(thePaddleMode == 2) + type = Event::PaddleTwoFire; + else if(thePaddleMode == 3) + type = Event::PaddleThreeFire; + + theConsole->eventHandler().sendEvent(type, value); + break; + + // Check for horizontal movement + case DIMOFS_X: + theMouseX = theMouseX + eventArray[i].dwData; + + // Force mouseX between 0 ... 999 + if(theMouseX < 0) + theMouseX = 0; + else if(theMouseX > 999) + theMouseX = 999; + + Int32 value = (999 - theMouseX) * 1000; + + if(thePaddleMode == 0) + type = Event::PaddleZeroResistance; + else if(thePaddleMode == 1) + type = Event::PaddleOneResistance; + else if(thePaddleMode == 2) + type = Event::PaddleTwoResistance; + else if(thePaddleMode == 3) + type = Event::PaddleThreeResistance; + + theConsole->eventHandler().sendEvent(type, value); + break; + } + } } -*/ /* // // Update joystick diff --git a/stella/src/ui/cyberstella/MainWin32.hxx b/stella/src/ui/cyberstella/MainWin32.hxx index e43de7ef0..641cdb01c 100644 --- a/stella/src/ui/cyberstella/MainWin32.hxx +++ b/stella/src/ui/cyberstella/MainWin32.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: MainWin32.hxx,v 1.1 2003-11-13 00:25:07 stephena Exp $ +// $Id: MainWin32.hxx,v 1.2 2003-11-14 00:47:35 stephena Exp $ //============================================================================ #ifndef MAIN_WIN32_HXX @@ -41,7 +41,7 @@ class DirectInput; in the Porting.txt document @author Stephen Anthony - @version $Id: MainWin32.hxx,v 1.1 2003-11-13 00:25:07 stephena Exp $ + @version $Id: MainWin32.hxx,v 1.2 2003-11-14 00:47:35 stephena Exp $ */ class MainWin32 { @@ -68,6 +68,7 @@ class MainWin32 private: void UpdateEvents(); + void cleanup(); private: // Pointer to the console object @@ -95,117 +96,16 @@ class MainWin32 }; static Switches keyList[StellaEvent::LastKCODE]; - -///////////////////////////////////////////////////////// -// -// These will move into a separate Framebuffer class soon -// -///////////////////////////////////////////////////////// -#if 0 - public: - HWND hwnd() const { return myHWND; } - - ////////////////////////////////////////////////////////////////////// - // The following methods are derived from FrameBuffer.hxx - ////////////////////////////////////////////////////////////////////// - /** - This routine should be called once the console is created to setup - the video system for us to use. Return false if any operation fails, - otherwise return true. - */ - bool init(); - - /** - This routine should be called anytime the MediaSource needs to be redrawn - to the screen. - */ - void drawMediaSource(); - - /** - This routine should be called to draw a rectangular box with sides - at the specified coordinates. - - @param x The x coordinate - @param y The y coordinate - @param w The width of the box - @param h The height of the box - */ - void drawBoundedBox(uInt32 x, uInt32 y, uInt32 w, uInt32 h); - - /** - This routine should be called to draw text at the specified coordinates. - - @param x The x coordinate - @param y The y coordinate - @param message The message text - */ - void drawText(uInt32 x, uInt32 y, const string& message); - - /** - This routine should be called to draw character 'c' at the specified coordinates. - - @param x The x coordinate - @param y The y coordinate - @param c The character to draw - */ - void drawChar(uInt32 x, uInt32 y, uInt32 c); - - /** - This routine is called before any drawing is done (per-frame). - */ - void preFrameUpdate(); - - /** - This routine is called after any drawing is done (per-frame). - */ - void postFrameUpdate(); - - /** - This routine is called when the emulation has received - a pause event. - - @param status The received pause status - */ - virtual void pauseEvent(bool status); -#endif -////////////////////////////////////////////////// -// Some of this will stay here, some will go to -// the FrameBufferWin32 class -////////////////////////////////////////////////// - private: const CGlobalData* m_rGlobalData; + // Indicates the current mouse position in the X direction + Int32 theMouseX; + + // Indicates the current paddle mode + uInt32 thePaddleMode; + + // Indicates that all subsystems were initialized bool myIsInitialized; - - void cleanup(); -#if 0 - static LRESULT CALLBACK StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); - BOOL WndProc( UINT uMsg, WPARAM wParam, LPARAM lParam ); - - static HRESULT WINAPI EnumModesCallback( LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext); - - void cleanup(); - - HWND myHWND; - bool m_fActiveWindow; - - RECT m_rectScreen; - POINT m_ptBlitOffset; - - // Stella objects - SIZE mySizeGame; - BYTE myPalette[256]; - - // - // DirectX - // - IDirectDraw* m_piDD; - IDirectDrawSurface* m_piDDSPrimary; - IDirectDrawSurface* m_piDDSBack; - IDirectDrawPalette* m_piDDPalette; - - static LPCTSTR pszClassName; -#endif }; #endif