mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 11:06:06 -04:00
OS/2 specific branch created. Work on audio and window system done.
This commit is contained in:
parent
424ad6808e
commit
f1494776e4
@ -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
396
src/Window_OS2.c
Normal 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
|
Loading…
x
Reference in New Issue
Block a user