OS/2 specific branch created. Work on audio and window system done.

This commit is contained in:
Jochen Sch„fer 2024-04-15 12:13:11 +02:00
parent 424ad6808e
commit f1494776e4
2 changed files with 770 additions and 0 deletions

View File

@ -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 <os2.h>
#include <os2me.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);
}

396
src/Window_OS2.c Normal file
View File

@ -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 <os2.h>
#include <os2me.h>
#include <dive.h>
#include <string.h>
#include <stdio.h>
#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