From f1494776e47c1e4b2ac6ba7851d0e87197617f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20Sch=C2=84fer?= Date: Mon, 15 Apr 2024 12:13:11 +0200 Subject: [PATCH] OS/2 specific branch created. Work on audio and window system done. --- src/AudioBackend.c | 374 ++++++++++++++++++++++++++++++++++++++++++ src/Window_OS2.c | 396 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 770 insertions(+) create mode 100644 src/Window_OS2.c diff --git a/src/AudioBackend.c b/src/AudioBackend.c index 5f750b9c1..340da9301 100644 --- a/src/AudioBackend.c +++ b/src/AudioBackend.c @@ -1513,6 +1513,380 @@ cc_result Audio_AllocChunks(cc_uint32 size, void** chunks, int numChunks) { return AudioBase_AllocChunks(size, chunks, numChunks); } +void Audio_FreeChunks(void** chunks, int numChunks) { + AudioBase_FreeChunks(chunks, numChunks); +} +#elif defined CC_BUILD_SDL2 +/*########################################################################################################################* +*----------------------------------------------------OS/2 backend---------------------------------------------------* +*#########################################################################################################################*/ +#define INCL_BASE +#define INCL_MCIOS2 +#define INCL_OS2MM +#define INCL_DOSSEMAPHORES +#include +#include +#include +#include +#include + +#define NUM_BUFFERS 4 +#define SIZE_BUFFERS 4096 +#define AUDIO_COMMON_ALLOC + +struct AudioContext { + int count; + int volume; +}; + +typedef struct DeviceContext { + CHAR productInfo[MAX_PRODINFO]; + USHORT usDeviceId; + BYTE _pad[2]; + HEV hevBuf; + ULONG ulState; + cc_bool initRun; + PMCI_MIX_BUFFER pFillBuffer; + PMCI_MIX_BUFFER pDrainBuffer; + ULONG cMixBuffers; + MCI_MIX_BUFFER aMixBuffers[NUM_BUFFERS]; + MCI_MIXSETUP_PARMS stMCIMixSetup; +} DeviceContext; + +DeviceContext devicecontext; + +// get next buffer +static PMCI_MIX_BUFFER _getNextBuffer(PMCI_MIX_BUFFER pBuffer) +{ + PMCI_MIX_BUFFER pFirstBuffer = &devicecontext.aMixBuffers[0]; + PMCI_MIX_BUFFER pLastBuffer = &devicecontext.aMixBuffers[devicecontext.cMixBuffers - 1]; + return (pBuffer == pLastBuffer ? pFirstBuffer : pBuffer + 1); +} + +/* Playback callback function */ +static LONG APIENTRY cbAudioWriteEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags) +{ + ULONG ulRC; + + //debug(SDL_LOG_CATEGORY_AUDIO,"cbAudioWriteEvent: ulStatus = %lu, pBuffer = %p, ulFlags = %#lX",ulStatus,pBuffer,ulFlags); + + if (devicecontext.ulState == 2) return 0; + + if (ulFlags != MIX_WRITE_COMPLETE) return 0; + + devicecontext.pDrainBuffer = pBuffer; + ulRC = devicecontext.stMCIMixSetup.pmixWrite( + devicecontext.stMCIMixSetup.ulMixHandle, + devicecontext.pDrainBuffer, 1 + ); + if (ulRC != MCIERR_SUCCESS) { + Logger_SimpleWarn(ulRC, "Write to audio mixer failed"); + return 0; + } + + ulRC = DosPostEventSem(devicecontext.hevBuf); + if (ulRC != NO_ERROR && ulRC != ERROR_ALREADY_POSTED) { + Logger_SimpleWarn(ulRC, "Semaphore: post event failed"); + } + + return 1; /* return value doesn't seem to matter. */ +} + +cc_bool AudioBackend_Init(void) { + MCI_SYSINFO_PARMS stMCISysInfo; + CHAR acBuf[256]; + ULONG ulDevicesNum; + MCI_SYSINFO_LOGDEVICE stLogDevice; + MCI_SYSINFO_PARMS stSysInfoParams; + ULONG ulRC; + ULONG ulNumber; + MCI_GENERIC_PARMS stMCIGenericParms; + MCI_AMP_OPEN_PARMS stMCIAmpOpen; + MCI_BUFFER_PARMS stMCIBuffer; + MCI_SET_PARMS msp; + + if (devicecontext.initRun && devicecontext.usDeviceId != (USHORT)~0) { /* Device is already open. */ + return true; + } + + devicecontext.usDeviceId = (USHORT)~0; + devicecontext.initRun = true; + Mem_Set(&stMCISysInfo, 0, sizeof(stMCISysInfo)); + Mem_Set(&stLogDevice, 0, sizeof(MCI_SYSINFO_LOGDEVICE)); + + acBuf[0] = '\0'; + stMCISysInfo.pszReturn = acBuf; + stMCISysInfo.ulRetSize = sizeof(acBuf); + stMCISysInfo.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX; + ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_QUANTITY, &stMCISysInfo, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) return ulRC; + + ulDevicesNum = strtoul(stMCISysInfo.pszReturn, NULL, 10); + + for (ulNumber = 1; ulNumber <= ulDevicesNum; ulNumber++) { + /* Get device install name. */ + stSysInfoParams.ulNumber = ulNumber; + stSysInfoParams.pszReturn = acBuf; + stSysInfoParams.ulRetSize = sizeof(acBuf); + stSysInfoParams.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX; + ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_INSTALLNAME, &stSysInfoParams, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + Logger_SimpleWarn(LOUSHORT(ulRC), "Querying device type failed"); + continue; + } + + /* Get textual product description. */ + stSysInfoParams.ulItem = MCI_SYSINFO_QUERY_DRIVER; + stSysInfoParams.pSysInfoParm = &stLogDevice; + Mem_Copy(stLogDevice.szInstallName, stSysInfoParams.pszReturn, MAX_DEVICE_NAME); + ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_ITEM, &stSysInfoParams, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + Logger_SimpleWarn(LOUSHORT(ulRC), "Querying device info failed"); + continue; + } + + ulRC = DosCreateEventSem(NULL, &devicecontext.hevBuf, DCE_AUTORESET, TRUE); + if (ulRC != NO_ERROR) { + Logger_SimpleWarn(ulRC, "Creating semaphore failed"); + continue; + } + + /* Open audio device */ + stMCIAmpOpen.usDeviceID = 0; + stMCIAmpOpen.pszDeviceType = (PSZ)MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, 0); + ulRC = mciSendCommand(0, MCI_OPEN, + MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE, + &stMCIAmpOpen, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + devicecontext.usDeviceId = (USHORT)~0; + Logger_SimpleWarn(LOUSHORT(ulRC), "Open audio device failed"); + return false; + } + devicecontext.usDeviceId = stMCIAmpOpen.usDeviceID; + + Mem_Set(&stMCIGenericParms, 0, sizeof(stMCIGenericParms)); + ulRC = mciSendCommand(stMCIAmpOpen.usDeviceID, MCI_ACQUIREDEVICE, + MCI_WAIT,&stMCIGenericParms,0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + devicecontext.usDeviceId = (USHORT)~0; + Logger_SimpleWarn(LOUSHORT(ulRC), "Acquiring audio device failed"); + return false; + } + + /* Setup mixer */ + devicecontext.stMCIMixSetup.ulFormatTag = MCI_WAVE_FORMAT_PCM; + devicecontext.stMCIMixSetup.ulBitsPerSample = 16; + devicecontext.stMCIMixSetup.ulSamplesPerSec = 48000; + devicecontext.stMCIMixSetup.ulChannels = 2; + devicecontext.stMCIMixSetup.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO; + devicecontext.stMCIMixSetup.ulFormatMode = MCI_PLAY; + devicecontext.stMCIMixSetup.pmixEvent = cbAudioWriteEvent; + ulRC = mciSendCommand(devicecontext.usDeviceId, MCI_MIXSETUP, + MCI_WAIT | MCI_MIXSETUP_INIT, &devicecontext.stMCIMixSetup, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS && devicecontext.stMCIMixSetup.ulSamplesPerSec > 44100) { + devicecontext.stMCIMixSetup.ulSamplesPerSec = 44100; + ulRC = mciSendCommand(devicecontext.usDeviceId, MCI_MIXSETUP, + MCI_WAIT | MCI_MIXSETUP_INIT, &devicecontext.stMCIMixSetup, 0); + } + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + devicecontext.stMCIMixSetup.ulBitsPerSample = 0; + Logger_SimpleWarn(LOUSHORT(ulRC), "Setting up mixer failed"); + continue; + } + + /* Allocate memory buffers */ + stMCIBuffer.ulBufferSize = SIZE_BUFFERS; + stMCIBuffer.ulNumBuffers = NUM_BUFFERS; + stMCIBuffer.pBufList = devicecontext.aMixBuffers; + ulRC = mciSendCommand(devicecontext.usDeviceId, MCI_BUFFER, + MCI_WAIT | MCI_ALLOCATE_MEMORY, &stMCIBuffer, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + printf("buffer fail %d %x\n", LOUSHORT(ulRC),LOUSHORT(ulRC)); + Logger_SimpleWarn(LOUSHORT(ulRC), "Failed to allocate device buffers"); + continue; + } + devicecontext.cMixBuffers = stMCIBuffer.ulNumBuffers; + + /* Fill all device buffers with data */ + for (ulNumber = 0; ulNumber < stMCIBuffer.ulNumBuffers; ulNumber++) { + devicecontext.aMixBuffers[ulNumber].ulFlags = 0; + devicecontext.aMixBuffers[ulNumber].ulBufferLength = stMCIBuffer.ulBufferSize; + //devicecontext.aMixBuffers[ulNumber].ulUserParm = (ULONG)_this; + + Mem_Set(((PMCI_MIX_BUFFER)stMCIBuffer.pBufList)[ulNumber].pBuffer, + 0, stMCIBuffer.ulBufferSize); + } + devicecontext.pFillBuffer = devicecontext.aMixBuffers; + devicecontext.pDrainBuffer = devicecontext.aMixBuffers; + + msp.ulLevel = 100; + msp.ulAudio = MCI_SET_AUDIO_ALL; + mciSendCommand(devicecontext.usDeviceId, MCI_SET, + MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME, + (PVOID) &msp, 0); + + return true; + } + + Logger_SimpleWarn(ERROR_BASE, "No audiodevice"); + return false; +} + +void AudioBackend_Free(void) { + MCI_GENERIC_PARMS stMCIGenericParms; + ULONG ulRC; + + devicecontext.ulState = 2; + + /* Close up audio */ + if (devicecontext.usDeviceId != (USHORT)~0) { /* Device is open. */ + Mem_Set(&stMCIGenericParms, 0, sizeof(MCI_GENERIC_PARMS)); + + ulRC = mciSendCommand(devicecontext.usDeviceId, MCI_STOP, + MCI_WAIT, &stMCIGenericParms, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + Logger_SimpleWarn(ulRC, "Stopping playback failed"); + } + + Mem_Set(&stMCIGenericParms, 0, sizeof(MCI_GENERIC_PARMS)); + ulRC = mciSendCommand(devicecontext.usDeviceId,MCI_RELEASEDEVICE, + MCI_WAIT, &stMCIGenericParms, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + Logger_SimpleWarn(ulRC, "Releasing audio device failed"); + } + + if (devicecontext.stMCIMixSetup.ulBitsPerSample != 0) { + /* Mixer was initialized. */ + ulRC = mciSendCommand(devicecontext.usDeviceId, MCI_MIXSETUP, + MCI_WAIT | MCI_MIXSETUP_DEINIT, &devicecontext.stMCIMixSetup, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + Logger_SimpleWarn(ulRC, "Closing mixer failed"); + } + } + + if (devicecontext.cMixBuffers != 0) { /* Buffers was allocated. */ + MCI_BUFFER_PARMS stMCIBuffer; + + stMCIBuffer.ulBufferSize = devicecontext.aMixBuffers[0].ulBufferLength; + stMCIBuffer.ulNumBuffers = devicecontext.cMixBuffers; + stMCIBuffer.pBufList = devicecontext.aMixBuffers; + + ulRC = mciSendCommand(devicecontext.usDeviceId, MCI_BUFFER, + MCI_WAIT | MCI_DEALLOCATE_MEMORY, &stMCIBuffer, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + Logger_SimpleWarn(ulRC, "Deallocating buffers failed"); + } + } + ulRC = mciSendCommand(devicecontext.usDeviceId, MCI_CLOSE, MCI_WAIT, + &stMCIGenericParms, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + Logger_SimpleWarn(ulRC, "Closing audio device failed"); + } + } + + if (devicecontext.hevBuf != NULLHANDLE) + DosCloseEventSem(devicecontext.hevBuf); + + Mem_Set(&devicecontext, 0, sizeof(DeviceContext)); + devicecontext.usDeviceId = (USHORT)~0; + devicecontext.initRun = false; +} + +void AudioBackend_Tick(void) { } + +cc_result Audio_Init(struct AudioContext* ctx, int buffers) { + + printf("audio_init %p\n", ctx); + return 0; +} + +void Audio_Close(struct AudioContext* ctx) { + + printf("Audio_Close %p\n", ctx); +} + +cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate, int playbackRate) { + ULONG ulRC; + MCI_BUFFER_PARMS stMCIBuffer; + int newsamplerate = Audio_AdjustSampleRate(sampleRate, playbackRate); + + printf("Audio_SetFormat %d %d %d %d\n",channels,sampleRate,playbackRate, newsamplerate); + // Checking whether to change anything at all. + if (devicecontext.stMCIMixSetup.ulSamplesPerSec == newsamplerate && + devicecontext.stMCIMixSetup.ulChannels == channels) return 0; + + // Deinit mixer and buffers first + if (devicecontext.stMCIMixSetup.ulBitsPerSample != 0) { + /* Mixer was initialized. */ + ulRC = mciSendCommand(devicecontext.usDeviceId, MCI_MIXSETUP, + MCI_WAIT | MCI_MIXSETUP_DEINIT, &devicecontext.stMCIMixSetup, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + return ulRC; + } + } + + // Then set the new format. + Mem_Set(&devicecontext.stMCIMixSetup, 0, sizeof(MCI_MIXSETUP_PARMS)); + devicecontext.stMCIMixSetup.ulSamplesPerSec = newsamplerate; + devicecontext.stMCIMixSetup.ulChannels = channels; + devicecontext.stMCIMixSetup.ulFormatTag = MCI_WAVE_FORMAT_PCM; + devicecontext.stMCIMixSetup.ulBitsPerSample = 16; + devicecontext.stMCIMixSetup.ulSamplesPerSec = newsamplerate; + devicecontext.stMCIMixSetup.ulChannels = channels; + devicecontext.stMCIMixSetup.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO; + devicecontext.stMCIMixSetup.ulFormatMode = MCI_PLAY; + devicecontext.stMCIMixSetup.pmixEvent = cbAudioWriteEvent; + ulRC = mciSendCommand(devicecontext.usDeviceId, MCI_MIXSETUP, + MCI_WAIT | MCI_MIXSETUP_INIT, &devicecontext.stMCIMixSetup, 0); + if (LOUSHORT(ulRC) != MCIERR_SUCCESS) { + devicecontext.stMCIMixSetup.ulBitsPerSample = 0; + printf("setup mixer %u\n", LOUSHORT(ulRC)); + return ulRC; + } + printf("set format %p\n", ctx); + return 0; +} + +void Audio_SetVolume(struct AudioContext* ctx, int volume) { + ctx->volume = volume; +printf("Audio_SetVolume %p\n",ctx); +} + +cc_result Audio_QueueChunk(struct AudioContext* ctx, void* chunk, cc_uint32 size) { +printf("Audio_QueueChunk %p\n",ctx); + return 0; +} + +cc_result Audio_Play(struct AudioContext* ctx) { +printf("Audio_Play%p\n", ctx); + return 0; +} + +cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) { +printf("Audio_Poll %p\n",ctx); + return 0; +} + +static cc_bool Audio_FastPlay(struct AudioContext* ctx, struct AudioData* data) { +printf("Audio_FastPlay %p\n",ctx); + return false; +} + +cc_bool Audio_DescribeError(cc_result res, cc_string* dst) { + CHAR buffer[128]; + if (mciGetErrorString(res, buffer, 128) == MCIERR_SUCCESS) { + String_DecodeCP1252(dst, buffer, strlen(buffer)); + } + else + // TODO Query more error messages. + *dst = String_FromReadonly("Unknown Error"); + return true; +} + +cc_result Audio_AllocChunks(cc_uint32 size, void** chunks, int numChunks) { + return AudioBase_AllocChunks(size, chunks, numChunks); +} + void Audio_FreeChunks(void** chunks, int numChunks) { AudioBase_FreeChunks(chunks, numChunks); } diff --git a/src/Window_OS2.c b/src/Window_OS2.c new file mode 100644 index 000000000..1e4ff465d --- /dev/null +++ b/src/Window_OS2.c @@ -0,0 +1,396 @@ +#include "Core.h" +#if defined CC_BUILD_OS2 && !defined CC_BUILD_SDL2 +#include "_WindowBase.h" +#include "String.h" +#include "Funcs.h" +#include "Bitmap.h" +#include "Options.h" +#include "Errors.h" + +#define INCL_DOSPROCESS +#define INCL_DOSMEMMGR +#define INCL_DOSERRORS +#define INCL_PM +#define INCL_MMIOOS2 +#include +#include +#include +#include +#include + +#define CC_WIN_STYLE WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN +#define CC_WIN_CLASSNAME "ClassiCube_Window" +#define Rect_Width(rect) (rect.xRight - rect.xLeft) +#define Rect_Height(rect) (rect.yBottom - rect.yTop) + +static HAB habAnchor; +static HMQ msgQueue; +static HWND hwndFrame; +static HWND hwndClient; +static HDIVE hDive = NULLHANDLE; +static ULONG bufNum = 0; +static PBYTE imageBuffer = NULL; + +static HDC win_DC; +static cc_bool suppress_resize; +static int win_totalWidth, win_totalHeight; /* Size of window including titlebar and borders */ +static cc_bool grabCursor; +static int windowX, windowY; + +typedef struct _WINDATA { + HWND hwndFrame; + HWND hwnd; + PFNWP fnUserWndProc; + PFNWP fnWndFrameProc; +} WINDATA; + +static const cc_uint8 key_map[14 * 16] = { + 0, 0, 0, 0, 0, 0, 0, 0, CCKEY_BACKSPACE, CCKEY_TAB, 0, 0, 0, CCKEY_ENTER, 0, 0, + 0, 0, 0, CCKEY_PAUSE, CCKEY_CAPSLOCK, 0, 0, 0, 0, 0, 0, CCKEY_ESCAPE, 0, 0, 0, 0, + CCKEY_SPACE, CCKEY_PAGEUP, CCKEY_PAGEDOWN, CCKEY_END, CCKEY_HOME, CCKEY_LEFT, CCKEY_UP, CCKEY_RIGHT, CCKEY_DOWN, 0, CCKEY_PRINTSCREEN, 0, CCKEY_PRINTSCREEN, CCKEY_INSERT, CCKEY_DELETE, 0, + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0, + 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', CCKEY_LWIN, CCKEY_RWIN, CCKEY_MENU, 0, 0, + CCKEY_KP0, CCKEY_KP1, CCKEY_KP2, CCKEY_KP3, CCKEY_KP4, CCKEY_KP5, CCKEY_KP6, CCKEY_KP7, CCKEY_KP8, CCKEY_KP9, CCKEY_KP_MULTIPLY, CCKEY_KP_PLUS, 0, CCKEY_KP_MINUS, CCKEY_KP_DECIMAL, CCKEY_KP_DIVIDE, + CCKEY_F1, CCKEY_F2, CCKEY_F3, CCKEY_F4, CCKEY_F5, CCKEY_F6, CCKEY_F7, CCKEY_F8, CCKEY_F9, CCKEY_F10, CCKEY_F11, CCKEY_F12, CCKEY_F13, CCKEY_F14, CCKEY_F15, CCKEY_F16, + CCKEY_F17, CCKEY_F18, CCKEY_F19, CCKEY_F20, CCKEY_F21, CCKEY_F22, CCKEY_F23, CCKEY_F24, 0, 0, 0, 0, 0, 0, 0, 0, + CCKEY_NUMLOCK, CCKEY_SCROLLLOCK, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + CCKEY_LSHIFT, CCKEY_RSHIFT, CCKEY_LCTRL, CCKEY_RCTRL, CCKEY_LALT, CCKEY_RALT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CCKEY_SEMICOLON, CCKEY_EQUALS, CCKEY_COMMA, CCKEY_MINUS, CCKEY_PERIOD, CCKEY_SLASH, + CCKEY_TILDE, 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, CCKEY_LBRACKET, CCKEY_BACKSLASH, CCKEY_RBRACKET, CCKEY_QUOTE, 0, +}; + +static int MapNativeKey(MPARAM mp1, MPARAM mp2) { + USHORT flags = SHORT1FROMMP(mp1); + USHORT scanCode = CHAR4FROMMP(mp1); + USHORT key = SHORT2FROMMP(mp2); + + if (flags & KC_VIRTUALKEY) + { + switch (key) + { + case VK_CTRL: + return scanCode == 0x1D ? CCKEY_LCTRL : CCKEY_RCTRL; + case VK_ALT: + return scanCode == 0x38 ? CCKEY_LALT : CCKEY_RALT; + case VK_ENTER: + return scanCode == 0x1C ? CCKEY_ENTER : CCKEY_KP_ENTER; + default: + return key < Array_Elems(key_map) ? key_map[key] : 0; + } + } + return 0; +} + +// Window procedure +MRESULT EXPENTRY ClientWndProc(HWND hwnd, ULONG message, MPARAM mp1, MPARAM mp2) { +//printf("m %lu\n", message); + switch(message) { + case WM_CLOSE: + if (hwnd == hwndClient) + WinPostMsg(hwnd, WM_QUIT, 0L, 0L); + break; + + case WM_QUIT: + + default: + return WinDefWindowProc(hwnd, message, mp1, mp2); + } + return FALSE; +} + +void DiveFreeBuffer(void) { + ULONG rc; + + if (bufNum != 0) { + rc = DiveFreeImageBuffer(hDive, bufNum); + if (rc != DIVE_SUCCESS) { + // TODO Debug messages + } + bufNum = 0; + + if (imageBuffer != NULL) { + rc = DosFreeMem(imageBuffer); + if (rc != NO_ERROR) { + // TODO Debug messages + } + imageBuffer = NULL; + } + } +} + + +/*########################################################################################################################* +*--------------------------------------------------Public implementation--------------------------------------------------* +*#########################################################################################################################*/ +void Window_Init(void) { + ULONG rc; + PPIB pib; + DIVE_CAPS caps = {0}; + FOURCC fccFormats[100] = {0}; + +printf("Window_Init\n"); + /* Change process type code for use Win* API from VIO session */ + DosGetInfoBlocks(NULL, &pib); + if (pib->pib_ultype == 2 || pib->pib_ultype == 0) { + /* VIO windowable or fullscreen protect-mode session */ + pib->pib_ultype = 3; /* Presentation Manager protect-mode session */ + } + + habAnchor = WinInitialize(0); + if (habAnchor == NULLHANDLE) { + Logger_Abort2(LOUSHORT(WinGetLastError(0)), "Initialization failed"); + } + msgQueue = WinCreateMsgQueue(habAnchor, 0); + if (msgQueue == NULLHANDLE) { + Logger_Abort2(LOUSHORT(WinGetLastError(habAnchor)), "Window queue creation failed"); + } + + // Init Dive + caps.pFormatData = fccFormats; + caps.ulFormatLength = 120; + caps.ulStructLen = sizeof(DIVE_CAPS); + if (rc = DiveQueryCaps(&caps, DIVE_BUFFER_SCREEN)) { + Logger_Abort2(rc, "DIVE: Could get capabilities."); + } +printf("depth %d\n", caps.ulDepth); + rc = DiveOpen(&hDive, FALSE, NULL); + if (rc != DIVE_SUCCESS) { + Logger_Abort2(rc, "DIVE: Display engine instance open failed"); + } +} + +void Window_Create(int width, int height) { + ULONG ulFlags = FCF_TITLEBAR | FCF_SYSMENU | FCF_SHELLPOSITION | FCF_TASKLIST + | FCF_MINBUTTON | FCF_MAXBUTTON | FCF_SIZEBORDER | FCF_ICON; + + if (!WinRegisterClass(habAnchor, CC_WIN_CLASSNAME, ClientWndProc, + CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT, 0)) { + Logger_Abort2(LOUSHORT(WinGetLastError(habAnchor)), "Window class registration failed"); + } + hwndFrame = WinCreateStdWindow(HWND_DESKTOP, WS_VISIBLE, &ulFlags, + CC_WIN_CLASSNAME, "ClassiCube", 0L, NULLHANDLE, 0, &hwndClient); + if (hwndFrame == NULLHANDLE) { + Logger_Abort2(LOUSHORT(WinGetLastError(habAnchor)), "Failed to create window"); + } + Window_SetSize(width, height); + Window_Main.Exists = true; + Window_Main.Handle = (HWND)hwndFrame; +} + +void Window_Create2D(int width, int height) { + printf("Window_Create2D\n"); + Window_Create(width, height); +} + +void Window_Create3D(int width, int height) { + Window_Create(width, height); +} + +void Window_Free(void) { + DiveFreeBuffer(); + if (hDive != NULLHANDLE) DiveClose(hDive); +} + +void Window_ProcessEvents(double delta) { + QMSG msg; + HWND hwndFocused; + + if (WinPeekMsg(habAnchor, &msg, NULLHANDLE, 0, 0, PM_NOREMOVE)) { + WinGetMsg(habAnchor, &msg, NULLHANDLE, 0, 0); + WinDispatchMsg(habAnchor, &msg); + } +} + +void Window_SetTitle(const cc_string* title) { + WinSetWindowText(hwndFrame, title->buffer); +} + +void Clipboard_GetText(cc_string* value) { + PSZ data; + + if (WinOpenClipbrd(habAnchor)) { + data = (PSZ) WinQueryClipbrdData(habAnchor, CF_TEXT); + if (data) { + strcpy(value->buffer, data); + value->length = strlen(data); + } + WinCloseClipbrd(habAnchor); + } +} + +void Clipboard_SetText(const cc_string* value) { + + if (WinOpenClipbrd(habAnchor)) { + WinEmptyClipbrd(habAnchor); + WinSetClipbrdData(habAnchor, (ULONG) value->buffer, CF_TEXT, CFI_POINTER); + WinCloseClipbrd(habAnchor); + } +} + +void Window_Show(void) { + WinShowWindow(hwndFrame, TRUE); + WinSetFocus(HWND_DESKTOP, hwndFrame); +} + +void Window_SetSize(int width, int height) { + WinSetWindowPos(hwndFrame, HWND_TOP, 0, 0, width, height, SWP_SIZE); +} + +void Cursor_SetPosition(int x, int y) { + WinSetWindowPos(hwndFrame, HWND_TOP, x, y, 0, 0, SWP_MOVE); +} + +void Window_RequestClose(void) { + WinPostMsg(hwndFrame, WM_CLOSE, 0, 0); +} + +int Window_GetWindowState(void) { + ULONG style = WinQueryWindowULong(hwndFrame, QWL_STYLE); + if (style & WS_MINIMIZED) return WINDOW_STATE_MINIMISED; + if (style & WS_MAXIMIZED) return WINDOW_STATE_FULLSCREEN; + return WINDOW_STATE_NORMAL; +} + +void Window_AllocFramebuffer(struct Bitmap* bmp) { + ULONG rc; + ULONG scanLineSize = bmp->width * (32 >> 3); + + /* Destroy previous buffer. */ + DiveFreeBuffer(); + + if (bmp->width == 0 || bmp->height == 0) return; + + /* Bytes per line. */ + scanLineSize = (scanLineSize + 3) & ~3; /* 4-byte aligning */ + + rc = DosAllocMem((PPVOID)&imageBuffer, + (bmp->height * scanLineSize) + sizeof(ULONG), + PAG_COMMIT | PAG_READ | PAG_WRITE); + if (rc != NO_ERROR) { + // TODO Debug messages + return; + } + + rc = DiveAllocImageBuffer(hDive, &bufNum, + mmioStringToFOURCC("RGB4", MMIO_TOUPPER), bmp->width, bmp->height, + scanLineSize, imageBuffer); + if (rc != DIVE_SUCCESS) { +printf("DiveAllocImageBuffer(), rc = 0x%lX", rc ); + DosFreeMem(imageBuffer); + imageBuffer = NULL; + bufNum = 0; + return; + } + + /*debug(SDL_LOG_CATEGORY_VIDEO, "buffer: 0x%p, DIVE buffer number: %lu", + imageBuffer, bufNum );*/ + + bmp->scan0 = (unsigned int*)imageBuffer; + +printf("Window_AllocFrameBuffer\n"); +} + +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { +printf("Window_DrawFrameBuffer\n"); +DiveBlitImage ( hDive, + bufNum, + DIVE_BUFFER_SCREEN ); + +} + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + DiveFreeBuffer(); + printf("Window_FreeFrameBuffer\n"); +} + + + +cc_result Window_EnterFullscreen(void) { +printf("Window_EnterFullscreen\n"); +} + +cc_result Window_ExitFullscreen(void) { +printf("Window_ExitFillscreen\n"); +} + + +void Cursor_GetRawPos(int *x, int *y) { +printf("Cursor_GetRawPos\n"); +} + +void Cursor_DoSetVisible(cc_bool visible) { printf("Cursor_DoSetVisible\n");} + +int Window_IsObscured(void) { return 0; } + + +void ShowDialogCore(const char *title, const char *name) { + printf("ShowDialogcore\n"); + WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, name, title, 0, MB_OK); +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { +#if defined CC_BUILD_OS2 + FILEDLG fileDialog; + HWND hDialog; + + memset(&fileDialog, 0, sizeof(FILEDLG)); + fileDialog.cbSize = sizeof(FILEDLG); + fileDialog.fl = FDS_HELPBUTTON | FDS_CENTER | FDS_PRELOAD_VOLINFO | FDS_OPEN_DIALOG; + fileDialog.pszTitle = (PSZ)args->description; + fileDialog.pszOKButton = NULL; + fileDialog.pfnDlgProc = WinDefFileDlgProc; + + Mem_Copy(fileDialog.szFullFile, *args->filters, CCHMAXPATH); + hDialog = WinFileDlg(HWND_DESKTOP, 0, &fileDialog); + if (fileDialog.lReturn == DID_OK) { + cc_string temp = String_FromRaw(fileDialog.szFullFile, CCHMAXPATH); + args->Callback(&temp); + } + + return 0; +#else + return ERR_NOT_SUPPORTED; +#endif +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { +#if defined CC_BUILD_OS2 + FILEDLG fileDialog; + HWND hDialog; + + memset(&fileDialog, 0, sizeof(FILEDLG)); + fileDialog.cbSize = sizeof(FILEDLG); + fileDialog.fl = FDS_HELPBUTTON | FDS_CENTER | FDS_PRELOAD_VOLINFO | FDS_SAVEAS_DIALOG; + fileDialog.pszTitle = (PSZ)args->titles; + fileDialog.pszOKButton = NULL; + fileDialog.pfnDlgProc = WinDefFileDlgProc; + + Mem_Copy(fileDialog.szFullFile, *args->filters, CCHMAXPATH); + hDialog = WinFileDlg(HWND_DESKTOP, 0, &fileDialog); + if (fileDialog.lReturn == DID_OK) { + cc_string temp = String_FromRaw(fileDialog.szFullFile, CCHMAXPATH); + args->Callback(&temp); + } + + return 0; +#else + return ERR_NOT_SUPPORTED; +#endif +} + +void Window_OpenKeyboard(struct OpenKeyboardArgs* args) { } +void Window_SetKeyboardText(const cc_string* text) { } +void Window_CloseKeyboard(void) { } + +void Window_LockLandscapeOrientation(cc_bool lock) { } + +void Window_EnableRawMouse(void) { } + +void Window_UpdateRawMouse(void) { } + +void Window_DisableRawMouse(void) { } + + +#endif