diff --git a/src/core.h b/src/core.h index dc545bdf..0683b31f 100644 --- a/src/core.h +++ b/src/core.h @@ -11,6 +11,12 @@ #include #include #include +#elif __APPLE__ + #include + #include + #include + #include + #include #elif __EMSCRIPTEN__ #define MOBILE 1 #include diff --git a/src/platform/osx/OpenLara.xcodeproj/project.pbxproj b/src/platform/osx/OpenLara.xcodeproj/project.pbxproj new file mode 100644 index 00000000..c9f67f27 --- /dev/null +++ b/src/platform/osx/OpenLara.xcodeproj/project.pbxproj @@ -0,0 +1,331 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 99BFB6A21DCA7F5300E2E997 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99BFB6A11DCA7F5300E2E997 /* main.cpp */; }; + 99BFB6A51DCA872D00E2E997 /* LEVEL2_DEMO.PHD in Resources */ = {isa = PBXBuildFile; fileRef = 99BFB6A31DCA872D00E2E997 /* LEVEL2_DEMO.PHD */; }; + 99BFB6A61DCA872D00E2E997 /* 05.ogg in Resources */ = {isa = PBXBuildFile; fileRef = 99BFB6A41DCA872D00E2E997 /* 05.ogg */; }; + 99BFB6A91DCA87BF00E2E997 /* stb_vorbis.c in Sources */ = {isa = PBXBuildFile; fileRef = 99BFB6A81DCA87BF00E2E997 /* stb_vorbis.c */; }; + 99BFB6AB1DCA87C500E2E997 /* minimp3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99BFB6AA1DCA87C500E2E997 /* minimp3.cpp */; }; + 99C4C0B71796AB730032DE85 /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 99C4C0951796A9730032DE85 /* AGL.framework */; }; + 99C4C0B91796AB7B0032DE85 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 99C4C0B81796AB7B0032DE85 /* Carbon.framework */; }; + 99C4C0BA1796AB810032DE85 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 99C4C0931796A96F0032DE85 /* OpenGL.framework */; }; + 99DF7BC41DCBA30B00C40D0A /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 99DF7BC31DCBA30B00C40D0A /* AudioToolbox.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 99BFB68D1DCA7F1700E2E997 /* lara.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lara.h; path = ../../lara.h; sourceTree = ""; }; + 99BFB68E1DCA7F1700E2E997 /* format.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = format.h; path = ../../format.h; sourceTree = ""; }; + 99BFB68F1DCA7F1700E2E997 /* level.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = level.h; path = ../../level.h; sourceTree = ""; }; + 99BFB6901DCA7F1700E2E997 /* mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mesh.h; path = ../../mesh.h; sourceTree = ""; }; + 99BFB6911DCA7F1700E2E997 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = debug.h; path = ../../debug.h; sourceTree = ""; }; + 99BFB6921DCA7F1700E2E997 /* controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = controller.h; path = ../../controller.h; sourceTree = ""; }; + 99BFB6931DCA7F1700E2E997 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utils.h; path = ../../utils.h; sourceTree = ""; }; + 99BFB6941DCA7F1700E2E997 /* sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sound.h; path = ../../sound.h; sourceTree = ""; }; + 99BFB6951DCA7F1700E2E997 /* camera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = camera.h; path = ../../camera.h; sourceTree = ""; }; + 99BFB6961DCA7F1700E2E997 /* core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = core.h; path = ../../core.h; sourceTree = ""; }; + 99BFB6971DCA7F1700E2E997 /* trigger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = trigger.h; path = ../../trigger.h; sourceTree = ""; }; + 99BFB6981DCA7F1700E2E997 /* shader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = shader.h; path = ../../shader.h; sourceTree = ""; }; + 99BFB6991DCA7F1700E2E997 /* shader.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = shader.glsl; path = ../../shader.glsl; sourceTree = ""; }; + 99BFB69A1DCA7F1700E2E997 /* input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = input.h; path = ../../input.h; sourceTree = ""; }; + 99BFB69B1DCA7F1700E2E997 /* enemy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = enemy.h; path = ../../enemy.h; sourceTree = ""; }; + 99BFB69C1DCA7F1700E2E997 /* game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = game.h; path = ../../game.h; sourceTree = ""; }; + 99BFB69D1DCA7F1700E2E997 /* texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = texture.h; path = ../../texture.h; sourceTree = ""; }; + 99BFB69E1DCA7F1700E2E997 /* libs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = libs; path = ../../libs; sourceTree = ""; }; + 99BFB6A11DCA7F5300E2E997 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 99BFB6A31DCA872D00E2E997 /* LEVEL2_DEMO.PHD */ = {isa = PBXFileReference; lastKnownFileType = file; name = LEVEL2_DEMO.PHD; path = ../../../bin/LEVEL2_DEMO.PHD; sourceTree = SOURCE_ROOT; }; + 99BFB6A41DCA872D00E2E997 /* 05.ogg */ = {isa = PBXFileReference; lastKnownFileType = file; name = 05.ogg; path = ../../../bin/05.ogg; sourceTree = SOURCE_ROOT; }; + 99BFB6A81DCA87BF00E2E997 /* stb_vorbis.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = stb_vorbis.c; path = ../../libs/stb_vorbis/stb_vorbis.c; sourceTree = ""; }; + 99BFB6AA1DCA87C500E2E997 /* minimp3.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = minimp3.cpp; path = ../../libs/minimp3/minimp3.cpp; sourceTree = ""; }; + 99C4C0931796A96F0032DE85 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; + 99C4C0951796A9730032DE85 /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = System/Library/Frameworks/AGL.framework; sourceTree = SDKROOT; }; + 99C4C09B1796AACF0032DE85 /* OpenLara.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OpenLara.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 99C4C0A41796AACF0032DE85 /* OpenLara-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "OpenLara-Info.plist"; sourceTree = ""; }; + 99C4C0B81796AB7B0032DE85 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; + 99DF7BBF1DCBA2BF00C40D0A /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; + 99DF7BC11DCBA2D100C40D0A /* CoreAudioKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudioKit.framework; path = System/Library/Frameworks/CoreAudioKit.framework; sourceTree = SDKROOT; }; + 99DF7BC31DCBA30B00C40D0A /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 99C4C0981796AACF0032DE85 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 99DF7BC41DCBA30B00C40D0A /* AudioToolbox.framework in Frameworks */, + 99C4C0BA1796AB810032DE85 /* OpenGL.framework in Frameworks */, + 99C4C0B91796AB7B0032DE85 /* Carbon.framework in Frameworks */, + 99C4C0B71796AB730032DE85 /* AGL.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 99C4C0771796A8230032DE85 = { + isa = PBXGroup; + children = ( + 99BFB6AA1DCA87C500E2E997 /* minimp3.cpp */, + 99BFB6A81DCA87BF00E2E997 /* stb_vorbis.c */, + 99BFB69E1DCA7F1700E2E997 /* libs */, + 99BFB6A11DCA7F5300E2E997 /* main.cpp */, + 99BFB68D1DCA7F1700E2E997 /* lara.h */, + 99BFB68E1DCA7F1700E2E997 /* format.h */, + 99BFB68F1DCA7F1700E2E997 /* level.h */, + 99BFB6901DCA7F1700E2E997 /* mesh.h */, + 99BFB6911DCA7F1700E2E997 /* debug.h */, + 99BFB6921DCA7F1700E2E997 /* controller.h */, + 99BFB6931DCA7F1700E2E997 /* utils.h */, + 99BFB6941DCA7F1700E2E997 /* sound.h */, + 99BFB6951DCA7F1700E2E997 /* camera.h */, + 99BFB6961DCA7F1700E2E997 /* core.h */, + 99BFB6971DCA7F1700E2E997 /* trigger.h */, + 99BFB6981DCA7F1700E2E997 /* shader.h */, + 99BFB6991DCA7F1700E2E997 /* shader.glsl */, + 99BFB69A1DCA7F1700E2E997 /* input.h */, + 99BFB69B1DCA7F1700E2E997 /* enemy.h */, + 99BFB69C1DCA7F1700E2E997 /* game.h */, + 99BFB69D1DCA7F1700E2E997 /* texture.h */, + 99C4C0A31796AACF0032DE85 /* Supporting Files */, + 99C4C0821796A8230032DE85 /* Frameworks */, + 99C4C0811796A8230032DE85 /* Products */, + ); + sourceTree = ""; + }; + 99C4C0811796A8230032DE85 /* Products */ = { + isa = PBXGroup; + children = ( + 99C4C09B1796AACF0032DE85 /* OpenLara.app */, + ); + name = Products; + sourceTree = ""; + }; + 99C4C0821796A8230032DE85 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 99DF7BC31DCBA30B00C40D0A /* AudioToolbox.framework */, + 99DF7BC11DCBA2D100C40D0A /* CoreAudioKit.framework */, + 99DF7BBF1DCBA2BF00C40D0A /* CoreAudio.framework */, + 99C4C0B81796AB7B0032DE85 /* Carbon.framework */, + 99C4C0931796A96F0032DE85 /* OpenGL.framework */, + 99C4C0951796A9730032DE85 /* AGL.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 99C4C0A31796AACF0032DE85 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 99BFB6A31DCA872D00E2E997 /* LEVEL2_DEMO.PHD */, + 99BFB6A41DCA872D00E2E997 /* 05.ogg */, + 99C4C0A41796AACF0032DE85 /* OpenLara-Info.plist */, + ); + name = "Supporting Files"; + path = OpenLara; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 99C4C09A1796AACF0032DE85 /* OpenLara */ = { + isa = PBXNativeTarget; + buildConfigurationList = 99C4C0B41796AAD00032DE85 /* Build configuration list for PBXNativeTarget "OpenLara" */; + buildPhases = ( + 99C4C0971796AACF0032DE85 /* Sources */, + 99C4C0981796AACF0032DE85 /* Frameworks */, + 99C4C0991796AACF0032DE85 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OpenLara; + productName = OpenLara; + productReference = 99C4C09B1796AACF0032DE85 /* OpenLara.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 99C4C0781796A8230032DE85 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0810; + ORGANIZATIONNAME = XProger; + }; + buildConfigurationList = 99C4C07B1796A8230032DE85 /* Build configuration list for PBXProject "OpenLara" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 99C4C0771796A8230032DE85; + productRefGroup = 99C4C0811796A8230032DE85 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 99C4C09A1796AACF0032DE85 /* OpenLara */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 99C4C0991796AACF0032DE85 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 99BFB6A61DCA872D00E2E997 /* 05.ogg in Resources */, + 99BFB6A51DCA872D00E2E997 /* LEVEL2_DEMO.PHD in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 99C4C0971796AACF0032DE85 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 99BFB6AB1DCA87C500E2E997 /* minimp3.cpp in Sources */, + 99BFB6A21DCA7F5300E2E997 /* main.cpp in Sources */, + 99BFB6A91DCA87BF00E2E997 /* stb_vorbis.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 99C4C08C1796A8230032DE85 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = c11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 99C4C08D1796A8230032DE85 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = c11; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; + SDKROOT = macosx; + }; + name = Release; + }; + 99C4C0B51796AAD00032DE85 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ""; + INFOPLIST_FILE = "OpenLara-Info.plist"; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_BUNDLE_IDENTIFIER = "com.xproger.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 99C4C0B61796AAD00032DE85 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + COMBINE_HIDPI_IMAGES = YES; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ""; + INFOPLIST_FILE = "OpenLara-Info.plist"; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_BUNDLE_IDENTIFIER = "com.xproger.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 99C4C07B1796A8230032DE85 /* Build configuration list for PBXProject "OpenLara" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 99C4C08C1796A8230032DE85 /* Debug */, + 99C4C08D1796A8230032DE85 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 99C4C0B41796AAD00032DE85 /* Build configuration list for PBXNativeTarget "OpenLara" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 99C4C0B51796AAD00032DE85 /* Debug */, + 99C4C0B61796AAD00032DE85 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 99C4C0781796A8230032DE85 /* Project object */; +} diff --git a/src/platform/osx/main.cpp b/src/platform/osx/main.cpp new file mode 100644 index 00000000..337b3b45 --- /dev/null +++ b/src/platform/osx/main.cpp @@ -0,0 +1,236 @@ +#include "game.h" +#include +#include + +bool isQuit = false; +WindowRef window; +AGLContext context; + +#define SND_SIZE 8192 // можно и 4096, что в 2 раза сократит latency, но в симуляторе будут слышны щелчки + +static AudioQueueRef audioQueue; + +void soundFill(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) { + void* frames = inBuffer->mAudioData; + UInt32 count = inBuffer->mAudioDataBytesCapacity / 4; + Sound::fill((Sound::Frame*)frames, count); + inBuffer->mAudioDataByteSize = count * 4; + AudioQueueEnqueueBuffer(audioQueue, inBuffer, 0, NULL); +} + +void soundInit() { + AudioStreamBasicDescription deviceFormat; + deviceFormat.mSampleRate = 44100; + deviceFormat.mFormatID = kAudioFormatLinearPCM; + deviceFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; + deviceFormat.mBytesPerPacket = 4; + deviceFormat.mFramesPerPacket = 1; + deviceFormat.mBytesPerFrame = 4; + deviceFormat.mChannelsPerFrame = 2; + deviceFormat.mBitsPerChannel = 16; + deviceFormat.mReserved = 0; + + AudioQueueNewOutput(&deviceFormat, soundFill, NULL, NULL, NULL, 0, &audioQueue); + + for (int i = 0; i < 2; i++) { + AudioQueueBufferRef mBuffer; + AudioQueueAllocateBuffer(audioQueue, SND_SIZE, &mBuffer); + soundFill(NULL, audioQueue, mBuffer); + } + AudioQueueStart(audioQueue, NULL); +} + +// common input functions +InputKey keyToInputKey(int code) { + static const int codes[] = { + 0x7B, 0x7C, 0x7E, 0x7D, 0x31, 0x24, 0x35, 0x38, 0x3B, 0x3A, + 0x1D, 0x12, 0x13, 0x14, 0x15, 0x17, 0x16, 0x1A, 0x1C, 0x19, // 0..9 + 0x00, 0x0B, 0x08, 0x02, 0x0E, 0x03, 0x05, 0x04, 0x22, 0x26, 0x28, 0x25, 0x2E, // A..M + 0x2D, 0x1F, 0x23, 0x0C, 0x0F, 0x01, 0x11, 0x20, 0x09, 0x0D, 0x07, 0x10, 0x06, // N..Z + }; + + for (int i = 0; i < sizeof(codes) / sizeof(codes[0]); i++) + if (codes[i] == code) + return (InputKey)(ikLeft + i); + return ikNone; +} + +InputKey mouseToInputKey(int btn) { + switch (btn) { + case 1 : return ikMouseL; + case 2 : return ikMouseR; + case 3 : return ikMouseM; + } + return ikNone; +} + +OSStatus eventHandler(EventHandlerCallRef handler, EventRef event, void* userData) { + OSType eventClass = GetEventClass(event); + UInt32 eventKind = GetEventKind(event); + + switch (eventClass) { + case kEventClassWindow : + switch (eventKind) { + case kEventWindowClosed : + isQuit = true; + break; + case kEventWindowBoundsChanged : { + aglUpdateContext(context); + Rect rect; + GetWindowPortBounds(window, &rect); + Core::width = rect.right - rect.left; + Core::height = rect.bottom - rect.top; + break; + } + } + break; + + case kEventClassMouse : { + EventMouseButton mouseButton; + CGPoint mousePos; + Rect wndRect; + + GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(mousePos), NULL, &mousePos); + GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), nil, &mouseButton); + + GetWindowBounds(window, kWindowContentRgn, &wndRect); + mousePos.x -= wndRect.left; + mousePos.y -= wndRect.top; + vec2 pos(mousePos.x, mousePos.y); + + switch (eventKind) { + case kEventMouseDown : + case kEventMouseUp : { + InputKey key = mouseToInputKey(mouseButton); + Input::setPos(key, pos); + Input::setDown(key, eventKind == kEventMouseDown); + break; + } + case kEventMouseDragged : + Input::setPos(ikMouseL, pos); + break; + } + break; + } + + case kEventClassKeyboard : { + switch (eventKind) { + case kEventRawKeyDown : + case kEventRawKeyUp : { + uint32 keyCode; + if (GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(keyCode), NULL, &keyCode) == noErr) + Input::setDown(keyToInputKey(keyCode), eventKind != kEventRawKeyUp); + break; + } + case kEventRawKeyModifiersChanged : { + uint32 modifiers; + if (GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers) == noErr) { + Input::setDown(ikShift, modifiers & shiftKey); + Input::setDown(ikCtrl, modifiers & controlKey); + Input::setDown(ikAlt, modifiers & optionKey); + } + break; + } + } + break; + } + } + + return CallNextEventHandler(handler, event); +} + +int getTime() { + UInt64 t; + Microseconds((UnsignedWide*)&t); + return int(t / 1000); +} + +char *contentPath; + +int main() { +// init window + Rect rect = {0, 0, 720, 1280}; + CreateNewWindow(kDocumentWindowClass, kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | kWindowFullZoomAttribute | kWindowResizableAttribute | kWindowStandardHandlerAttribute, &rect, &window); + SetWTitle(window, "\pOpenLara"); + + // init OpenGL context + GLint attribs[] = { + AGL_RGBA, + AGL_DOUBLEBUFFER, + AGL_BUFFER_SIZE, 32, + AGL_DEPTH_SIZE, 24, + AGL_STENCIL_SIZE, 8, + AGL_NONE + }; + AGLPixelFormat format = aglChoosePixelFormat(NULL, 0, (GLint*)&attribs); + context = aglCreateContext(format, NULL); + aglDestroyPixelFormat(format); + + aglSetDrawable(context, GetWindowPort(window)); + aglSetCurrentContext(context); + + // get path to game content + CFBundleRef bundle = CFBundleGetMainBundle(); + CFURLRef bundleURL = CFBundleCopyBundleURL(bundle); + CFStringRef pathStr = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle); + contentPath = new char[1024]; + CFStringGetFileSystemRepresentation(pathStr, contentPath, 1024); + strcat(contentPath, "/Contents/Resources/"); + + soundInit(); + Game::init(); + + // show window + const int events[][2] = { + { kEventClassWindow, kEventWindowClosed }, + { kEventClassWindow, kEventWindowBoundsChanged }, + { kEventClassKeyboard, kEventRawKeyDown }, + { kEventClassKeyboard, kEventRawKeyUp }, + { kEventClassKeyboard, kEventRawKeyModifiersChanged }, + { kEventClassMouse, kEventMouseDown }, + { kEventClassMouse, kEventMouseUp }, + { kEventClassMouse, kEventMouseDragged }, + }; + + InstallEventHandler(GetApplicationEventTarget(), (EventHandlerUPP)eventHandler, sizeof(events) / sizeof(events[0]), (EventTypeSpec*)&events, NULL, NULL); + SelectWindow(window); + ShowWindow(window); + + int lastTime = getTime(), fpsTime = lastTime + 1000, fps = 0; + + EventRecord event; + while (!isQuit) + if (!GetNextEvent(0xffff, &event)) { + int time = getTime(); + if (time <= lastTime) + continue; + + float delta = (time - lastTime) * 0.001f; + while (delta > EPS) { + Core::deltaTime = min(delta, 1.0f / 30.0f); + Game::update(); + delta -= Core::deltaTime; + } + lastTime = time; + + Core::stats.dips = 0; + Core::stats.tris = 0; + Game::render(); + aglSwapBuffers(context); + + if (fpsTime < getTime()) { + LOG("FPS: %d DIP: %d TRI: %d\n", fps, Core::stats.dips, Core::stats.tris); + fps = 0; + fpsTime = getTime() + 1000; + } else + fps++; + } + + Game::free(); + delete[] contentPath; + + aglSetCurrentContext(NULL); + ReleaseWindow(window); + + return 0; +} diff --git a/src/utils.h b/src/utils.h index 929fb71c..14ee2bda 100644 --- a/src/utils.h +++ b/src/utils.h @@ -517,7 +517,15 @@ struct Stream { Stream(const void *data, int size) : f(NULL), data((char*)data), size(size), pos(0) {} Stream(const char *name) : data(NULL), size(-1), pos(0) { + #ifdef __APPLE__ + extern char *contentPath; + int len = strlen(contentPath); + strcat(contentPath, name); + f = fopen(contentPath, "rb"); + contentPath[len] = '\0'; + #else f = fopen(name, "rb"); + #endif if (!f) LOG("error loading file\n"); fseek(f, 0, SEEK_END); size = ftell(f);