Skip to content

Commit d1c9899

Browse files
committed
Merge branch 'master' of https://github.com/XProger/OpenLara
2 parents 7b77d03 + 93ce97e commit d1c9899

File tree

3 files changed

+151
-36
lines changed

3 files changed

+151
-36
lines changed

src/input.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ namespace Input {
128128
case jkRT : joy[index].RT = pos.x; break;
129129
default : return;
130130
}
131-
setJoyDown(index, key, pos.x > 0.0f); // gamepad LT, RT auto-down state
131+
setJoyDown(index, key, pos.x > EPS); // gamepad LT, RT auto-down state
132132
}
133133

134134
void setJoyVibration(int playerIndex, float L, float R) {

src/platform/osx/OpenLara.xcodeproj/project.pbxproj

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
523F97E41DDF7AA5006FE2FC /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523F97E31DDF7AA5006FE2FC /* Cocoa.framework */; };
11-
523F97E61DDF926E006FE2FC /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523F97E51DDF926E006FE2FC /* QuartzCore.framework */; };
11+
9938F1A421E830250056E172 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9938F1A021E81EFE0056E172 /* IOKit.framework */; };
1212
99713CC9204CAD9900006FAC /* tinflate.c in Sources */ = {isa = PBXBuildFile; fileRef = 99713CC8204CAD9900006FAC /* tinflate.c */; };
1313
99BF38CD21E7176900D90A38 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 99BF38CC21E7176900D90A38 /* main.mm */; };
1414
99BF38D221E7202500D90A38 /* audio in Resources */ = {isa = PBXBuildFile; fileRef = 99BF38CE21E7202500D90A38 /* audio */; };
@@ -23,7 +23,7 @@
2323

2424
/* Begin PBXFileReference section */
2525
523F97E31DDF7AA5006FE2FC /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
26-
523F97E51DDF926E006FE2FC /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
26+
9938F1A021E81EFE0056E172 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
2727
995C97EF1E91A857003825B2 /* shaders */ = {isa = PBXFileReference; lastKnownFileType = folder; name = shaders; path = ../../shaders; sourceTree = "<group>"; };
2828
99713CAE204CA3DA00006FAC /* animation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = animation.h; path = ../../animation.h; sourceTree = "<group>"; };
2929
99713CAF204CA3DA00006FAC /* cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cache.h; path = ../../cache.h; sourceTree = "<group>"; };
@@ -60,12 +60,8 @@
6060
99BFB6A81DCA87BF00E2E997 /* stb_vorbis.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = stb_vorbis.c; path = ../../libs/stb_vorbis/stb_vorbis.c; sourceTree = "<group>"; };
6161
99BFB6AA1DCA87C500E2E997 /* minimp3.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = minimp3.cpp; path = ../../libs/minimp3/minimp3.cpp; sourceTree = "<group>"; };
6262
99C4C0931796A96F0032DE85 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
63-
99C4C0951796A9730032DE85 /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = System/Library/Frameworks/AGL.framework; sourceTree = SDKROOT; };
6463
99C4C09B1796AACF0032DE85 /* OpenLara.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OpenLara.app; sourceTree = BUILT_PRODUCTS_DIR; };
6564
99C4C0A41796AACF0032DE85 /* OpenLara-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "OpenLara-Info.plist"; sourceTree = "<group>"; };
66-
99C4C0B81796AB7B0032DE85 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
67-
99DF7BBF1DCBA2BF00C40D0A /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
68-
99DF7BC11DCBA2D100C40D0A /* CoreAudioKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudioKit.framework; path = System/Library/Frameworks/CoreAudioKit.framework; sourceTree = SDKROOT; };
6965
99DF7BC31DCBA30B00C40D0A /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
7066
/* End PBXFileReference section */
7167

@@ -74,7 +70,7 @@
7470
isa = PBXFrameworksBuildPhase;
7571
buildActionMask = 2147483647;
7672
files = (
77-
523F97E61DDF926E006FE2FC /* QuartzCore.framework in Frameworks */,
73+
9938F1A421E830250056E172 /* IOKit.framework in Frameworks */,
7874
523F97E41DDF7AA5006FE2FC /* Cocoa.framework in Frameworks */,
7975
99DF7BC41DCBA30B00C40D0A /* AudioToolbox.framework in Frameworks */,
8076
99C4C0BA1796AB810032DE85 /* OpenGL.framework in Frameworks */,
@@ -139,14 +135,10 @@
139135
99C4C0821796A8230032DE85 /* Frameworks */ = {
140136
isa = PBXGroup;
141137
children = (
142-
523F97E51DDF926E006FE2FC /* QuartzCore.framework */,
138+
9938F1A021E81EFE0056E172 /* IOKit.framework */,
143139
523F97E31DDF7AA5006FE2FC /* Cocoa.framework */,
144140
99DF7BC31DCBA30B00C40D0A /* AudioToolbox.framework */,
145-
99DF7BC11DCBA2D100C40D0A /* CoreAudioKit.framework */,
146-
99DF7BBF1DCBA2BF00C40D0A /* CoreAudio.framework */,
147-
99C4C0B81796AB7B0032DE85 /* Carbon.framework */,
148141
99C4C0931796A96F0032DE85 /* OpenGL.framework */,
149-
99C4C0951796A9730032DE85 /* AGL.framework */,
150142
);
151143
name = Frameworks;
152144
sourceTree = "<group>";

src/platform/osx/main.mm

Lines changed: 146 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,36 @@
11
#include <Cocoa/Cocoa.h>
22
#include <mach/mach.h>
33
#include <mach/mach_time.h>
4+
#include <IOKit/hid/IOHidLib.h>
45

56
#include "game.h"
67

8+
// timing
9+
int osGetTime() {
10+
static mach_timebase_info_data_t timebaseInfo;
11+
if (timebaseInfo.denom == 0) {
12+
mach_timebase_info(&timebaseInfo);
13+
}
14+
15+
uint64_t absolute = mach_absolute_time();
16+
uint64_t milliseconds = absolute * timebaseInfo.numer / (timebaseInfo.denom * 1000000ULL);
17+
return int(milliseconds);
18+
}
19+
720
// sound
821
#define SND_SIZE 2352
922

1023
static AudioQueueRef audioQueue;
1124

12-
void soundFill(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
25+
void sndFill(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
1326
void* frames = inBuffer->mAudioData;
1427
UInt32 count = inBuffer->mAudioDataBytesCapacity / 4;
1528
Sound::fill((Sound::Frame*)frames, count);
1629
inBuffer->mAudioDataByteSize = count * 4;
1730
AudioQueueEnqueueBuffer(audioQueue, inBuffer, 0, NULL);
1831
}
1932

20-
void soundInit() {
33+
void sndInit() {
2134
AudioStreamBasicDescription deviceFormat;
2235
deviceFormat.mSampleRate = 44100;
2336
deviceFormat.mFormatID = kAudioFormatLinearPCM;
@@ -29,12 +42,12 @@ void soundInit() {
2942
deviceFormat.mBitsPerChannel = 16;
3043
deviceFormat.mReserved = 0;
3144

32-
AudioQueueNewOutput(&deviceFormat, soundFill, NULL, NULL, NULL, 0, &audioQueue);
45+
AudioQueueNewOutput(&deviceFormat, sndFill, NULL, NULL, NULL, 0, &audioQueue);
3346

3447
for (int i = 0; i < 2; i++) {
3548
AudioQueueBufferRef mBuffer;
3649
AudioQueueAllocateBuffer(audioQueue, SND_SIZE, &mBuffer);
37-
soundFill(NULL, audioQueue, mBuffer);
50+
sndFill(NULL, audioQueue, mBuffer);
3851
}
3952
AudioQueueStart(audioQueue, NULL);
4053
}
@@ -51,7 +64,6 @@ InputKey keyToInputKey(int code) {
5164
for (int i = 0; i < sizeof(codes) / sizeof(codes[0]); i++)
5265
if (codes[i] == code) {
5366
return (InputKey)(ikLeft + i);
54-
LOG("%d\n", code);
5567
}
5668
return ikNone;
5769
}
@@ -65,24 +77,133 @@ InputKey mouseToInputKey(int btn) {
6577
return ikNone;
6678
}
6779

80+
IOHIDDeviceRef joyDevices[4] = { 0 };
81+
IOHIDManagerRef hidManager;
82+
83+
JoyKey joyButtonToKey(uint32_t button) {
84+
static const JoyKey keys[] = { jkA, jkB, jkX, jkY, jkLB, jkRB, jkLT, jkRT, jkStart, jkSelect, jkNone, jkUp, jkDown, jkLeft, jkRight };
85+
86+
if (button >= 0 || button < COUNT(keys))
87+
return keys[button];
88+
return jkNone;
89+
}
90+
6891
bool osJoyReady(int index) {
69-
return false;
92+
if (index < 0 || index >= COUNT(joyDevices))
93+
return false;
94+
return joyDevices[index] != NULL;
7095
}
7196

7297
void osJoyVibrate(int index, float L, float R) {
7398
// TODO
7499
}
75100

76-
// timing
77-
int osGetTime() {
78-
static mach_timebase_info_data_t timebaseInfo;
79-
if (timebaseInfo.denom == 0) {
80-
mach_timebase_info(&timebaseInfo);
101+
float joyAxisValue(IOHIDValueRef value) {
102+
IOHIDElementRef element = IOHIDValueGetElement(value);
103+
CFIndex val = IOHIDValueGetIntegerValue(value);
104+
CFIndex min = IOHIDElementGetLogicalMin(element);
105+
CFIndex max = IOHIDElementGetLogicalMax(element);
106+
107+
float v = float(val - min) / float(max - min);
108+
if (v < 0.2f) v = 0.0f; // check for deadzone
109+
return v * 2.0f - 1.0f;
110+
}
111+
112+
void hidValueCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value) {
113+
if (result != kIOReturnSuccess)
114+
return;
115+
116+
IOHIDElementRef element = IOHIDValueGetElement(value);
117+
IOHIDDeviceRef device = IOHIDElementGetDevice(element);
118+
119+
int joyIndex = -1;
120+
for (int i = 0; i < COUNT(joyDevices); i++) {
121+
if (joyDevices[i] == device) {
122+
joyIndex = i;
123+
break;
124+
}
81125
}
82126

83-
uint64_t absolute = mach_absolute_time();
84-
uint64_t milliseconds = absolute * timebaseInfo.numer / (timebaseInfo.denom * 1000000ULL);
85-
return int(milliseconds);
127+
if (joyIndex == -1) return;
128+
129+
// TODO: add mapping for most popular gamepads by kIOHIDVendorIDKey / kIOHIDProductIDKey
130+
switch (IOHIDElementGetUsagePage(element)) {
131+
case kHIDPage_GenericDesktop : {
132+
switch (IOHIDElementGetUsage(IOHIDValueGetElement(value))) {
133+
case kHIDUsage_GD_X :
134+
Input::setJoyPos(joyIndex, jkL, vec2(joyAxisValue(value), Input::joy[joyIndex].L.y));
135+
break;
136+
case kHIDUsage_GD_Y :
137+
Input::setJoyPos(joyIndex, jkL, vec2(Input::joy[joyIndex].L.x, joyAxisValue(value)));
138+
break;
139+
case kHIDUsage_GD_Rx :
140+
Input::setJoyPos(joyIndex, jkR, vec2(joyAxisValue(value), Input::joy[joyIndex].R.y));
141+
break;
142+
case kHIDUsage_GD_Ry :
143+
Input::setJoyPos(joyIndex, jkR, vec2(Input::joy[joyIndex].R.x, joyAxisValue(value)));
144+
break;
145+
case kHIDUsage_GD_Z :
146+
Input::setJoyPos(joyIndex, jkLT, vec2(joyAxisValue(value) * 0.5f + 0.5f, 0.0f));
147+
break;
148+
case kHIDUsage_GD_Rz :
149+
Input::setJoyPos(joyIndex, jkRT, vec2(joyAxisValue(value) * 0.5f + 0.5f, 0.0f));
150+
break;
151+
default : LOG("! joy: unknown joy 0x%x (%d)\n", IOHIDElementGetUsage(IOHIDValueGetElement(value)), (int)IOHIDValueGetIntegerValue(value));
152+
}
153+
break;
154+
}
155+
case kHIDPage_Button : {
156+
uint32_t button = IOHIDElementGetUsage(IOHIDValueGetElement(value)) - kHIDUsage_Button_1;
157+
bool down = IOHIDValueGetIntegerValue(value) != 0;
158+
JoyKey key = joyButtonToKey(button);
159+
Input::setJoyDown(joyIndex, key, down);
160+
if (key == jkNone) LOG("! joy: unknown button %d\n", button);
161+
break;
162+
}
163+
default : ;
164+
}
165+
}
166+
167+
void joyAdd(void* context, IOReturn, void*, IOHIDDeviceRef device) {
168+
for (int i = 0; i < COUNT(joyDevices); i++) {
169+
if (joyDevices[i] == NULL) {
170+
joyDevices[i] = device;
171+
break;
172+
}
173+
}
174+
}
175+
176+
void joyRemove(void* context, IOReturn, void*, IOHIDDeviceRef device) {
177+
for (int i = 0; i < COUNT(joyDevices); i++) {
178+
if (joyDevices[i] == device) {
179+
joyDevices[i] = NULL;
180+
break;
181+
}
182+
}
183+
}
184+
185+
void joyInit() {
186+
hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDManagerOptionNone);
187+
188+
NSDictionary *matchingGamepad = @{
189+
@(kIOHIDDeviceUsagePageKey): @(kHIDPage_GenericDesktop),
190+
@(kIOHIDDeviceUsageKey): @(kHIDUsage_GD_GamePad)
191+
};
192+
NSArray *matchDicts = @[ matchingGamepad ];
193+
194+
IOHIDManagerSetDeviceMatchingMultiple(hidManager, (__bridge CFArrayRef) matchDicts);
195+
IOHIDManagerRegisterDeviceMatchingCallback(hidManager, joyAdd, NULL);
196+
IOHIDManagerRegisterDeviceRemovalCallback(hidManager, joyRemove, NULL);
197+
IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
198+
IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone);
199+
IOHIDManagerRegisterInputValueCallback(hidManager, hidValueCallback, NULL);
200+
}
201+
202+
void joyFree() {
203+
IOHIDManagerUnscheduleFromRunLoop(hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
204+
IOHIDManagerRegisterDeviceMatchingCallback(hidManager, NULL, 0);
205+
IOHIDManagerRegisterDeviceRemovalCallback(hidManager, NULL, 0);
206+
IOHIDManagerClose(hidManager, kIOHIDOptionsTypeNone);
86207
}
87208

88209
@interface OpenLaraGLView : NSOpenGLView
@@ -216,10 +337,10 @@ int main() {
216337

217338
// init window
218339
NSRect rect = NSMakeRect(0, 0, 1280, 720);
219-
NSWindow *mainWindow = [[NSWindow alloc] initWithContentRect:rect styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask backing:NSBackingStoreBuffered defer:YES];
220-
mainWindow.title = @"OpenLara";
221-
mainWindow.acceptsMouseMovedEvents = YES;
222-
mainWindow.delegate = [[OpenLaraWindowDelegate alloc] init];
340+
NSWindow *window = [[NSWindow alloc] initWithContentRect:rect styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask backing:NSBackingStoreBuffered defer:YES];
341+
window.title = @"OpenLara";
342+
window.acceptsMouseMovedEvents = YES;
343+
window.delegate = [[OpenLaraWindowDelegate alloc] init];
223344

224345
// init OpenGL context
225346
NSOpenGLPixelFormatAttribute attribs[] = {
@@ -232,9 +353,9 @@ int main() {
232353
};
233354
NSOpenGLPixelFormat *format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
234355

235-
OpenLaraGLView *view = [[OpenLaraGLView alloc] initWithFrame:mainWindow.contentLayoutRect pixelFormat:format];
356+
OpenLaraGLView *view = [[OpenLaraGLView alloc] initWithFrame:window.contentLayoutRect pixelFormat:format];
236357
view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
237-
mainWindow.contentView = view;
358+
window.contentView = view;
238359
[view.openGLContext makeCurrentContext];
239360

240361
// get path to game content
@@ -244,17 +365,19 @@ int main() {
244365
strcat(contentDir, "/");
245366

246367
// show window
247-
[mainWindow center];
248-
[mainWindow makeKeyAndOrderFront:nil];
368+
[window center];
369+
[window makeKeyAndOrderFront:nil];
249370

250-
soundInit();
371+
joyInit();
372+
sndInit();
251373
Game::init();
252374

253375
if (!Core::isQuit) {
254376
[application run];
255377
}
256378

257379
Game::deinit();
380+
joyFree();
258381
// TODO: sndFree
259382

260383
return 0;

0 commit comments

Comments
 (0)