├── .editorconfig ├── .gitignore ├── README.md ├── code ├── Makefile ├── osx_asset_builder.cpp ├── osx_asset_builder.h ├── osx_handmade.h ├── osx_handmade_audio.cpp ├── osx_handmade_cocoa.h ├── osx_handmade_cocoa.mm ├── osx_handmade_debug.cpp ├── osx_handmade_dylib.cpp ├── osx_handmade_events.h ├── osx_handmade_file.cpp ├── osx_handmade_game.cpp ├── osx_handmade_hid.cpp ├── osx_handmade_memory.cpp ├── osx_handmade_opengl.cpp ├── osx_handmade_opengl.h ├── osx_handmade_opengl.mm ├── osx_handmade_playback.cpp ├── osx_handmade_process.cpp ├── osx_handmade_renderer.h ├── osx_handmade_thread.cpp ├── osx_hhfont.cpp ├── osx_main.mm ├── osx_renderer_test.mm ├── osx_tabview.info.plist ├── osx_tabview.mm └── vsprintf.cpp ├── cpp └── code │ ├── README.md │ └── vsprintf.cpp ├── fix_handmade_hero_source.sh ├── fonts ├── AUTHORS ├── LICENSE ├── LiberationMono-Regular.ttf ├── LiberationSans-Regular.ttf └── LiberationSerif-Regular.ttf ├── patches ├── handmade_brain.cpp.day399.patch ├── handmade_dev_ui.cpp.day492.patch ├── handmade_lighting.cpp.day434.patch ├── handmade_memory.h.day541.patch ├── handmade_opengl.cpp.day373.patch ├── handmade_opengl.cpp.day374.patch ├── handmade_opengl.cpp.day375.patch ├── handmade_opengl.cpp.day380.patch ├── handmade_opengl.cpp.day384.patch ├── handmade_opengl.cpp.day387.patch ├── handmade_opengl.cpp.day388.patch ├── handmade_opengl.cpp.day393.patch ├── handmade_opengl.cpp.day394.patch ├── handmade_opengl.cpp.day395.patch ├── handmade_opengl.cpp.day396.patch ├── handmade_opengl.cpp.day397.patch ├── handmade_opengl.cpp.day398.patch ├── handmade_opengl.cpp.day405.patch ├── handmade_opengl.cpp.day410.patch ├── handmade_opengl.cpp.day414.patch ├── handmade_opengl.cpp.day415.patch ├── handmade_opengl.cpp.day416.patch ├── handmade_opengl.cpp.day420.patch ├── handmade_opengl.cpp.day430.patch ├── handmade_renderer_opengl.cpp.day471.patch ├── handmade_renderer_opengl.cpp.day475.patch ├── handmade_sampling_spheres.inl.day552.patch ├── handmade_simd.h.day434.patch ├── hhlightprof.cpp.day593.patch ├── hhlightprof.cpp.day594.patch ├── hhlightprof.cpp.day595.patch └── hhlightprof.cpp.day615.patch ├── test └── README.md └── xcode ├── Handmade Hero.xcodeproj └── project.pbxproj └── handmade.xcodeproj └── project.pbxproj /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{c,cpp,h,m,mm,inl}] 4 | indent_style = space 5 | indent_size = 4 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .ycm_extra_conf.py 3 | .ycm_extra_conf.pyc 4 | cpp 5 | data 6 | xcode/Handmade\ Hero.xcodeproj/project.xcworkspace/* 7 | xcode/Handmade\ Hero.xcodeproj/xcuserdata 8 | xcode/handmade.xcodeproj/project.xcworkspace/* 9 | xcode/handmade.xcodeproj/xcuserdata 10 | handmade 11 | handmade.dSYM/ 12 | osx_asset_builder 13 | test_asset_builder 14 | test_asset_builder.dSYM/ 15 | *.dylib 16 | *.so 17 | *.o 18 | Contents/ 19 | Handmade.app 20 | HandmadeTabView 21 | hhaedit 22 | hhsphere 23 | hhlightprof 24 | stb_truetype.h 25 | loop_edit*.hmi 26 | *.hha 27 | *.dump 28 | hh*.sh 29 | cas*.sh 30 | makepatch*.sh 31 | art/ 32 | build/ 33 | hha/ 34 | sources/ 35 | tags/ 36 | test/ 37 | test2/ 38 | test3/ 39 | osx_fonts/ 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | osx_handmade 2 | ============ 3 | 4 | A port of Handmade Hero (http://handmadehero.org) for macOS. 5 | 6 | This repository works with Casey's source code from Day 615. 7 | 8 | If you encounter any errors compiling or running on a particular 9 | day of the series, check out the [macOS Porting Notes](#macos-porting-notes) 10 | section below. I have made occasional patches along the way to fix 11 | interim problems porting to macOS. 12 | 13 | This macOS platform layer code does not need to be updated for 14 | every episode of Handmade Hero, although I do test each day's code 15 | on macOS. If you see "missing" days in this macOS repository, it just 16 | means that the most recent version of the macOS platform layer will 17 | work. For example, day 405 of the macOS platform layer 18 | will work with Casey's Handmade Hero days 405 through 409. 19 | 20 | 21 | # Compiling and Running 22 | 23 | Once you clone or update this repository, copy (or clone/pull, if you are 24 | using Casey's Github repository) Casey's source code files to the 25 | cpp/code subdirectory of this repository. Also, copy over the 26 | sources and tags asset folders to the root directory of this 27 | repository. 28 | 29 | Your resulting directory structure should look like this: 30 | 31 | // files from this repository... 32 | . // root directory of this repository 33 | code/ // macOS platform code 34 | patches/ // patches to Casey's source code 35 | xcode/ // optional Xcode project files 36 | // files from Handmade Hero distribution... 37 | cpp/code/ // Casey's code 38 | sources/ // artwork and sounds 39 | tags/ // descriptions and instructions for asset import 40 | 41 | Before you compile the code, run 42 | 43 | sh fix_handmade_hero_source.sh 44 | 45 | from the root directory of this repository to apply any relevant patches 46 | to Casey's Handmade Hero code. This shell script is updated to run 47 | appropriate patch files from the patches subdirectory. If there are no 48 | pending patches for a particular day, the shell script does nothing. 49 | 50 | The first time you compile, run `make full` from the code 51 | directory (Note: not the cpp/code directory!) to build the application bundle. 52 | Note that a `make full` will cause an entire asset import on the subsequent 53 | game startup, which is slow. And it's extra slow in debug mode, so doing 54 | the initial asset import in release mode is recommended. 55 | 56 | Once you have done a full build and have created the application 57 | bundles, you can run `make` (with no arguments) to just recompile the 58 | dynamic libraries and the executable. Most of the build time when running 59 | a `make full` is spent copying over the large asset files, so `make` avoids 60 | that step and also avoids a full asset import on game startup. 61 | 62 | You can then either run `handmade` directly, or `open Handmade.app`. 63 | The advantage of running `handmade` directly is that debug console output 64 | (printf's, etc.) will be displayed in your terminal window instead 65 | of being logged to the System Console. 66 | 67 | I typically run the game from the command line like this: 68 | 69 | ./handmade 70 | 71 | I normally use lldb to debug. lldb has a `gui` command that will 72 | display a source code and variable view while debugging. It's not great, 73 | but it's sometimes better than using the plain command line mode in lldb. 74 | You can also debug using Xcode. 75 | 76 | 77 | ### Hot Code Reloading 78 | 79 | Hot code reloading is supported, so you can just run `make` again (or 80 | have your favorite editor do it) while the application is running to 81 | build and reload the newest code. `make` recompiles all of the code 82 | targets. If you know that your code change only affects a single target 83 | (e.g. the renderer dynamic library), you can just recompile that 84 | particular target to speed up the hot reloading cycle. These are the 85 | individual targets for the game: 86 | 87 | make handmade 88 | make libhandmade.dylib 89 | make libhandmade_opengl.dylib 90 | 91 | 92 | ### Utilities 93 | 94 | There are make targets for several utilities. None of these utilities 95 | are required to run the game, but they are useful for debugging and 96 | exploring. 97 | 98 | First, there are utilities that have been rewritten for macOS: 99 | 100 | make HandmadeTabView 101 | make HandmadeRendererTest 102 | make osx_hhfont 103 | 104 | `HandmadeTabView` can view a text dump of an asset file that was 105 | generated by `hhaedit`. You can either open a dump file, or drag 106 | one into the application window. 107 | 108 | `HandmadeRendererTest` is a macOS version of the Windows renderer 109 | test utility. 110 | 111 | `osx_hhfont` uses CoreText to generate PNG glyph files and tag files 112 | from any installed macOS font. Run `osx_hhfont` with no arguments 113 | to see the command line options. The options differ slightly from the 114 | official Handmade Hero version. There is also a debug mode option 115 | featuring ASCII glyph art. 116 | 117 | Several utilities from the Handmade Hero distribution 118 | compile with no needed changes (outside of an occasional patch) 119 | on macOS: 120 | 121 | make hhaedit 122 | make hhsphere 123 | make hhlightprof 124 | make test_png 125 | 126 | 127 | # macOS Porting Notes 128 | 129 | ## Day 615 Note: 130 | 131 | Updated the patch to `hhlightprof` to replace the Microsoft-specific 132 | `__popcnt` with the more portable Intel `_mm_popcnt_u32` intrinsic. 133 | 134 | 135 | ## Day 612 Note: 136 | 137 | Casey turned off the raycaster at the end of the stream to test some 138 | performance numbers, so you will see a dark world. If you want to 139 | turn the lights back on, comment out the `CostMetric = 0;` on line 140 | 383 in handmade_lighting.cpp. 141 | 142 | 143 | ## Day 593 Note: 144 | 145 | The `hhlightprof` doesn't currently compile under macOS due to the 146 | new Windows-specific `QueryPerformanceCounter` calls. I created a 147 | quick patch to fix the errors. The fix is not a great solution 148 | for high-precision timing and is subject to overflow for long 149 | elapsed time measures. For the non-critical and relatively short 150 | elapsed timing that we are doing, it should be good enough. 151 | 152 | You can apply the patch by running: 153 | 154 | sh fix_handmade_hero_source.sh 155 | 156 | and then compiling with `make hhlightprof`. Once you have compiled 157 | and run Handmade Hero to generate the .dump files, change to the 158 | ./Contents/Resources/debug directory of the application bundle 159 | you are using and run `hhlightprof` from that directory. 160 | 161 | 162 | ## Day 591 Note: 163 | 164 | Added a new target for `hhlightprof`. The debug `.dump` files are 165 | located in the ./Contents/Resources/debug directory of the 166 | application bundle that you are using. 167 | 168 | If you use the ./handmade development executable, then run 169 | `hhlightprof` like this: 170 | 171 | hhlightprof ./Contents/Resources/debug/lightboxes.dump 172 | 173 | Or if using Handmade.app: 174 | 175 | hhlightprof Handmade.app/Contents/Resources/debug/lightboxes.dump 176 | 177 | 178 | ## Day 576 Note: 179 | 180 | Shaders now get recompiled upon a hot-reload. If you know you are 181 | only changing the renderer (and not the game code), you can just 182 | `make libhandmade_opengl.dylib` to quickly rebuild just the 183 | renderer code. 184 | 185 | 186 | ## Day 575 Note: 187 | 188 | Hot loading of the renderer is now supported. 189 | 190 | The default make target is now `make quick`, which recompiles 191 | all of the code, but does not rebuild the application bundle. 192 | This will prevent re-importing the asset libraries on startup. 193 | 194 | If you want to rebuild the application bundles and force a 195 | re-import of the asset libraries, you now run `make full`. 196 | 197 | 198 | ## Day 552 Note: 199 | 200 | Somewhere between Day 551 and 552, the PushX macros were fixed 201 | so I removed that patch. However, we are zero sum on patches 202 | for the day as I had to add a new patch to fix two misplaced 203 | `alignas` decorators in handmade_sampling_spheres.inl. 204 | 205 | As usual, you can apply patches by running: 206 | 207 | sh fix_handmade_hero_source.sh 208 | 209 | 210 | ## Day 541 Note: 211 | 212 | I added a new patch to fix a few compile errors in the PushX 213 | macros madness in handmade_memory.h. I'm not sure how the Visual 214 | Studio compiler let those slide, but clang said no way. 215 | 216 | You can apply the patch by running: 217 | 218 | sh fix_handmade_hero_source.sh 219 | 220 | 221 | ## Day 532 Note: 222 | 223 | I wrote a native macOS version of hhfont using Core Text. It is not 224 | required, as you can just use the font images and hht file that Casey 225 | generated. I was mostly interested in learning about some of the 226 | details of Core Text that I hadn't used before. 227 | 228 | If you do want to generate your own font images and hht files, 229 | you can compile and run the utility like this: 230 | 231 | make osx_hhfont 232 | 233 | If you run `osx_hhfont` with no command line options, you will see 234 | some usage details. Once you generate the .hht file and the png 235 | images, copy the .hht file and the .png files into the appropriate 236 | tags and sources directories. 237 | 238 | `osx_hhfont` also has a handy debugging mode to ASCII print a single 239 | code point or glyph. See the usage for details. 240 | 241 | ## Day 526 Note: 242 | 243 | Make sure you reimport your assets (or just do a full 'make' build) 244 | so you can hear the sound and music play. 245 | 246 | 247 | ## Day 516 Note: 248 | 249 | Make sure you move the /sources directory tree to the root directory 250 | of this repository before running make. 251 | 252 | A full build triggers an asset import when running the game for the 253 | first time. Asset importing is slow. If you are just making code 254 | changes and don't need to reimport assets between builds, then 255 | 'make quick' is the target you want. 256 | 257 | 258 | ## Day 498 Note: 259 | 260 | After you do a clean compile and run the game for the first time, 261 | you have to import and save the textures using the new DevUI 262 | command button (hit F10 to display the DevUI, F9 to dismiss it when 263 | finished). 264 | 265 | 266 | ## Day 493 Note: 267 | 268 | The handmade_dev_ui.cpp compile error was fixed in day 493. You should still 269 | run 'fix_handmade_hero_source.sh' to patch the lingering OpenGL 270 | artifact issue if you notice it happening on your particular 271 | graphics hardware. 272 | 273 | Compilation note: Hot reloading works when you use the 274 | 'make quick' target. This will recompile the executable and the 275 | dynamic library and move them into place without needing to 276 | rebuild the entire application bundle. 277 | 278 | The 'make quick' target is also useful to prevent the assets from 279 | being re-imported when rebuilding the application bundle, which 280 | is what happens when performing a default 'make'. 281 | 282 | 283 | ## Day 492 Note: 284 | 285 | I added a new patch to fix a compile error in handmade_dev_ui.cpp. clang 286 | complains about passing string literals to the Button() function which 287 | expects a char pointer. For now, the patch just casts the string literals to 288 | character pointers. 289 | 290 | You can apply the patch by running: 291 | 292 | sh fix_handmade_hero_source.sh 293 | 294 | Also, don't forget to regenerate your .hha files to fix the font glyph alignment 295 | bug. 296 | 297 | 298 | ## Day 472 Note: 299 | 300 | If you want to run the HandmadeRendererTest with textures, you will 301 | have to recreate the sample textures that Casey created on stream 302 | and put them in the ./data/renderer_test directory. I recreated 303 | them with Gimp on macOS, but I didn't want to redistribute Casey's 304 | original artwork. 305 | 306 | WARNING: The popular native graphics editing packages on macOS 307 | (Acorn, Pixelmator, Affinity Photo, Preview, etc.) either do not 308 | export bitmaps at all, or do not write bitmaps in the 309 | .bmp format that the Handmade Hero code expects. The y-axis is 310 | flipped and a different compression method is used. I'd recommend 311 | downloading and using Gimp to create the .bmp files. 312 | 313 | 314 | ## Day 471 Note: 315 | 316 | I added an macOS version of the HandmadeRendererTest application. 317 | You can build this by running: 318 | 319 | make HandmadeRendererTest 320 | 321 | in the code subdirectory. This will create the HandmadeRendererTest.app 322 | bundle. You can run the application from the Finder or by launching it 323 | from a shell prompt like this: 324 | 325 | open HandmadeRendererTest.app 326 | 327 | 328 | ## Day 467 Note: 329 | 330 | Day 467 started using version 1 assets, so don't forget to 331 | rewrite the .hha files! You can rewrite an .hha file like this: 332 | 333 | hhaedit -rewrite ../data/intro_art.hha ../data/intro_art_v1.hha 334 | 335 | Day 468 started using local.hha to dynamically import .png resources 336 | at runtime. Make sure you create a local.hha file before compiling 337 | the application bundle if you want this functionality at runtime. 338 | 339 | hhaedit -create ../data/local.hha 340 | 341 | 342 | ## Day 466 Note: 343 | 344 | I added an macOS version of the TabView utility. You can build this 345 | by running: 346 | 347 | make HandmadeTabView 348 | 349 | in the code subdirectory (the same directory where you build Handmade Hero). 350 | This will create the HandmadeTabView.app bundle. 351 | 352 | Some notes: 353 | 354 | - Create .hha dump files for viewing like this: 355 | 356 | hhaedit -dump ../data/intro_art_v1.hha > intro_art_v1.hha.dump 357 | 358 | - Run HandmadeTabView.app. Either double-click the .app file in the Finder, 359 | or run it from a shell prompt like this: 360 | 361 | open HandmadeTabView.app 362 | 363 | - The application launches with an empty document. You can drag and drop 364 | a dump file from the Finder onto any existing window (empty or not) and it 365 | will replace the current contents with the contents of the dropped file. 366 | You can also use the standard Open File or Open Recent menu items to 367 | select a file to open. 368 | 369 | - The application supports multiple files open at the same time so that 370 | you can compare dump file contents. 371 | 372 | - 'Command +' and 'Command -' (also available from the View menu) will 373 | expand/collapse all nodes of a dump tree in the currently active window. 374 | 375 | - 'Command r' will reload the file contents of the currently active window. 376 | 377 | 378 | ## 2018-08-17 Note: 379 | 380 | While the code compiles as-is on macOS, you must first apply a patch to 381 | Casey's Handmade Hero source code to get the game to render properly. You can 382 | apply the patch by running: 383 | 384 | sh fix_handmade_hero_source.sh 385 | 386 | This patches a problem in handmade_opengl.cpp: 387 | 388 | - Casey's final implementation for multisample depth peeling on Day 388 389 | causes undesirable artifacts on macOS. Instead of averaging the Min and Max 390 | Depth values, I reverted to using the MaxDepth value in the shader with a 391 | threshold of 0.02. This still produces some minor artifacts, but it is a big 392 | improvement over the averaging method. I'll continue to look into this. 393 | 394 | 395 | Note on using joysticks: Casey added a Clutch control on Day 443. He 396 | uses an XBox controller's Left or Right "Trigger" buttons for the Clutch 397 | control. I currently have this mapped to HID Button 6 on macOS, which on a 398 | Logitech Dual Action controller, corresponds to the top right shoulder 399 | button. Your mileage may vary with other controllers. Let me know if you 400 | have problems. 401 | 402 | 403 | 404 | # Author 405 | 406 | Jeff Buck 407 | 408 | The original version of Handmade Hero is being created by Casey Muratori. 409 | 410 | -------------------------------------------------------------------------------- /code/Makefile: -------------------------------------------------------------------------------- 1 | CXX = clang 2 | 3 | HANDMADE_CODE_PATH = ../cpp/code 4 | HANDMADE_SOURCES_PATH = ../sources 5 | HANDMADE_TAGS_PATH = ../tags 6 | HANDMADE_ART_PATH = ../art 7 | HANDMADE_SOUND_PATH = ../sound 8 | 9 | HANDMADE_FLAGS = -DOSX_HANDMADE_USE_METAL=0 -DHANDMADE_USE_VSYNC=0 -DHANDMADE_PROFILE=1 -DHANDMADE_INTERNAL=1 -DHANDMADE_SLOW=1 -DHANDMADE_OSX=1 10 | 11 | HANDMADE_COMPILER_FLAGS = -fno-exceptions -fno-rtti 12 | 13 | HANDMADE_WARNING_FLAGS = -Wno-deprecated-declarations -Wno-unused-function -Wno-unused-variable -Wno-c++11-narrowing -Wno-missing-braces -Wno-logical-not-parentheses -Wno-switch -Wno-write-strings -Wno-c++11-compat-deprecated-writable-strings -Wno-tautological-compare -Wno-missing-braces -Wno-null-dereference -Wno-writable-strings 14 | 15 | 16 | COPTS = -g -Wall -fno-inline $(HANDMADE_FLAGS) 17 | COPTS = -O2 -Wall $(HANDMADE_FLAGS) 18 | 19 | 20 | CPP11_FLAGS = -std=c++11 -stdlib=libc++ -ggdb 21 | CPP11_LD_FLAGS = -lstdc++ 22 | 23 | 24 | OSX_LD_FLAGS = -framework Cocoa -framework IOKit -framework AudioUnit 25 | 26 | 27 | DYNAMIC_COMPILE_PATH=$(shell pwd) 28 | DYNAMIC_COMPILE_COMMAND=$(DYNAMIC_COMPILE_PATH)/dynamic_compile.sh 29 | 30 | 31 | #default: osx_hhfont 32 | default: quick 33 | 34 | full: clean libhandmade.dylib libhandmade_opengl.dylib handmade package unlock 35 | 36 | # 'quick' only rebuilds the local debugging 'handmade' executable. Does not update the Handmade.app bundle! 37 | lock: 38 | echo "Temporary Code Rebuild Lock file" > lock.tmp 39 | cp lock.tmp ./Handmade.app/Contents/MacOS/lock.tmp 40 | 41 | unlock: 42 | rm -f lock.tmp 43 | rm -f ./Handmade.app/Contents/MacOS/lock.tmp 44 | 45 | quick_copy: 46 | cp handmade ./Contents/MacOS/Handmade 47 | cp libhandmade.dylib ./Contents/MacOS/libhandmade.dylib 48 | cp libhandmade_opengl.dylib ./Contents/MacOS/libhandmade_opengl.dylib 49 | cp handmade ./Handmade.app/Contents/MacOS/Handmade 50 | cp libhandmade.dylib ./Handmade.app/Contents/MacOS/libhandmade.dylib 51 | cp libhandmade_opengl.dylib ./Handmade.app/Contents/MacOS/libhandmade_opengl.dylib 52 | 53 | quick: lock quick_clean libhandmade.dylib libhandmade_opengl.dylib handmade quick_copy unlock 54 | 55 | 56 | clean_handmade_lib: 57 | rm -f libhandmade.dylib 58 | 59 | libhandmade.dylib: clean_handmade_lib 60 | $(CXX) $(COPTS) $(HANDMADE_COMPILER_FLAGS) $(HANDMADE_WARNING_FLAGS) $(CPP11_FLAGS) -dynamiclib -o $@ $(HANDMADE_CODE_PATH)/handmade.cpp 61 | 62 | 63 | clean_opengl_lib: 64 | rm -f libhandmade_opengl.dylib 65 | 66 | libhandmade_opengl.dylib: clean_opengl_lib 67 | $(CXX) $(COPTS) $(HANDMADE_COMPILER_FLAGS) $(HANDMADE_WARNING_FLAGS) $(CPP11_FLAGS) -I$(HANDMADE_CODE_PATH) -dynamiclib -framework Cocoa -framework QuartzCore -framework OpenGL -o $@ osx_handmade_opengl.mm 68 | 69 | 70 | clean_metal_lib: 71 | rm -f libhandmade_metal.dylib 72 | 73 | libhandmade_metal.dylib: clean_metal_lib 74 | $(CXX) $(COPTS) $(HANDMADE_COMPILER_FLAGS) $(HANDMADE_WARNING_FLAGS) $(CPP11_FLAGS) $(CPP11_LD_FLAGS) -I$(HANDMADE_CODE_PATH) -dynamiclib -framework Cocoa -framework Metal -framework MetalKit -o $@ osx_handmade_metal.mm 75 | 76 | 77 | clean_handmade_app: 78 | rm -f ./handmade 79 | 80 | handmade: clean_handmade_app 81 | $(CXX) $(COPTS) $(CPP11_FLAGS) -I$(HANDMADE_CODE_PATH) $(HANDMADE_COMPILER_FLAGS) -Wno-writable-strings -Wno-deprecated-declarations -Wno-null-dereference -Wno-c++11-compat-deprecated-writable-strings -Wno-unused-function -Wno-unused-variable -Wno-missing-braces $(CPP11_LD_FLAGS) $(OSX_LD_FLAGS) -o $@ osx_main.mm 82 | 83 | 84 | BINARIES = libhandmade.dylib libhandmade_opengl.dylib handmade test_png hhaedit HandmadeTabView HandmadeRendererTest 85 | 86 | all: clean libhandmade.dylib handmade package test_png hhaedit HandmadeTabView HandmadeRendererTest 87 | 88 | package: 89 | # The 'local' bundle for convenient debugging with lldb 90 | mkdir -p ./Contents/MacOS 91 | mkdir -p ./Contents/Resources 92 | mkdir -p ./Contents/Resources/data 93 | mkdir -p ./Contents/Resources/debug 94 | cp -R ../tags ./Contents/Resources 95 | cp -R ../sources ./Contents/Resources 96 | # Uncomment the following 4 lines to use our own generated fonts 97 | # cp osx_fonts/liberation_mono* ./Contents/Resources/sources/base_game/fonts 98 | # mkdir -p ./Contents/Resources/tags/fonts 99 | # cp LiberationMono.hht ./Contents/Resources/tags/fonts/ 100 | #cp Monaco.hht ./Contents/Resources/tags/fonts/ 101 | # 102 | #cp $(HANDMADE_ASSETS_PATH)/testfonts_v2.hha ./Contents/Resources/data/testfonts_v2.hha 103 | #cp $(HANDMADE_ASSETS_PATH)/intro_art_v2.hha ./Contents/Resources/data/intro_art_v2.hha 104 | #cp $(HANDMADE_ART_PATH)/*.png ./Contents/Resources/art 105 | cp libhandmade.dylib ./Contents/MacOS/libhandmade.dylib 106 | cp libhandmade_opengl.dylib ./Contents/MacOS/libhandmade_opengl.dylib 107 | # The "official" app bundle 108 | #rm -rf ../build/Handmade.app 109 | mkdir Handmade.app 110 | cp -R ./Contents ./Handmade.app/ 111 | cp handmade ./Handmade.app/Contents/MacOS/Handmade 112 | #mv Handmade.app ../build 113 | 114 | 115 | #osx_asset_builder: osx_asset_builder.cpp 116 | # $(CXX) $(COPTS) $(CPP11_FLAGS) -I$(HANDMADE_CODE_PATH) $(HANDMADE_COMPILER_FLAGS) $(HANDMADE_WARNING_FLAGS) -o $@ $^ 117 | 118 | test_png: $(HANDMADE_CODE_PATH)/test_png.cpp 119 | $(CXX) $(COPTS) $(CPP11_FLAGS) -I$(HANDMADE_CODE_PATH) $(HANDMADE_COMPILER_FLAGS) $(HANDMADE_WARNING_FLAGS) -o $@ $^ 120 | 121 | hhaedit: $(HANDMADE_CODE_PATH)/hhaedit.cpp 122 | $(CXX) $(COPTS) $(CPP11_FLAGS) -I$(HANDMADE_CODE_PATH) $(HANDMADE_COMPILER_FLAGS) $(HANDMADE_WARNING_FLAGS) -o $@ $^ 123 | 124 | hhsphere: $(HANDMADE_CODE_PATH)/hhsphere.cpp 125 | $(CXX) $(COPTS) $(CPP11_FLAGS) -I$(HANDMADE_CODE_PATH) $(HANDMADE_COMPILER_FLAGS) $(HANDMADE_WARNING_FLAGS) -o $@ $^ 126 | 127 | hhlightprof: $(HANDMADE_CODE_PATH)/hhlightprof.cpp 128 | $(CXX) $(COPTS) $(CPP11_FLAGS) -I$(HANDMADE_CODE_PATH) $(HANDMADE_COMPILER_FLAGS) $(HANDMADE_WARNING_FLAGS) -mpopcnt -o $@ $^ 129 | 130 | osx_hhfont: osx_hhfont.cpp 131 | $(CXX) $(COPTS) $(CPP11_FLAGS) -I$(HANDMADE_CODE_PATH) $(HANDMADE_COMPILER_FLAGS) $(HANDMADE_WARNING_FLAGS) -framework Foundation -framework CoreGraphics -framework CoreText -o $@ $^ 132 | 133 | #handmade_optimized.o: $(HANDMADE_CODE_PATH)/handmade_optimized.cpp 134 | # $(CXX) -O3 -Wall $(HANDMADE_COMPILER_FLAGS) $(HANDMADE_FLAGS) $(HANDMADE_WARNING_FLAGS) $(CPP11_FLAGS) -c $< 135 | 136 | 137 | HandmadeTabView: osx_tabview.mm 138 | $(CXX) $(COPTS) $(HANDMADE_COMPILER_FLAGS) -framework Cocoa $(CPP11_LD_FLAGS) -o $@ $^ 139 | rm -rf ./HandmadeTabView.app 140 | mkdir -p ./HandmadeTabView.app/Contents/MacOS 141 | cp HandmadeTabView HandmadeTabView.app/Contents/MacOS/HandmadeTabView 142 | cp osx_tabview.info.plist HandmadeTabView.app/Contents/Info.plist 143 | 144 | HandmadeRendererTest: osx_renderer_test.mm libhandmade_opengl.dylib 145 | $(CXX) $(COPTS) $(HANDMADE_COMPILER_FLAGS) -I$(HANDMADE_CODE_PATH) $(CPP11_FLAGS) -Wno-null-dereference -Wno-missing-braces -Wno-unused-variable -Wno-unused-function -Wno-writable-strings -framework Cocoa $(CPP11_LD_FLAGS) -o $@ $< 146 | rm -rf ./HandmadeRendererTest.app 147 | mkdir -p ./HandmadeRendererTest.app/Contents/MacOS 148 | mkdir -p ./HandmadeRendererTest.app/Contents/Resources 149 | cp $(HANDMADE_SOURCES_PATH)/renderer_test/test_cube_grass.bmp ./HandmadeRendererTest.app/Contents/Resources 150 | cp $(HANDMADE_SOURCES_PATH)/renderer_test/test_cube_wall.bmp ./HandmadeRendererTest.app/Contents/Resources 151 | cp $(HANDMADE_SOURCES_PATH)/renderer_test/test_sprite_tree.bmp ./HandmadeRendererTest.app/Contents/Resources 152 | cp $(HANDMADE_SOURCES_PATH)/renderer_test/test_sprite_head.bmp ./HandmadeRendererTest.app/Contents/Resources 153 | cp $(HANDMADE_SOURCES_PATH)/renderer_test/test_cover_grass.bmp ./HandmadeRendererTest.app/Contents/Resources 154 | mv HandmadeRendererTest HandmadeRendererTest.app/Contents/MacOS/HandmadeRendererTest 155 | cp libhandmade_opengl.dylib HandmadeRendererTest.app/Contents/Resources 156 | #cp osx_tabview.info.plist HandmadeTabView.app/Contents/Info.plist 157 | 158 | quick_clean: 159 | rm -f handmade libhandmade.dylib libhandmade_opengl.dylib 160 | 161 | clean: 162 | rm -rf *.o *.dylib $(BINARIES) Contents Handmade.app HandmadeTabView.app HandmadeRendererTest.app osx_hhfont *.dSYM 163 | 164 | -------------------------------------------------------------------------------- /code/osx_asset_builder.h: -------------------------------------------------------------------------------- 1 | #if !defined(TEST_ASSET_BUILDER_H) 2 | /* ======================================================================== 3 | $File: $ 4 | $Date: $ 5 | $Revision: $ 6 | $Creator: Casey Muratori $ 7 | $Notice: (C) Copyright 2015 by Molly Rocket, Inc. All Rights Reserved. $ 8 | ======================================================================== */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "handmade_platform.h" 14 | #include "handmade_file_formats.h" 15 | #include "handmade_file_formats_v0.h" 16 | #include "handmade_intrinsics.h" 17 | #include "handmade_math.h" 18 | 19 | 20 | #define ONE_PAST_MAX_FONT_CODEPOINT (0x10FFFF + 1) 21 | 22 | //#define USE_FONTS_FROM_WINDOWS 1 23 | 24 | #if USE_FONTS_FROM_WINDOWS 25 | #include 26 | 27 | #define MAX_FONT_WIDTH 1024 28 | #define MAX_FONT_HEIGHT 1024 29 | 30 | global_variable VOID *GlobalFontBits; 31 | global_variable HDC GlobalFontDeviceContext; 32 | 33 | #else 34 | #define STB_TRUETYPE_IMPLEMENTATION 35 | #include "stb_truetype.h" 36 | #endif 37 | 38 | struct loaded_bitmap 39 | { 40 | int32 Width; 41 | int32 Height; 42 | int32 Pitch; 43 | void *Memory; 44 | 45 | void *Free; 46 | }; 47 | 48 | #if not USE_FONTS_FROM_WINDOWS 49 | struct font_metric 50 | { 51 | int32 Ascent; 52 | int32 Descent; 53 | int32 Leading; 54 | }; 55 | #endif 56 | 57 | struct loaded_font 58 | { 59 | #if USE_FONTS_FROM_WINDOWS 60 | HFONT Win32Handle; 61 | TEXTMETRIC TextMetric; 62 | #else 63 | stbtt_fontinfo FontInfo; 64 | font_metric FontMetric; 65 | r32 Scale; 66 | #endif 67 | 68 | r32 LineAdvance; 69 | 70 | hha_font_glyph *Glyphs; 71 | r32 *HorizontalAdvance; 72 | 73 | u32 MinCodePoint; 74 | u32 MaxCodePoint; 75 | 76 | u32 MaxGlyphCount; 77 | u32 GlyphCount; 78 | 79 | u32 *GlyphIndexFromCodePoint; 80 | u32 OnePastHighestCodepoint; 81 | }; 82 | 83 | enum asset_type 84 | { 85 | AssetType_Sound, 86 | AssetType_Bitmap, 87 | AssetType_Font, 88 | AssetType_FontGlyph, 89 | }; 90 | 91 | struct loaded_font; 92 | struct asset_source_font 93 | { 94 | loaded_font *Font; 95 | }; 96 | 97 | struct asset_source_font_glyph 98 | { 99 | loaded_font *Font; 100 | u32 Codepoint; 101 | }; 102 | 103 | struct asset_source_bitmap 104 | { 105 | char *FileName; 106 | }; 107 | 108 | struct asset_source_sound 109 | { 110 | char *FileName; 111 | u32 FirstSampleIndex; 112 | }; 113 | 114 | struct asset_source 115 | { 116 | asset_type Type; 117 | union 118 | { 119 | asset_source_bitmap Bitmap; 120 | asset_source_sound Sound; 121 | asset_source_font Font; 122 | asset_source_font_glyph Glyph; 123 | }; 124 | }; 125 | 126 | // TODO(casey): Are there larger numbers than 4096? Do we have evidence 127 | // in the natural world of things that can exist in quantities _larger_ than 4096? 128 | #define VERY_LARGE_NUMBER 4096 // NOTE(casey): 4096 should be enough for anybody 129 | 130 | struct game_assets 131 | { 132 | u32 TagCount; 133 | hha_tag Tags[VERY_LARGE_NUMBER]; 134 | 135 | u32 AssetTypeCount; 136 | hha_asset_type_v0 AssetTypes[Asset_Count]; 137 | 138 | u32 AssetCount; 139 | asset_source AssetSources[VERY_LARGE_NUMBER]; 140 | hha_asset Assets[VERY_LARGE_NUMBER]; 141 | 142 | hha_asset_type_v0 *DEBUGAssetType; 143 | u32 AssetIndex; 144 | }; 145 | 146 | #define TEST_ASSET_BUILDER_H 147 | #endif 148 | -------------------------------------------------------------------------------- /code/osx_handmade.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////// 2 | // osx_handmade.h 3 | // 4 | // Jeff Buck 5 | // Copyright 2014-2016. All Rights Reserved. 6 | // 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | //#import 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | //////////////////////////////////////////////////////////////////////// 32 | // Hot code reloading 33 | // 34 | 35 | //#define OSX_LOADED_CODE_ENTRY_POINT(name) b32x (void* DL, void* FunctionTable) 36 | //typedef OSX_LOADED_CODE_ENTRY_POINT(osx_loaded_code_entry_point); 37 | 38 | 39 | struct osx_loaded_code 40 | { 41 | b32x IsValid; 42 | u32 TempDLNumber; 43 | 44 | const char* TransientDLName; 45 | const char* DLFullPath; 46 | const char* LockFullPath; 47 | 48 | void* DL; 49 | time_t DLLastWriteTime; 50 | 51 | u32 FunctionCount; 52 | char** FunctionNames; 53 | void** Functions; 54 | }; 55 | 56 | 57 | struct osx_game_function_table 58 | { 59 | // IMPORTANT(casey): The callbacks can be 0! You must check before calling 60 | // (or check the IsValid in osx_loaded_code). 61 | game_update_and_render* UpdateAndRender; 62 | game_get_sound_samples* GetSoundSamples; 63 | debug_game_frame_end* DEBUGFrameEnd; 64 | }; 65 | 66 | 67 | global char* OSXGameFunctionTableNames[] = 68 | { 69 | "GameUpdateAndRender", 70 | "GameGetSoundSamples", 71 | "DEBUGGameFrameEnd", 72 | }; 73 | 74 | 75 | //////////////////////////////////////////////////////////////////////// 76 | // Audio 77 | // 78 | struct osx_sound_output 79 | { 80 | game_sound_output_buffer SoundBuffer; 81 | u32 SoundBufferSize; 82 | s16* CoreAudioBuffer; 83 | s16* ReadCursor; 84 | s16* WriteCursor; 85 | 86 | AudioStreamBasicDescription AudioDescriptor; 87 | AudioUnit AudioUnit; 88 | 89 | #if 0 90 | AudioQueueRef AudioQueue; 91 | AudioQueueBufferRef AudioBuffers[2]; 92 | bool32 RanAFrame; 93 | #endif 94 | }; 95 | 96 | 97 | void OSXInitCoreAudio(osx_sound_output* SoundOutput); 98 | void OSXStopCoreAudio(osx_sound_output* SoundOutput); 99 | 100 | 101 | //////////////////////////////////////////////////////////////////////// 102 | // Memory Blocks 103 | // 104 | enum osx_memory_block_flag 105 | { 106 | OSXMem_AllocatedDuringLooping = 0x1, 107 | OSXMem_FreedDuringLooping = 0x2 108 | }; 109 | 110 | struct osx_memory_block 111 | { 112 | platform_memory_block Block; 113 | 114 | osx_memory_block* Prev; 115 | osx_memory_block* Next; 116 | u64 LoopingFlags; 117 | u64 TotalAllocatedSize; 118 | 119 | u64 Pad[7]; 120 | }; 121 | 122 | 123 | struct osx_saved_memory_block 124 | { 125 | u64 BasePointer; 126 | u64 Size; 127 | }; 128 | 129 | 130 | //////////////////////////////////////////////////////////////////////// 131 | // Replay 132 | // 133 | struct osx_replay_buffer 134 | { 135 | char Filename[FILENAME_MAX]; 136 | }; 137 | 138 | 139 | struct osx_state 140 | { 141 | ticket_mutex MemoryMutex; 142 | osx_memory_block MemorySentinel; 143 | 144 | int RecordingHandle; 145 | int InputRecordingIndex; 146 | 147 | int PlaybackHandle; 148 | int InputPlayingIndex; 149 | 150 | char AppFilename[FILENAME_MAX]; 151 | char* OnePastLastAppFilenameSlash; 152 | }; 153 | 154 | 155 | //extern osx_state GlobalOSXState; 156 | 157 | 158 | #ifndef HANDMADE_USE_ASM_RDTSC 159 | // NOTE(jeff): Thanks to @visitect for this suggestion 160 | #define rdtsc __builtin_readcyclecounter 161 | #else 162 | internal inline uint64 163 | rdtsc() 164 | { 165 | u32 eax = 0; 166 | u32 edx; 167 | 168 | __asm__ __volatile__("cpuid;" 169 | "rdtsc;" 170 | : "+a" (eax), "=d" (edx) 171 | : 172 | : "%rcx", "%rbx", "memory"); 173 | 174 | __asm__ __volatile__("xorl %%eax, %%eax;" 175 | "cpuid;" 176 | : 177 | : 178 | : "%rax", "%rbx", "%rcx", "%rdx", "memory"); 179 | 180 | return (((u64)edx << 32) | eax); 181 | } 182 | #endif 183 | 184 | 185 | #if HANDMADE_INTERNAL 186 | DEBUG_PLATFORM_EXECUTE_SYSTEM_COMMAND(DEBUGExecuteSystemCommand); 187 | DEBUG_PLATFORM_GET_PROCESS_STATE(DEBUGGetProcessState); 188 | DEBUG_PLATFORM_GET_MEMORY_STATS(OSXGetMemoryStats); 189 | #endif 190 | 191 | 192 | struct osx_platform_file_group 193 | { 194 | memory_arena Memory; 195 | }; 196 | 197 | 198 | PLATFORM_GET_ALL_FILE_OF_TYPE_BEGIN(OSXGetAllFilesOfTypeBegin); 199 | PLATFORM_GET_ALL_FILE_OF_TYPE_END(OSXGetAllFilesOfTypeEnd); 200 | PLATFORM_OPEN_FILE(OSXOpenFile); 201 | PLATFORM_READ_DATA_FROM_FILE(OSXReadDataFromFile); 202 | PLATFORM_FILE_ERROR(OSXFileError); 203 | 204 | void OSXFreeMemoryBlock(osx_memory_block* Block); 205 | PLATFORM_ALLOCATE_MEMORY(OSXAllocateMemory); 206 | PLATFORM_DEALLOCATE_MEMORY(OSXDeallocateMemory); 207 | 208 | void* OSXSimpleAllocateMemory(umm Size); 209 | 210 | 211 | void OSXGetAppFilename(osx_state *State); 212 | 213 | void OSXBuildAppPathFilename(osx_state *State, const char *Filename, 214 | int DestCount, char *Dest); 215 | 216 | time_t OSXGetLastWriteTime(const char* Filename); 217 | float OSXGetSecondsElapsed(u64 Then, u64 Now); 218 | 219 | 220 | void OSXGetInputFileLocation(osx_state* State, bool32 InputStream, int SlotIndex, int DestCount, char* Dest); 221 | void OSXBeginRecordingInput(osx_state* State, int InputRecordingIndex); 222 | void OSXEndRecordingInput(osx_state* State); 223 | void OSXBeginInputPlayback(osx_state* State, int InputPlayingIndex); 224 | void OSXEndInputPlayback(osx_state* State); 225 | void OSXRecordInput(osx_state* State, game_input* NewInput); 226 | void OSXPlaybackInput(osx_state* State, game_input* NewInput); 227 | 228 | 229 | struct platform_work_queue_entry 230 | { 231 | platform_work_queue_callback* Callback; 232 | void* Data; 233 | }; 234 | 235 | 236 | struct platform_work_queue 237 | { 238 | u32 volatile CompletionGoal; 239 | u32 volatile CompletionCount; 240 | 241 | u32 volatile NextEntryToWrite; 242 | u32 volatile NextEntryToRead; 243 | dispatch_semaphore_t SemaphoreHandle; 244 | 245 | platform_work_queue_entry Entries[256]; 246 | 247 | b32 NeedsOpenGL; 248 | }; 249 | 250 | 251 | struct osx_thread_startup 252 | { 253 | //int LogicalThreadIndex; 254 | //CGLContextObj OpenGLContext; 255 | platform_work_queue *Queue; 256 | }; 257 | 258 | 259 | void OSXMakeQueue(platform_work_queue* Queue, uint32 ThreadCount); 260 | void OSXAddEntry(platform_work_queue* Queue, platform_work_queue_callback* Callback, void* Data); 261 | bool32 OSXDoNextWorkQueueEntry(platform_work_queue* Queue); 262 | void OSXCompleteAllWork(platform_work_queue *Queue); 263 | 264 | 265 | 266 | #define MAX_HID_BUTTONS 32 267 | 268 | typedef struct osx_game_data 269 | { 270 | // input 271 | IOHIDManagerRef HIDManager; 272 | int HIDX; 273 | int HIDY; 274 | u8 HIDButtons[MAX_HID_BUTTONS]; 275 | 276 | char SourceGameCodeDLFullPath[FILENAME_MAX]; 277 | char RendererCodeDLFullPath[FILENAME_MAX]; 278 | char CodeLockFullPath[FILENAME_MAX]; 279 | 280 | platform_renderer_limits Limits; 281 | platform_renderer* Renderer; 282 | 283 | game_input Input[2]; 284 | game_input* NewInput; 285 | game_input* OldInput; 286 | 287 | osx_game_function_table GameFunctions; 288 | osx_loaded_code GameCode; 289 | 290 | osx_renderer_function_table RendererFunctions; 291 | osx_loaded_code RendererCode; 292 | 293 | osx_sound_output SoundOutput; 294 | 295 | osx_thread_startup HighPriorityStartups[6]; 296 | platform_work_queue HighPriorityQueue; 297 | 298 | osx_thread_startup LowPriorityStartups[2]; 299 | platform_work_queue LowPriorityQueue; 300 | 301 | u32 MonitorRefreshHz; 302 | f32 GameUpdateHz; 303 | 304 | b32x RendererWasReloaded; 305 | u32 ExpectedFramesPerUpdate; 306 | 307 | u32 TargetFramesPerSecond; 308 | r32 TargetSecondsPerFrame; 309 | 310 | r64 MachTimebaseConversionFactor; 311 | int SetupComplete; 312 | 313 | int RenderAtHalfSpeed; 314 | 315 | u64 LastCounter; 316 | 317 | int RenderCommandsInitialized; 318 | game_render_commands RenderCommands; 319 | 320 | lighting_box* LightBoxes; 321 | 322 | u8 KeyboardState[255]; 323 | u8 OldKeyboardState[255]; 324 | 325 | v2u RenderDim; 326 | 327 | // Software Renderer: 328 | //game_offscreen_buffer RenderBuffer; 329 | 330 | // Old stuff to delete: 331 | //umm CurrentSortMemorySize; 332 | //void* SortMemory; 333 | 334 | //umm CurrentClipMemorySize; 335 | //void* ClipMemory; 336 | 337 | //texture_op TextureQueueMemory[512]; 338 | //u32 TextureOpCount; 339 | } osx_game_data; 340 | 341 | 342 | void OSXSetupGamepad(osx_game_data* game_data); 343 | 344 | void OSXUpdateGlobalDebugTable(); 345 | 346 | 347 | void OSXToggleGlobalPause(); 348 | 349 | b32 OSXIsGameRunning(); 350 | void OSXStopGame(); 351 | 352 | 353 | inline void OSXProcessKeyboardMessage(game_button_state* NewState, b32 IsDown) 354 | { 355 | if (NewState->EndedDown != IsDown) 356 | { 357 | NewState->EndedDown = IsDown; 358 | ++NewState->HalfTransitionCount; 359 | } 360 | } 361 | 362 | void OSXKeyProcessing(b32 IsDown, u32 KeyCode, u32 Key, 363 | int ShiftKeyFlag, int CommandKeyFlag, int ControlKeyFlag, int AlternateKeyFlag, 364 | game_input* Input, osx_game_data* GameData); 365 | 366 | inline b32x OSXIsInLoop(osx_state* State) 367 | { 368 | b32x Result = (State->InputRecordingIndex || State->InputPlayingIndex); 369 | return Result; 370 | } 371 | 372 | #if HANDMADE_INTERNAL 373 | #define OSXDebugLogOpenGLErrors(l) OSXDebugInternalLogOpenGLErrors(l) 374 | #else 375 | #define OSXDebugLogOpenGLErrors(l) {} 376 | #endif 377 | 378 | void OSXDebugInternalLogOpenGLErrors(const char* label); 379 | void OSXSetupSound(osx_game_data* GameData); 380 | void OSXSetupGameData(NSWindow* Window, osx_game_data* GameData); 381 | void OSXInitOpenGL(); 382 | void OSXSetupGameRenderBuffer(osx_game_data* GameData, float Width, float Height, int BytesPerPixel); 383 | 384 | void OSXInitializeGameInputForNewFrame(osx_game_data* GameData); 385 | 386 | struct osx_mouse_data; 387 | 388 | void OSXProcessFrameAndRunGameLogic(osx_game_data* GameData, CGRect WindowFrame, osx_mouse_data* MouseData); 389 | 390 | 391 | -------------------------------------------------------------------------------- /code/osx_handmade_audio.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /////////////////////////////////////////////////////////////////////// 5 | // Audio 6 | // 7 | #if 1 // Handmade Hero Sound Buffer 8 | OSStatus OSXAudioUnitCallback(void * inRefCon, 9 | AudioUnitRenderActionFlags * ioActionFlags, 10 | const AudioTimeStamp * inTimeStamp, 11 | UInt32 inBusNumber, 12 | UInt32 inNumberFrames, 13 | AudioBufferList * ioData) 14 | { 15 | // NOTE(jeff): Don't do anything too time consuming in this function. 16 | // It is a high-priority "real-time" thread. 17 | // Even too many printf calls can throw off the timing. 18 | #pragma unused(ioActionFlags) 19 | #pragma unused(inTimeStamp) 20 | #pragma unused(inBusNumber) 21 | 22 | //double currentPhase = *((double*)inRefCon); 23 | 24 | osx_sound_output* SoundOutput = ((osx_sound_output*)inRefCon); 25 | 26 | 27 | if (SoundOutput->ReadCursor == SoundOutput->WriteCursor) 28 | { 29 | SoundOutput->SoundBuffer.SampleCount = 0; 30 | //printf("AudioCallback: No Samples Yet!\n"); 31 | } 32 | 33 | //printf("AudioCallback: SampleCount = %d\n", SoundOutput->SoundBuffer.SampleCount); 34 | 35 | int SampleCount = inNumberFrames; 36 | if (SoundOutput->SoundBuffer.SampleCount < inNumberFrames) 37 | { 38 | SampleCount = SoundOutput->SoundBuffer.SampleCount; 39 | } 40 | 41 | int16* outputBufferL = (int16 *)ioData->mBuffers[0].mData; 42 | int16* outputBufferR = (int16 *)ioData->mBuffers[1].mData; 43 | 44 | for (UInt32 i = 0; i < SampleCount; ++i) 45 | { 46 | outputBufferL[i] = *SoundOutput->ReadCursor++; 47 | outputBufferR[i] = *SoundOutput->ReadCursor++; 48 | 49 | if ((char*)SoundOutput->ReadCursor >= (char*)((char*)SoundOutput->CoreAudioBuffer + SoundOutput->SoundBufferSize)) 50 | { 51 | //printf("Callback: Read cursor wrapped!\n"); 52 | SoundOutput->ReadCursor = SoundOutput->CoreAudioBuffer; 53 | } 54 | } 55 | 56 | for (UInt32 i = SampleCount; i < inNumberFrames; ++i) 57 | { 58 | outputBufferL[i] = 0.0; 59 | outputBufferR[i] = 0.0; 60 | } 61 | 62 | return noErr; 63 | } 64 | 65 | #else // Test Sine Wave 66 | 67 | OSStatus SineWaveRenderCallback(void * inRefCon, 68 | AudioUnitRenderActionFlags * ioActionFlags, 69 | const AudioTimeStamp * inTimeStamp, 70 | UInt32 inBusNumber, 71 | UInt32 inNumberFrames, 72 | AudioBufferList * ioData) 73 | { 74 | #pragma unused(ioActionFlags) 75 | #pragma unused(inTimeStamp) 76 | #pragma unused(inBusNumber) 77 | 78 | //double currentPhase = *((double*)inRefCon); 79 | 80 | osx_sound_output* SoundOutput = ((osx_sound_output*)inRefCon); 81 | 82 | int16* outputBuffer = (int16 *)ioData->mBuffers[0].mData; 83 | const double phaseStep = (SoundOutput->Frequency 84 | / SoundOutput->SoundBuffer.SamplesPerSecond) 85 | * (2.0 * M_PI); 86 | 87 | for (UInt32 i = 0; i < inNumberFrames; i++) 88 | { 89 | outputBuffer[i] = 5000 * sin(SoundOutput->RenderPhase); 90 | SoundOutput->RenderPhase += phaseStep; 91 | } 92 | 93 | // Copy to the stereo (or the additional X.1 channels) 94 | for(UInt32 i = 1; i < ioData->mNumberBuffers; i++) 95 | { 96 | memcpy(ioData->mBuffers[i].mData, outputBuffer, ioData->mBuffers[i].mDataByteSize); 97 | } 98 | 99 | return noErr; 100 | } 101 | 102 | OSStatus SilentCallback(void* inRefCon, 103 | AudioUnitRenderActionFlags* ioActionFlags, 104 | const AudioTimeStamp* inTimeStamp, 105 | UInt32 inBusNumber, 106 | UInt32 inNumberFrames, 107 | AudioBufferList* ioData) 108 | { 109 | #pragma unused(inRefCon) 110 | #pragma unused(ioActionFlags) 111 | #pragma unused(inTimeStamp) 112 | #pragma unused(inBusNumber) 113 | 114 | //double currentPhase = *((double*)inRefCon); 115 | //osx_sound_output* SoundOutput = ((osx_sound_output*)inRefCon); 116 | 117 | Float32* outputBuffer = (Float32 *)ioData->mBuffers[0].mData; 118 | 119 | for (UInt32 i = 0; i < inNumberFrames; i++) 120 | { 121 | outputBuffer[i] = 0.0; 122 | } 123 | 124 | // Copy to the stereo (or the additional X.1 channels) 125 | for(UInt32 i = 1; i < ioData->mNumberBuffers; i++) 126 | { 127 | memcpy(ioData->mBuffers[i].mData, outputBuffer, 128 | ioData->mBuffers[i].mDataByteSize); 129 | } 130 | 131 | return noErr; 132 | } 133 | #endif 134 | 135 | 136 | #if 0 // Use AudioQueues 137 | void OSXAudioQueueCallback(void* data, AudioQueueRef queue, AudioQueueBufferRef buffer) 138 | { 139 | osx_sound_output* SoundOutput = ((osx_sound_output*)data); 140 | 141 | int16* outputBuffer = (int16 *)ioData->mBuffers[0].mData; 142 | const double phaseStep = (SoundOutput->Frequency / SoundOutput->SamplesPerSecond) * (2.0 * M_PI); 143 | 144 | for (UInt32 i = 0; i < inNumberFrames; i++) 145 | { 146 | outputBuffer[i] = 5000 * sin(SoundOutput->RenderPhase); 147 | SoundOutput->RenderPhase += phaseStep; 148 | } 149 | 150 | // Copy to the stereo (or the additional X.1 channels) 151 | for(UInt32 i = 1; i < ioData->mNumberBuffers; i++) 152 | { 153 | memcpy(ioData->mBuffers[i].mData, outputBuffer, ioData->mBuffers[i].mDataByteSize); 154 | } 155 | } 156 | 157 | 158 | void OSXInitCoreAudio(osx_sound_output* SoundOutput) 159 | { 160 | SoundOutput->AudioDescriptor.mSampleRate = SoundOutput->SamplesPerSecond; 161 | SoundOutput->AudioDescriptor.mFormatID = kAudioFormatLinearPCM; 162 | SoundOutput->AudioDescriptor.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagIsPacked; 163 | SoundOutput->AudioDescriptor.mFramesPerPacket = 1; 164 | SoundOutput->AudioDescriptor.mChannelsPerFrame = 2; 165 | SoundOutput->AudioDescriptor.mBitsPerChannel = sizeof(int16) * 8; 166 | SoundOutput->AudioDescriptor.mBytesPerFrame = sizeof(int16); // don't multiply by channel count with non-interleaved! 167 | SoundOutput->AudioDescriptor.mBytesPerPacket = SoundOutput->AudioDescriptor.mFramesPerPacket * SoundOutput->AudioDescriptor.mBytesPerFrame; 168 | 169 | uint32 err = AudioQueueNewOutput(&SoundOutput->AudioDescriptor, OSXAudioQueueCallback, SoundOutput, NULL, 0, 0, &SoundOutput->AudioQueue); 170 | if (err) 171 | { 172 | printf("Error in AudioQueueNewOutput\n"); 173 | } 174 | 175 | } 176 | 177 | #else // Use raw AudioUnits 178 | 179 | void OSXInitCoreAudio(osx_sound_output* SoundOutput) 180 | { 181 | AudioComponentDescription acd; 182 | acd.componentType = kAudioUnitType_Output; 183 | acd.componentSubType = kAudioUnitSubType_DefaultOutput; 184 | acd.componentManufacturer = kAudioUnitManufacturer_Apple; 185 | 186 | AudioComponent outputComponent = AudioComponentFindNext(NULL, &acd); 187 | 188 | AudioComponentInstanceNew(outputComponent, &SoundOutput->AudioUnit); 189 | AudioUnitInitialize(SoundOutput->AudioUnit); 190 | 191 | #if 1 // uint16 192 | //AudioStreamBasicDescription asbd; 193 | SoundOutput->AudioDescriptor.mSampleRate = SoundOutput->SoundBuffer.SamplesPerSecond; 194 | SoundOutput->AudioDescriptor.mFormatID = kAudioFormatLinearPCM; 195 | SoundOutput->AudioDescriptor.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagIsPacked; 196 | SoundOutput->AudioDescriptor.mFramesPerPacket = 1; 197 | SoundOutput->AudioDescriptor.mChannelsPerFrame = 2; // Stereo 198 | SoundOutput->AudioDescriptor.mBitsPerChannel = sizeof(int16) * 8; 199 | SoundOutput->AudioDescriptor.mBytesPerFrame = sizeof(int16); // don't multiply by channel count with non-interleaved! 200 | SoundOutput->AudioDescriptor.mBytesPerPacket = SoundOutput->AudioDescriptor.mFramesPerPacket * SoundOutput->AudioDescriptor.mBytesPerFrame; 201 | #else // floating point - this is the "native" format on the Mac 202 | AudioStreamBasicDescription asbd; 203 | SoundOutput->AudioDescriptor.mSampleRate = SoundOutput->SamplesPerSecond; 204 | SoundOutput->AudioDescriptor.mFormatID = kAudioFormatLinearPCM; 205 | SoundOutput->AudioDescriptor.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; 206 | SoundOutput->AudioDescriptor.mFramesPerPacket = 1; 207 | SoundOutput->AudioDescriptor.mChannelsPerFrame = 2; 208 | SoundOutput->AudioDescriptor.mBitsPerChannel = sizeof(Float32) * 8; // 1 * sizeof(Float32) * 8; 209 | SoundOutput->AudioDescriptor.mBytesPerFrame = sizeof(Float32); 210 | SoundOutput->AudioDescriptor.mBytesPerPacket = SoundOutput->AudioDescriptor.mFramesPerPacket * SoundOutput->AudioDescriptor.mBytesPerFrame; 211 | #endif 212 | 213 | 214 | // TODO(jeff): Add some error checking... 215 | AudioUnitSetProperty(SoundOutput->AudioUnit, 216 | kAudioUnitProperty_StreamFormat, 217 | kAudioUnitScope_Input, 218 | 0, 219 | &SoundOutput->AudioDescriptor, 220 | sizeof(SoundOutput->AudioDescriptor)); 221 | 222 | AURenderCallbackStruct cb; 223 | cb.inputProc = OSXAudioUnitCallback; 224 | cb.inputProcRefCon = SoundOutput; 225 | 226 | AudioUnitSetProperty(SoundOutput->AudioUnit, 227 | kAudioUnitProperty_SetRenderCallback, 228 | kAudioUnitScope_Global, 229 | 0, 230 | &cb, 231 | sizeof(cb)); 232 | 233 | AudioOutputUnitStart(SoundOutput->AudioUnit); 234 | } 235 | 236 | 237 | void OSXStopCoreAudio(osx_sound_output* SoundOutput) 238 | { 239 | printf("Stopping Core Audio\n"); 240 | AudioOutputUnitStop(SoundOutput->AudioUnit); 241 | AudioUnitUninitialize(SoundOutput->AudioUnit); 242 | AudioComponentInstanceDispose(SoundOutput->AudioUnit); 243 | } 244 | 245 | #endif 246 | 247 | 248 | 249 | -------------------------------------------------------------------------------- /code/osx_handmade_cocoa.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////// 2 | // osx_handmade_cocoa.h 3 | // 4 | // Jeff Buck 5 | // Copyright 2014-2018. All Rights Reserved. 6 | // 7 | 8 | 9 | @class HandmadeAppDelegate; 10 | 11 | typedef struct osx_mouse_data 12 | { 13 | b32x MouseInWindowFlag; 14 | CGPoint MouseLocation; // in view coordinates 15 | u32 MouseButtonMask; 16 | } osx_mouse_data; 17 | 18 | 19 | struct OSXCocoaContext 20 | { 21 | HandmadeAppDelegate* AppDelegate; 22 | NSWindow* Window; 23 | NSString* AppName; 24 | NSString* WorkingDirectory; 25 | }; 26 | 27 | 28 | void OSXMessageBox(NSString* Title, NSString* Text); 29 | -------------------------------------------------------------------------------- /code/osx_handmade_cocoa.mm: -------------------------------------------------------------------------------- 1 | 2 | /////////////////////////////////////////////////////////////////////// 3 | // Application Delegate 4 | 5 | static v2 GlobalAspectRatio = {16.0, 9.0}; 6 | 7 | @interface HandmadeAppDelegate : NSObject 8 | @end 9 | 10 | @implementation HandmadeAppDelegate 11 | 12 | // app delegate methods 13 | - (void)applicationDidFinishLaunching:(id)sender 14 | { 15 | #pragma unused(sender) 16 | } 17 | 18 | 19 | - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)sender 20 | { 21 | #pragma unused(sender) 22 | 23 | return YES; 24 | } 25 | 26 | 27 | - (void)applicationWillTerminate:(NSApplication*)sender 28 | { 29 | #pragma unused(sender) 30 | } 31 | 32 | 33 | // window delegate methods 34 | - (NSSize)windowWillResize:(NSWindow*)window 35 | toSize:(NSSize)frameSize 36 | { 37 | // Maintain the proper aspect ratio... 38 | 39 | NSRect WindowRect = [window frame]; 40 | NSRect ContentRect = [window contentRectForFrameRect:WindowRect]; 41 | 42 | r32 WidthAdd = (WindowRect.size.width - ContentRect.size.width); 43 | r32 HeightAdd = (WindowRect.size.height - ContentRect.size.height); 44 | 45 | //r32 NewCy = (GlobalRenderHeight * (frameSize.width - WidthAdd)) / GlobalRenderWidth; 46 | r32 NewCy = (GlobalAspectRatio.Height * (frameSize.width - WidthAdd)) / GlobalAspectRatio.Width; 47 | 48 | frameSize.height = NewCy + HeightAdd; 49 | 50 | return frameSize; 51 | } 52 | 53 | - (void)windowWillClose:(id)sender 54 | { 55 | GlobalRunning = false; 56 | } 57 | 58 | @end 59 | 60 | // Application Delegate 61 | /////////////////////////////////////////////////////////////////////// 62 | 63 | 64 | void OSXCreateSimpleMainMenu(NSString* AppName) 65 | { 66 | NSMenu* menubar = [NSMenu new]; 67 | 68 | NSMenuItem* appMenuItem = [NSMenuItem new]; 69 | [menubar addItem:appMenuItem]; 70 | 71 | [NSApp setMainMenu:menubar]; 72 | 73 | NSMenu* appMenu = [NSMenu new]; 74 | 75 | [appMenu addItem:[[NSMenuItem alloc] initWithTitle:@"Enter Full Screen" 76 | action:@selector(toggleFullScreen:) 77 | keyEquivalent:@"f"]]; 78 | 79 | [appMenu addItem:[[NSMenuItem alloc] initWithTitle:[@"Quit " stringByAppendingString:AppName] 80 | action:@selector(terminate:) 81 | keyEquivalent:@"q"]]; 82 | [appMenuItem setSubmenu:appMenu]; 83 | } 84 | 85 | 86 | void OSXProcessMinimalPendingMessages() 87 | { 88 | NSEvent* Event; 89 | 90 | do 91 | { 92 | Event = [NSApp nextEventMatchingMask:NSEventMaskAny 93 | untilDate:nil 94 | inMode:NSDefaultRunLoopMode 95 | dequeue:YES]; 96 | 97 | switch ([Event type]) 98 | { 99 | case NSEventTypeKeyDown: 100 | case NSEventTypeKeyUp: 101 | { 102 | u32 KeyCode = [Event keyCode]; 103 | if (KeyCode == kVK_ANSI_Q) 104 | { 105 | GlobalRunning = false; 106 | } 107 | } break; 108 | 109 | default: 110 | [NSApp sendEvent:Event]; 111 | } 112 | } while (Event != nil); 113 | } 114 | 115 | 116 | 117 | OSXCocoaContext OSXInitCocoaContext(NSString* AppName, float WindowWidth, float WindowHeight) 118 | { 119 | OSXCocoaContext Context = {}; 120 | 121 | // Cocoa boilerplate startup code 122 | NSApplication* app = [NSApplication sharedApplication]; 123 | [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; 124 | 125 | // Set working directory 126 | NSString *dir = [[NSFileManager defaultManager] currentDirectoryPath]; 127 | 128 | NSFileManager* FileManager = [NSFileManager defaultManager]; 129 | Context.WorkingDirectory = [NSString stringWithFormat:@"%@/Contents/Resources", 130 | [[NSBundle mainBundle] bundlePath]]; 131 | if ([FileManager changeCurrentDirectoryPath:Context.WorkingDirectory] == NO) 132 | { 133 | Assert(0); 134 | } 135 | NSLog(@"working directory: %@", Context.WorkingDirectory); 136 | 137 | Context.AppDelegate = [[HandmadeAppDelegate alloc] init]; 138 | [app setDelegate:Context.AppDelegate]; 139 | 140 | [NSApp finishLaunching]; 141 | 142 | // Create the main application window 143 | NSRect ScreenRect = [[NSScreen mainScreen] frame]; 144 | 145 | NSRect InitialFrame = NSMakeRect((ScreenRect.size.width - WindowWidth) * 0.5, 146 | (ScreenRect.size.height - WindowHeight) * 0.5, 147 | WindowWidth, 148 | WindowHeight); 149 | 150 | NSWindow* Window = [[NSWindow alloc] initWithContentRect:InitialFrame 151 | styleMask:NSWindowStyleMaskTitled 152 | | NSWindowStyleMaskClosable 153 | | NSWindowStyleMaskMiniaturizable 154 | | NSWindowStyleMaskResizable 155 | backing:NSBackingStoreBuffered 156 | defer:NO]; 157 | 158 | [Window setBackgroundColor: NSColor.redColor]; 159 | [Window setDelegate:Context.AppDelegate]; 160 | 161 | NSView* CV = [Window contentView]; 162 | [CV setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; 163 | [CV setAutoresizesSubviews:YES]; 164 | 165 | [Window setMinSize:NSMakeSize(160, 90)]; 166 | [Window setTitle:AppName]; 167 | [Window makeKeyAndOrderFront:nil]; 168 | 169 | Context.Window = Window; 170 | Context.AppName = AppName; 171 | 172 | return Context; 173 | } 174 | 175 | 176 | osx_mouse_data OSXGetMouseData(OSXCocoaContext* AppContext) 177 | { 178 | osx_mouse_data MouseData = {}; 179 | 180 | NSWindow* Window = AppContext->Window; 181 | 182 | CGRect WindowFrame = [Window frame]; 183 | CGRect ContentViewFrame = [[Window contentView] frame]; 184 | 185 | CGPoint MouseLocationInScreen = [NSEvent mouseLocation]; 186 | 187 | // TODO(jeff): Should this be ContentViewFrame instead of WindowFrame??? 188 | MouseData.MouseInWindowFlag = NSPointInRect(MouseLocationInScreen, WindowFrame); 189 | 190 | if (MouseData.MouseInWindowFlag) 191 | { 192 | // We don't actually care what the mouse screen coordinates are, we just want the 193 | // coordinates relative to the content view 194 | NSRect RectInWindow = [Window convertRectFromScreen:NSMakeRect(MouseLocationInScreen.x, 195 | MouseLocationInScreen.y, 196 | 1, 1)]; 197 | NSPoint PointInWindow = RectInWindow.origin; 198 | MouseData.MouseLocation = [[Window contentView] convertPoint:PointInWindow fromView:nil]; 199 | } 200 | 201 | MouseData.MouseButtonMask = [NSEvent pressedMouseButtons]; 202 | 203 | return MouseData; 204 | } 205 | 206 | 207 | void OSXMessageBox(NSString* Title, NSString* Text) 208 | { 209 | NSAlert* MsgBox = [[NSAlert alloc] init]; 210 | [MsgBox addButtonWithTitle:@"Quit"]; 211 | [MsgBox setMessageText:Title]; 212 | [MsgBox setInformativeText:Text]; 213 | [MsgBox setAlertStyle:NSAlertStyleWarning]; 214 | 215 | [MsgBox runModal]; 216 | } 217 | -------------------------------------------------------------------------------- /code/osx_handmade_debug.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////// 2 | // osx_handmade_debug.cpp 3 | // 4 | // Jeff Buck 5 | // Copyright 2014-2016. All Rights Reserved. 6 | // 7 | 8 | #ifndef Assert 9 | 10 | #if HANDMADE_SLOW 11 | // TODO(casey): Complete assertion macro - don't worry everyone! 12 | #define Assert(Expression) if(!(Expression)) {*(int *)0 = 0;} 13 | #else 14 | #define Assert(Expression) 15 | #endif 16 | 17 | #endif 18 | 19 | 20 | float OSXGetSecondsElapsed(u64 Then, u64 Now) 21 | { 22 | static mach_timebase_info_data_t tb; 23 | 24 | u64 Elapsed = Now - Then; 25 | 26 | if (tb.denom == 0) 27 | { 28 | // First time we need to get the timebase 29 | mach_timebase_info(&tb); 30 | } 31 | 32 | u64 Nanos = Elapsed * tb.numer / tb.denom; 33 | float Result = (float)Nanos * 1.0E-9; 34 | 35 | return Result; 36 | } 37 | 38 | void OSXVerifyMemoryListIntegrity() 39 | { 40 | BeginTicketMutex(&GlobalOSXState.MemoryMutex); 41 | local_persist u32 FailCounter; 42 | 43 | osx_memory_block* Sentinel = &GlobalOSXState.MemorySentinel; 44 | 45 | for (osx_memory_block* SourceBlock = Sentinel->Next; 46 | SourceBlock != Sentinel; 47 | SourceBlock = SourceBlock->Next) 48 | { 49 | Assert(SourceBlock->Block.Size <= U32Max); 50 | } 51 | 52 | ++FailCounter; 53 | 54 | EndTicketMutex(&GlobalOSXState.MemoryMutex); 55 | } 56 | 57 | 58 | #if HANDMADE_INTERNAL 59 | DEBUG_PLATFORM_GET_MEMORY_STATS(OSXGetMemoryStats) 60 | { 61 | debug_platform_memory_stats Stats = {}; 62 | 63 | BeginTicketMutex(&GlobalOSXState.MemoryMutex); 64 | osx_memory_block* Sentinel = &GlobalOSXState.MemorySentinel; 65 | 66 | for (osx_memory_block* SourceBlock = Sentinel->Next; 67 | SourceBlock != Sentinel; 68 | SourceBlock = SourceBlock->Next) 69 | { 70 | Assert(SourceBlock->Block.Size <= U32Max); 71 | 72 | ++Stats.BlockCount; 73 | Stats.TotalSize += SourceBlock->Block.Size; 74 | Stats.TotalUsed += SourceBlock->Block.Used; 75 | } 76 | EndTicketMutex(&GlobalOSXState.MemoryMutex); 77 | 78 | return Stats; 79 | } 80 | #endif 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /code/osx_handmade_dylib.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////// 2 | // osx_handmade_dylib.cpp 3 | // 4 | // Jeff Buck 5 | // Copyright 2014-2016. All Rights Reserved. 6 | // 7 | 8 | void OSXUnloadCode(osx_loaded_code* Loaded) 9 | { 10 | if (Loaded->DL) 11 | { 12 | // TODO(casey): Currently, we never unload libraries, because 13 | // we may still be pointing to strings that are inside them 14 | // (despite our best efforts). Should we just make "never unload" 15 | // be the policy? 16 | // 17 | //dlclose(Loaded->DL); 18 | // 19 | Loaded->DL = 0; 20 | } 21 | 22 | Loaded->IsValid = false; 23 | ZeroArray(Loaded->FunctionCount, Loaded->Functions); 24 | } 25 | 26 | 27 | void OSXLoadCode(osx_state* State, osx_loaded_code* Loaded) 28 | { 29 | char TempDLName[FILENAME_MAX]; 30 | 31 | // Only do this if there is no lock file 32 | 33 | struct stat FileStat; 34 | int StatStatus = stat(Loaded->LockFullPath, &FileStat); 35 | 36 | if (StatStatus == -1) 37 | { 38 | Loaded->DLLastWriteTime = OSXGetLastWriteTime(Loaded->DLFullPath); 39 | 40 | for (u32 AttemptIndex = 0; 41 | AttemptIndex < 128; 42 | ++AttemptIndex) 43 | { 44 | OSXBuildAppPathFilename(State, Loaded->TransientDLName, ++Loaded->TempDLNumber, 45 | sizeof(TempDLName), TempDLName); 46 | 47 | if (Loaded->TempDLNumber >= 1024) 48 | { 49 | Loaded->TempDLNumber = 0; 50 | } 51 | 52 | if (OSXCopyFile(Loaded->DLFullPath, TempDLName) == 0) 53 | { 54 | break; 55 | } 56 | } 57 | 58 | Loaded->DL = dlopen(TempDLName, RTLD_LAZY|RTLD_GLOBAL); 59 | if (Loaded->DL) 60 | { 61 | printf("OSXLoadCode: loading %s successful\n", TempDLName); 62 | 63 | Loaded->IsValid = true; 64 | 65 | for (u32 FunctionIndex = 0; 66 | FunctionIndex < Loaded->FunctionCount; 67 | ++FunctionIndex) 68 | { 69 | void* Function = dlsym(Loaded->DL, Loaded->FunctionNames[FunctionIndex]); 70 | if (Function) 71 | { 72 | Loaded->Functions[FunctionIndex] = Function; 73 | } 74 | else 75 | { 76 | Loaded->IsValid = false; 77 | } 78 | } 79 | } 80 | else 81 | { 82 | printf("OSXLoadCode: error loading %s\n", TempDLName); 83 | } 84 | } 85 | 86 | if (!Loaded->IsValid) 87 | { 88 | OSXUnloadCode(Loaded); 89 | } 90 | } 91 | 92 | 93 | b32x OSXCheckForCodeChange(osx_loaded_code* Loaded) 94 | { 95 | b32x Result = false; 96 | 97 | time_t NewDLWriteTime = OSXGetLastWriteTime(Loaded->DLFullPath); 98 | if (NewDLWriteTime != Loaded->DLLastWriteTime) 99 | { 100 | Result = true; 101 | } 102 | 103 | return Result; 104 | } 105 | 106 | 107 | void OSXReloadCode(osx_state* OSXState, osx_loaded_code* Loaded) 108 | { 109 | OSXUnloadCode(Loaded); 110 | 111 | for (u32 LoadTryIndex = 0; 112 | !Loaded->IsValid && (LoadTryIndex < 100); 113 | ++LoadTryIndex) 114 | { 115 | OSXLoadCode(OSXState, Loaded); 116 | usleep(100); 117 | } 118 | } 119 | 120 | -------------------------------------------------------------------------------- /code/osx_handmade_events.h: -------------------------------------------------------------------------------- 1 | // NOTE(jeff): Originally from Carbon's Event.h 2 | 3 | /* 4 | * Summary: 5 | * Virtual keycodes 6 | * 7 | * Discussion: 8 | * These constants are the virtual keycodes defined originally in 9 | * Inside Mac Volume V, pg. V-191. They identify physical keys on a 10 | * keyboard. Those constants with "ANSI" in the name are labeled 11 | * according to the key position on an ANSI-standard US keyboard. 12 | * For example, kVK_ANSI_A indicates the virtual keycode for the key 13 | * with the letter 'A' in the US keyboard layout. Other keyboard 14 | * layouts may have the 'A' key label on a different physical key; 15 | * in this case, pressing 'A' will generate a different virtual 16 | * keycode. 17 | */ 18 | enum { 19 | kVK_ANSI_A = 0x00, 20 | kVK_ANSI_S = 0x01, 21 | kVK_ANSI_D = 0x02, 22 | kVK_ANSI_F = 0x03, 23 | kVK_ANSI_H = 0x04, 24 | kVK_ANSI_G = 0x05, 25 | kVK_ANSI_Z = 0x06, 26 | kVK_ANSI_X = 0x07, 27 | kVK_ANSI_C = 0x08, 28 | kVK_ANSI_V = 0x09, 29 | kVK_ANSI_B = 0x0B, 30 | kVK_ANSI_Q = 0x0C, 31 | kVK_ANSI_W = 0x0D, 32 | kVK_ANSI_E = 0x0E, 33 | kVK_ANSI_R = 0x0F, 34 | kVK_ANSI_Y = 0x10, 35 | kVK_ANSI_T = 0x11, 36 | kVK_ANSI_1 = 0x12, 37 | kVK_ANSI_2 = 0x13, 38 | kVK_ANSI_3 = 0x14, 39 | kVK_ANSI_4 = 0x15, 40 | kVK_ANSI_6 = 0x16, 41 | kVK_ANSI_5 = 0x17, 42 | kVK_ANSI_Equal = 0x18, 43 | kVK_ANSI_9 = 0x19, 44 | kVK_ANSI_7 = 0x1A, 45 | kVK_ANSI_Minus = 0x1B, 46 | kVK_ANSI_8 = 0x1C, 47 | kVK_ANSI_0 = 0x1D, 48 | kVK_ANSI_RightBracket = 0x1E, 49 | kVK_ANSI_O = 0x1F, 50 | kVK_ANSI_U = 0x20, 51 | kVK_ANSI_LeftBracket = 0x21, 52 | kVK_ANSI_I = 0x22, 53 | kVK_ANSI_P = 0x23, 54 | kVK_ANSI_L = 0x25, 55 | kVK_ANSI_J = 0x26, 56 | kVK_ANSI_Quote = 0x27, 57 | kVK_ANSI_K = 0x28, 58 | kVK_ANSI_Semicolon = 0x29, 59 | kVK_ANSI_Backslash = 0x2A, 60 | kVK_ANSI_Comma = 0x2B, 61 | kVK_ANSI_Slash = 0x2C, 62 | kVK_ANSI_N = 0x2D, 63 | kVK_ANSI_M = 0x2E, 64 | kVK_ANSI_Period = 0x2F, 65 | kVK_ANSI_Grave = 0x32, 66 | kVK_ANSI_KeypadDecimal = 0x41, 67 | kVK_ANSI_KeypadMultiply = 0x43, 68 | kVK_ANSI_KeypadPlus = 0x45, 69 | kVK_ANSI_KeypadClear = 0x47, 70 | kVK_ANSI_KeypadDivide = 0x4B, 71 | kVK_ANSI_KeypadEnter = 0x4C, 72 | kVK_ANSI_KeypadMinus = 0x4E, 73 | kVK_ANSI_KeypadEquals = 0x51, 74 | kVK_ANSI_Keypad0 = 0x52, 75 | kVK_ANSI_Keypad1 = 0x53, 76 | kVK_ANSI_Keypad2 = 0x54, 77 | kVK_ANSI_Keypad3 = 0x55, 78 | kVK_ANSI_Keypad4 = 0x56, 79 | kVK_ANSI_Keypad5 = 0x57, 80 | kVK_ANSI_Keypad6 = 0x58, 81 | kVK_ANSI_Keypad7 = 0x59, 82 | kVK_ANSI_Keypad8 = 0x5B, 83 | kVK_ANSI_Keypad9 = 0x5C 84 | }; 85 | 86 | /* keycodes for keys that are independent of keyboard layout*/ 87 | enum { 88 | kVK_Return = 0x24, 89 | kVK_Tab = 0x30, 90 | kVK_Space = 0x31, 91 | kVK_Delete = 0x33, 92 | kVK_Escape = 0x35, 93 | kVK_Command = 0x37, 94 | kVK_Shift = 0x38, 95 | kVK_CapsLock = 0x39, 96 | kVK_Option = 0x3A, 97 | kVK_Alternate = 0x3A, 98 | kVK_Control = 0x3B, 99 | kVK_RightCommand = 0x36, 100 | kVK_RightShift = 0x3C, 101 | kVK_RightOption = 0x3D, 102 | kVK_RightAlternate = 0x3D, 103 | kVK_RightControl = 0x3E, 104 | kVK_Function = 0x3F, 105 | kVK_F17 = 0x40, 106 | kVK_VolumeUp = 0x48, 107 | kVK_VolumeDown = 0x49, 108 | kVK_Mute = 0x4A, 109 | kVK_F18 = 0x4F, 110 | kVK_F19 = 0x50, 111 | kVK_F20 = 0x5A, 112 | kVK_F5 = 0x60, 113 | kVK_F6 = 0x61, 114 | kVK_F7 = 0x62, 115 | kVK_F3 = 0x63, 116 | kVK_F8 = 0x64, 117 | kVK_F9 = 0x65, 118 | kVK_F11 = 0x67, 119 | kVK_F13 = 0x69, 120 | kVK_F16 = 0x6A, 121 | kVK_F14 = 0x6B, 122 | kVK_F10 = 0x6D, 123 | kVK_F12 = 0x6F, 124 | kVK_F15 = 0x71, 125 | kVK_Help = 0x72, 126 | kVK_Home = 0x73, 127 | kVK_PageUp = 0x74, 128 | kVK_ForwardDelete = 0x75, 129 | kVK_F4 = 0x76, 130 | kVK_End = 0x77, 131 | kVK_F2 = 0x78, 132 | kVK_PageDown = 0x79, 133 | kVK_F1 = 0x7A, 134 | kVK_LeftArrow = 0x7B, 135 | kVK_RightArrow = 0x7C, 136 | kVK_DownArrow = 0x7D, 137 | kVK_UpArrow = 0x7E 138 | }; 139 | 140 | -------------------------------------------------------------------------------- /code/osx_handmade_file.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////// 2 | // osx_handmade_file.cpp 3 | // 4 | // Jeff Buck 5 | // Copyright 2014-2016. All Rights Reserved. 6 | // 7 | #include 8 | 9 | 10 | int 11 | OSXCopyFile(const char* From, const char* To) 12 | { 13 | copyfile_state_t s = copyfile_state_alloc(); 14 | int Result = copyfile(From, To, s, COPYFILE_ALL); 15 | copyfile_state_free(s); 16 | 17 | return Result; 18 | } 19 | 20 | 21 | void 22 | OSXGetAppFilename(osx_state *State) 23 | { 24 | // NOTE(casey): Never use MAX_PATH in code that is user-facing, because it 25 | // can be dangerous and lead to bad results. 26 | // 27 | pid_t PID = getpid(); 28 | int r = proc_pidpath(PID, State->AppFilename, sizeof(State->AppFilename)); 29 | 30 | if (r <= 0) 31 | { 32 | fprintf(stderr, "Error getting process path: pid %d: %s\n", PID, strerror(errno)); 33 | } 34 | else 35 | { 36 | printf("process pid: %d path: %s\n", PID, State->AppFilename); 37 | } 38 | 39 | State->OnePastLastAppFilenameSlash = State->AppFilename; 40 | for(char *Scan = State->AppFilename; 41 | *Scan; 42 | ++Scan) 43 | { 44 | if(*Scan == '/') 45 | { 46 | State->OnePastLastAppFilenameSlash = Scan + 1; 47 | } 48 | } 49 | } 50 | 51 | 52 | void 53 | OSXBuildAppPathFilename(osx_state* State, const char* Filename, u32 Unique, 54 | int DestCount, char* Dest) 55 | { 56 | string A = 57 | { 58 | (umm)(State->OnePastLastAppFilenameSlash - State->AppFilename), 59 | (u8*)State->AppFilename 60 | }; 61 | 62 | string B = WrapZ((char*)Filename); 63 | 64 | if (Unique == 0) 65 | { 66 | FormatString(DestCount, Dest, "%S%S", A, B); 67 | } 68 | else 69 | { 70 | FormatString(DestCount, Dest, "%S%d_%S", A, Unique, B); 71 | } 72 | } 73 | 74 | 75 | void 76 | OSXBuildAppPathFilename(osx_state* State, const char* Filename, 77 | int DestCount, char* Dest) 78 | { 79 | OSXBuildAppPathFilename(State, Filename, 0, DestCount, Dest); 80 | } 81 | 82 | 83 | #if HANDMADE_INTERNAL 84 | 85 | #if 0 86 | DEBUG_PLATFORM_FREE_FILE_MEMORY(DEBUGPlatformFreeFileMemory) 87 | { 88 | if (Memory) 89 | { 90 | free(Memory); 91 | } 92 | } 93 | 94 | 95 | DEBUG_PLATFORM_READ_ENTIRE_FILE(DEBUGPlatformReadEntireFile) 96 | { 97 | debug_read_file_result Result = {}; 98 | 99 | int fd = open(Filename, O_RDONLY); 100 | if (fd != -1) 101 | { 102 | struct stat fileStat; 103 | if (fstat(fd, &fileStat) == 0) 104 | { 105 | uint32 FileSize32 = fileStat.st_size; 106 | 107 | int result = -1; 108 | 109 | #if 1 110 | Result.Contents = (char*)malloc(FileSize32); 111 | if (Result.Contents) 112 | { 113 | result = 0; 114 | } 115 | #else 116 | kern_return_t kresult = vm_allocate((vm_map_t)mach_task_self(), 117 | (vm_address_t*)&Result.Contents, 118 | FileSize32, 119 | VM_FLAGS_ANYWHERE); 120 | 121 | if ((result == KERN_SUCCESS) && Result.Contents) 122 | { 123 | result = 0; 124 | } 125 | #endif 126 | 127 | if (result == 0) 128 | { 129 | ssize_t BytesRead; 130 | BytesRead = read(fd, Result.Contents, FileSize32); 131 | if (BytesRead == FileSize32) // should have read until EOF 132 | { 133 | Result.ContentsSize = FileSize32; 134 | } 135 | else 136 | { 137 | DEBUGPlatformFreeFileMemory(Result.Contents); 138 | Result.Contents = 0; 139 | } 140 | } 141 | else 142 | { 143 | printf("DEBUGPlatformReadEntireFile %s: vm_allocate error: %d: %s\n", 144 | Filename, errno, strerror(errno)); 145 | } 146 | } 147 | else 148 | { 149 | printf("DEBUGPlatformReadEntireFile %s: fstat error: %d: %s\n", 150 | Filename, errno, strerror(errno)); 151 | } 152 | 153 | close(fd); 154 | } 155 | else 156 | { 157 | printf("DEBUGPlatformReadEntireFile %s: open error: %d: %s\n", 158 | Filename, errno, strerror(errno)); 159 | } 160 | 161 | return Result; 162 | } 163 | 164 | 165 | DEBUG_PLATFORM_WRITE_ENTIRE_FILE(DEBUGPlatformWriteEntireFile) 166 | { 167 | bool32 Result = false; 168 | 169 | int fd = open(Filename, O_WRONLY | O_CREAT, 0644); 170 | if (fd != -1) 171 | { 172 | ssize_t BytesWritten = write(fd, Memory, MemorySize); 173 | Result = (BytesWritten == MemorySize); 174 | 175 | if (!Result) 176 | { 177 | // TODO(jeff): Logging 178 | } 179 | 180 | close(fd); 181 | } 182 | else 183 | { 184 | } 185 | 186 | return Result; 187 | } 188 | #endif 189 | 190 | #endif 191 | 192 | #if 0 193 | internal platform_file_info* 194 | OSXAllocateFileInfo(platform_file_group* FileGroup, struct stat* FileStat) 195 | { 196 | osx_platform_file_group* OSXFileGroup = (osx_platform_file_group*)FileGroup->Platform; 197 | 198 | platform_file_info* Info = PushStruct(&OSXFileGroup->Memory, platform_file_info); 199 | Info->Next = FileGroup->FirstFileInfo; 200 | Info->FileDate = FileStat->st_mtimespec.tv_sec; 201 | Info->FileSize = FileStat->st_size; 202 | FileGroup->FirstFileInfo = Info; 203 | ++FileGroup->FileCount; 204 | 205 | return Info; 206 | } 207 | #endif 208 | 209 | PLATFORM_GET_ALL_FILE_OF_TYPE_BEGIN(OSXGetAllFilesOfTypeBegin) 210 | { 211 | platform_file_group Result = {}; 212 | 213 | osx_platform_file_group* OSXFileGroup = BootstrapPushStruct(osx_platform_file_group, Memory); 214 | Result.Platform = OSXFileGroup; 215 | 216 | const char* Stem = ""; 217 | const char* WildCard = "*.*"; 218 | 219 | switch (Type) 220 | { 221 | case PlatformFileType_AssetFile: 222 | { 223 | Stem = "data/"; 224 | WildCard = "data/*.hha"; 225 | } break; 226 | 227 | case PlatformFileType_SavedGameFile: 228 | { 229 | Stem = "data/"; 230 | WildCard = "data/*.hhs"; 231 | } break; 232 | 233 | case PlatformFileType_HHT: 234 | { 235 | Stem = "tags/"; 236 | WildCard = "tags/*.hht"; 237 | } break; 238 | 239 | case PlatformFileType_Dump: 240 | { 241 | Stem = "debug/"; 242 | WildCard = "debug/*.dump"; 243 | } break; 244 | 245 | InvalidDefaultCase; 246 | } 247 | 248 | u32 StemSize = 0; 249 | for (const char* Scan = Stem; *Scan; ++Scan) 250 | { 251 | ++StemSize; 252 | } 253 | 254 | glob_t GlobResults; 255 | 256 | if (glob(WildCard, 0, 0, &GlobResults) == 0) 257 | { 258 | Result.FileCount = GlobResults.gl_pathc; 259 | 260 | for (u32 CurrentIndex = 0; CurrentIndex < Result.FileCount; ++CurrentIndex) 261 | { 262 | const char* GlobFilename = *(GlobResults.gl_pathv + CurrentIndex); 263 | 264 | struct stat FileStat; 265 | int StatStatus = stat(GlobFilename, &FileStat); 266 | assert(StatStatus == 0); 267 | 268 | platform_file_info* Info = PushStruct(&OSXFileGroup->Memory, platform_file_info); 269 | 270 | Info->Next = Result.FirstFileInfo; 271 | Info->FileDate = FileStat.st_mtimespec.tv_sec; 272 | Info->FileSize = FileStat.st_size; 273 | 274 | const char* BaseNameBegin = GlobFilename; 275 | const char* BaseNameEnd = 0; 276 | const char* Scan = BaseNameBegin; 277 | 278 | while (*Scan) 279 | { 280 | if (Scan[0] == '/') 281 | { 282 | BaseNameBegin = Scan + 1; 283 | } 284 | 285 | if (Scan[0] == '.') 286 | { 287 | BaseNameEnd = Scan; 288 | } 289 | 290 | ++Scan; 291 | } 292 | 293 | if (!BaseNameEnd) 294 | { 295 | BaseNameEnd = Scan; 296 | } 297 | 298 | u32 BaseNameSize = (u32)(BaseNameEnd - BaseNameBegin); 299 | Info->BaseName = PushAndNullTerminate(&OSXFileGroup->Memory, BaseNameSize, (char*)BaseNameBegin); 300 | 301 | for (char* Lower = Info->BaseName; *Lower; ++Lower) 302 | { 303 | *Lower = ToLowercase(*Lower); 304 | } 305 | 306 | Info->Platform = PushStringZ(&OSXFileGroup->Memory, (char*)GlobFilename); 307 | 308 | Result.FirstFileInfo = Info; 309 | } 310 | } 311 | 312 | globfree(&GlobResults); 313 | 314 | return Result; 315 | } 316 | 317 | 318 | PLATFORM_GET_ALL_FILE_OF_TYPE_END(OSXGetAllFilesOfTypeEnd) 319 | { 320 | osx_platform_file_group* OSXFileGroup = (osx_platform_file_group*)FileGroup->Platform; 321 | 322 | if (OSXFileGroup) 323 | { 324 | Clear(&OSXFileGroup->Memory); 325 | } 326 | } 327 | 328 | 329 | internal PLATFORM_GET_FILE_BY_PATH(OSXGetFileByPath) 330 | { 331 | osx_platform_file_group* OSXFileGroup = (osx_platform_file_group*)FileGroup->Platform; 332 | platform_file_info* Result = 0; 333 | 334 | struct stat FileStat; 335 | int StatStatus = stat(Path, &FileStat); 336 | 337 | if ((StatStatus == 0) || (ModeFlags & OpenFile_Write)) 338 | { 339 | Result = PushStruct(&OSXFileGroup->Memory, platform_file_info); 340 | Result->Next = FileGroup->FirstFileInfo; 341 | Result->FileDate = FileStat.st_mtimespec.tv_sec; 342 | Result->FileSize = FileStat.st_size; 343 | FileGroup->FirstFileInfo = Result; 344 | ++FileGroup->FileCount; 345 | 346 | Result->BaseName = PushStringZ(&OSXFileGroup->Memory, Path); 347 | Result->Platform = PushStringZ(&OSXFileGroup->Memory, Path); 348 | } 349 | 350 | return Result; 351 | } 352 | 353 | 354 | PLATFORM_OPEN_FILE(OSXOpenFile) 355 | { 356 | //osx_platform_file_group* OSXFileGroup = (osx_platform_file_group*)FileGroup->Platform; 357 | platform_file_handle Result = {}; 358 | 359 | int FileOpenFlags = 0; 360 | 361 | if (ModeFlags & OpenFile_Write) 362 | { 363 | FileOpenFlags |= O_RDWR; 364 | FileOpenFlags |= O_CREAT; 365 | } 366 | else 367 | { 368 | FileOpenFlags |= O_RDONLY; 369 | } 370 | 371 | const char* Filename = (const char*)Info->Platform; 372 | 373 | int OSXFileHandle = open(Filename, FileOpenFlags, 0600); 374 | Result.NoErrors = (OSXFileHandle != -1); 375 | *(int*)&Result.Platform = OSXFileHandle; 376 | 377 | if (OSXFileHandle != -1) 378 | { 379 | if (ModeFlags & OpenFile_Read) 380 | { 381 | printf("Loading asset %s\n", Filename); 382 | } 383 | } 384 | else 385 | { 386 | printf("Error opening asset file |%s|: %d\n", Filename, errno); 387 | perror(NULL); 388 | } 389 | 390 | return Result; 391 | } 392 | 393 | 394 | PLATFORM_READ_DATA_FROM_FILE(OSXReadDataFromFile) 395 | { 396 | if (PlatformNoFileErrors(Handle)) 397 | { 398 | int OSXFileHandle = *(int*)&Handle->Platform; 399 | 400 | // TODO(jeff): Consider mmap instead of open/read for overlapped IO. 401 | // TODO(jeff): If sticking with read, make sure to handle interrupted read. 402 | 403 | u64 BytesRead = pread(OSXFileHandle, Dest, Size, Offset); 404 | 405 | if (BytesRead == Size) 406 | { 407 | // NOTE(jeff): File read succeeded 408 | //printf("Read file: %s read %ld bytes.\n", OSXFileHandle->Filename, BytesRead); 409 | } 410 | else 411 | { 412 | printf("OSXReadDataFromFile: Requested read of %llu bytes. Actual read of %llu bytes.\n", 413 | Size, BytesRead); 414 | 415 | OSXFileError(Handle, "Read file failed."); 416 | } 417 | } 418 | else 419 | { 420 | printf("OSXReadDataFromFile had pre-existing file errors\n"); 421 | } 422 | } 423 | 424 | 425 | PLATFORM_WRITE_DATA_TO_FILE(OSXWriteDataToFile) 426 | { 427 | if (PlatformNoFileErrors(Handle)) 428 | { 429 | int OSXFileHandle = *(int*)&Handle->Platform; 430 | 431 | u64 BytesWritten = pwrite(OSXFileHandle, Source, Size, Offset); 432 | 433 | if (BytesWritten == Size) 434 | { 435 | // NOTE(jeff): File read succeeded 436 | //printf("Wrote file: %s wrote %ld bytes.\n", OSXFileHandle->Filename, BytesWritten); 437 | } 438 | else 439 | { 440 | printf("OSXWriteDataToFile: Requested read of %llu bytes. Actual read of %llu bytes.\n", 441 | Size, BytesWritten); 442 | 443 | OSXFileError(Handle, "Write file failed."); 444 | } 445 | } 446 | else 447 | { 448 | printf("OSXWriteDataToFile had pre-existing file errors\n"); 449 | } 450 | } 451 | 452 | 453 | PLATFORM_ATOMIC_REPLACE_FILE_CONTENTS(OSXAtomicReplaceFileContents) 454 | { 455 | b32 Result = false; 456 | 457 | char* ExistingFilename = (char*)Info->Platform; 458 | char* LastSlash = ExistingFilename; 459 | for (char* Scan = ExistingFilename; *Scan; ++Scan) 460 | { 461 | if (*Scan == '/') 462 | { 463 | LastSlash = Scan; 464 | } 465 | } 466 | 467 | char TempFilename[FILENAME_MAX + 1]; 468 | *LastSlash = 0; // Temporarily null-terminate the path 469 | snprintf(TempFilename, sizeof(TempFilename), "%s/hh_XXXXXXXX", ExistingFilename); 470 | *LastSlash = '/'; 471 | 472 | int OSXTempFileHandle = mkstemp(TempFilename); 473 | 474 | printf("AtomicReplaceFileContents: ExistingFilename = %s\n", ExistingFilename); 475 | printf("AtomicReplaceFileContents: TempFilename = %s\n", TempFilename); 476 | 477 | if (OSXTempFileHandle > 0) 478 | { 479 | u64 BytesWritten = pwrite(OSXTempFileHandle, Source, Size, 0); 480 | close(OSXTempFileHandle); 481 | 482 | if (BytesWritten == Size) 483 | { 484 | //printf("Wrote file: %s wrote %ld bytes.\n", TempFilename, BytesWritten); 485 | 486 | // renamex_np atomically swaps the files 487 | if (renamex_np(TempFilename, ExistingFilename, RENAME_SWAP) == 0) 488 | { 489 | printf("AtomicReplaceFileContents: rename succeeded.\n"); 490 | Result = true; 491 | } 492 | else 493 | { 494 | printf("AtomicReplaceFileContents: rename(%s, %s) failed: %d.\n", 495 | TempFilename, ExistingFilename, errno); 496 | } 497 | } 498 | else 499 | { 500 | printf("AtomicReplaceFileContents write to temp file %s failed: %d.\n", TempFilename, errno); 501 | } 502 | 503 | // Delete the temp file in either case 504 | unlink(TempFilename); 505 | } 506 | 507 | return Result; 508 | } 509 | 510 | 511 | PLATFORM_CLOSE_FILE(OSXCloseFile) 512 | { 513 | int OSXFileHandle = *(int*)&Handle->Platform; 514 | 515 | if (OSXFileHandle != -1) 516 | { 517 | close(OSXFileHandle); 518 | } 519 | } 520 | 521 | 522 | PLATFORM_FILE_ERROR(OSXFileError) 523 | { 524 | #if HANDMADE_INTERNAL 525 | char buffer[256]; 526 | snprintf(buffer, sizeof(buffer), "OSX FILE ERROR: %s\n", Message); 527 | #endif 528 | 529 | Handle->NoErrors = false; 530 | } 531 | 532 | 533 | PLATFORM_SET_FILE_SIZE(OSXSetFileSize) 534 | { 535 | 536 | if (PlatformNoFileErrors(Handle)) 537 | { 538 | int OSXFileHandle = *(int*)&Handle->Platform; 539 | if (ftruncate(OSXFileHandle, Size) != 0) 540 | { 541 | OSXFileError(Handle, "Unable to set the end of the file.\n"); 542 | } 543 | } 544 | } 545 | 546 | 547 | time_t 548 | OSXGetLastWriteTime(const char* Filename) 549 | { 550 | time_t LastWriteTime = 0; 551 | 552 | struct stat FileStat; 553 | if (stat(Filename, &FileStat) == 0) 554 | { 555 | LastWriteTime = FileStat.st_mtimespec.tv_sec; 556 | } 557 | 558 | return LastWriteTime; 559 | } 560 | 561 | -------------------------------------------------------------------------------- /code/osx_handmade_hid.cpp: -------------------------------------------------------------------------------- 1 | 2 | /////////////////////////////////////////////////////////////////////// 3 | // HID input 4 | // 5 | 6 | 7 | #define OSX_HANDMADE_MAX_HID_DEVICES 32 8 | #define OSX_HANDMADE_MAX_HID_DEVICE_ELEMENTS 256 9 | 10 | #define OSX_HANDMADE_MAX_HID_MANUFACTURER_LEN 256 11 | #define OSX_HANDMADE_MAX_HID_PRODUCT_LEN 256 12 | 13 | 14 | typedef struct osx_hid_element 15 | { 16 | IOHIDElementRef ElementRef; 17 | IOHIDElementCookie Cookie; 18 | long Type; 19 | long Page; 20 | long Usage; 21 | long Min; 22 | long Max; 23 | } osx_hid_element; 24 | 25 | 26 | typedef struct osx_hid_device 27 | { 28 | IOHIDDeviceRef DeviceRef; 29 | 30 | osx_game_data* GameData; 31 | 32 | char Manufacturer[OSX_HANDMADE_MAX_HID_MANUFACTURER_LEN]; 33 | char Product[OSX_HANDMADE_MAX_HID_PRODUCT_LEN]; 34 | 35 | int ElementCount; 36 | osx_hid_element Elements[OSX_HANDMADE_MAX_HID_DEVICE_ELEMENTS]; 37 | } osx_hid_device; 38 | 39 | 40 | static osx_hid_device* HIDDevices[OSX_HANDMADE_MAX_HID_DEVICES]; 41 | static int HIDDeviceCount = 0; 42 | 43 | 44 | void OSXHIDElementInitialize(osx_hid_element* Element, 45 | IOHIDElementCookie Cookie, 46 | long Type, long Page, long Usage, long Min, long Max) 47 | { 48 | Element->Cookie = Cookie; 49 | Element->Type = Type; 50 | Element->Page = Page; 51 | Element->Usage = Usage; 52 | Element->Min = Min; 53 | Element->Max = Max; 54 | } 55 | 56 | 57 | osx_hid_device* OSXHIDDeviceCreate(IOHIDDeviceRef DeviceRef, 58 | const char* Manufacturer, 59 | const char* Product, 60 | osx_game_data* GameData) 61 | { 62 | Assert(HIDDeviceCount < (OSX_HANDMADE_MAX_HID_DEVICES - 1)); 63 | 64 | osx_hid_device* Device = (osx_hid_device*)malloc(sizeof(osx_hid_device)); 65 | 66 | Device->DeviceRef = DeviceRef; 67 | 68 | strncpy(Device->Manufacturer, Manufacturer, OSX_HANDMADE_MAX_HID_MANUFACTURER_LEN); 69 | strncpy(Device->Product, Product, OSX_HANDMADE_MAX_HID_PRODUCT_LEN); 70 | 71 | Device->ElementCount = 0; 72 | 73 | Device->GameData = GameData; 74 | 75 | HIDDevices[HIDDeviceCount++] = Device; 76 | 77 | return Device; 78 | } 79 | 80 | 81 | 82 | 83 | 84 | void OSXHIDAction(void* Context, IOReturn Result, void* Sender, IOHIDValueRef Value) 85 | { 86 | #pragma unused(Result) 87 | #pragma unused(Sender) 88 | 89 | osx_hid_device* Device = (osx_hid_device*)Context; 90 | 91 | // NOTE(jeff): Check suggested by Filip to prevent an access violation when 92 | // using a PS3 controller. 93 | // TODO(jeff): Investigate this further... 94 | if (IOHIDValueGetLength(Value) > 2) 95 | { 96 | //printf("OSXHIDAction: value length > 2: %ld\n", IOHIDValueGetLength(value)); 97 | return; 98 | } 99 | 100 | IOHIDElementRef ElementRef = IOHIDValueGetElement(Value); 101 | /* 102 | if (CFGetTypeID(ElementRef) != IOHIDElementGetTypeID()) 103 | { 104 | return; 105 | } 106 | */ 107 | 108 | IOHIDElementCookie Cookie = IOHIDElementGetCookie(ElementRef); 109 | int UsagePage = IOHIDElementGetUsagePage(ElementRef); 110 | int Usage = IOHIDElementGetUsage(ElementRef); 111 | 112 | int ElementValue = IOHIDValueGetIntegerValue(Value); 113 | 114 | 115 | osx_game_data* GameData = Device->GameData; 116 | 117 | osx_hid_element* Element = NULL; 118 | 119 | for (int i = 0; i < Device->ElementCount; ++i) 120 | { 121 | if (Device->Elements[i].Cookie == Cookie) 122 | { 123 | Element = &(Device->Elements[i]); 124 | break; 125 | } 126 | } 127 | 128 | if (Element == NULL) 129 | { 130 | printf("Could not find matching element for device\n"); 131 | return; 132 | } 133 | else 134 | { 135 | #if 0 136 | printf("HID Event: Cookie: %ld Page/Usage = %ld/%ld Min/Max = %ld/%ld Value = %d\n", 137 | (long)Element->Cookie, 138 | Element->Page, 139 | Element->Usage, 140 | Element->Min, 141 | Element->Max, 142 | ElementValue); 143 | #endif 144 | } 145 | 146 | // NOTE(jeff): This is just for reference. From the USB HID Usage Tables spec: 147 | // Usage Pages: 148 | // 1 - Generic Desktop (mouse, joystick) 149 | // 2 - Simulation Controls 150 | // 3 - VR Controls 151 | // 4 - Sports Controls 152 | // 5 - Game Controls 153 | // 6 - Generic Device Controls (battery, wireless, security code) 154 | // 7 - Keyboard/Keypad 155 | // 8 - LED 156 | // 9 - Button 157 | // A - Ordinal 158 | // B - Telephony 159 | // C - Consumer 160 | // D - Digitizers 161 | // 10 - Unicode 162 | // 14 - Alphanumeric Display 163 | // 40 - Medical Instrument 164 | 165 | if (UsagePage == 1) // Generic Desktop Page 166 | { 167 | int HatDelta = 16; 168 | 169 | float NormalizedValue = 0.0; 170 | if (Element->Max != Element->Min) 171 | { 172 | NormalizedValue = (float)(ElementValue - Element->Min) / (float)(Element->Max - Element->Min); 173 | } 174 | float ScaledMin = -25.0; 175 | float ScaledMax = 25.0; 176 | 177 | int ScaledValue = ScaledMin + NormalizedValue * (ScaledMax - ScaledMin); 178 | 179 | //printf("page:usage = %d:%d value = %ld ", usagePage, usage, elementValue); 180 | switch(Usage) 181 | { 182 | case 0x30: // x 183 | GameData->HIDX = ScaledValue; 184 | //printf("[x] scaled = %d\n", view->_HIDX); 185 | break; 186 | 187 | case 0x31: // y 188 | GameData->HIDY = ScaledValue; 189 | //printf("[y] scaled = %d\n", view->_HIDY); 190 | break; 191 | 192 | case 0x32: // z 193 | //GameData->HIDX = ScaledValue; 194 | //printf("[z] scaled = %d\n", view->_HIDX); 195 | break; 196 | 197 | case 0x35: // rz 198 | //GameData->HIDY = ScaledValue; 199 | //printf("[rz] scaled = %d\n", view->_HIDY); 200 | break; 201 | 202 | case 0x39: // Hat 0 = up, 2 = right, 4 = down, 6 = left, 8 = centered 203 | { 204 | game_controller_input* Controller = &GameData->NewInput->Controllers[0]; 205 | 206 | OSXProcessKeyboardMessage(&Controller->MoveUp, 0); 207 | OSXProcessKeyboardMessage(&Controller->MoveDown, 0); 208 | OSXProcessKeyboardMessage(&Controller->MoveLeft, 0); 209 | OSXProcessKeyboardMessage(&Controller->MoveRight, 0); 210 | 211 | //printf("[hat] "); 212 | switch(ElementValue) 213 | { 214 | case 0: 215 | GameData->HIDX = 0; 216 | GameData->HIDY = -HatDelta; 217 | OSXProcessKeyboardMessage(&Controller->MoveUp, 1); 218 | //printf("n\n"); 219 | break; 220 | 221 | case 1: 222 | GameData->HIDX = HatDelta; 223 | GameData->HIDY = -HatDelta; 224 | OSXProcessKeyboardMessage(&Controller->MoveUp, 1); 225 | OSXProcessKeyboardMessage(&Controller->MoveRight, 1); 226 | //printf("ne\n"); 227 | break; 228 | 229 | case 2: 230 | GameData->HIDX = HatDelta; 231 | GameData->HIDY = 0; 232 | OSXProcessKeyboardMessage(&Controller->MoveRight, 1); 233 | //printf("e\n"); 234 | break; 235 | 236 | case 3: 237 | GameData->HIDX = HatDelta; 238 | GameData->HIDY = HatDelta; 239 | OSXProcessKeyboardMessage(&Controller->MoveRight, 1); 240 | OSXProcessKeyboardMessage(&Controller->MoveDown, 1); 241 | //printf("se\n"); 242 | break; 243 | 244 | case 4: 245 | GameData->HIDX = 0; 246 | GameData->HIDY = HatDelta; 247 | OSXProcessKeyboardMessage(&Controller->MoveDown, 1); 248 | //printf("s\n"); 249 | break; 250 | 251 | case 5: 252 | GameData->HIDX = -HatDelta; 253 | GameData->HIDY = HatDelta; 254 | OSXProcessKeyboardMessage(&Controller->MoveDown, 1); 255 | OSXProcessKeyboardMessage(&Controller->MoveLeft, 1); 256 | //printf("sw\n"); 257 | break; 258 | 259 | case 6: 260 | GameData->HIDX = -HatDelta; 261 | GameData->HIDY = 0; 262 | OSXProcessKeyboardMessage(&Controller->MoveLeft, 1); 263 | //printf("w\n"); 264 | break; 265 | 266 | case 7: 267 | GameData->HIDX = -HatDelta; 268 | GameData->HIDY = -HatDelta; 269 | OSXProcessKeyboardMessage(&Controller->MoveLeft, 1); 270 | OSXProcessKeyboardMessage(&Controller->MoveUp, 1); 271 | //printf("nw\n"); 272 | break; 273 | 274 | case 8: 275 | GameData->HIDX = 0; 276 | GameData->HIDY = 0; 277 | //printf("up\n"); 278 | break; 279 | } 280 | 281 | } break; 282 | 283 | default: 284 | break; 285 | } 286 | } 287 | else if (UsagePage == 9) // Buttons 288 | { 289 | game_controller_input* Controller = &GameData->NewInput->Controllers[0]; 290 | 291 | if ((ElementValue == 0) || (ElementValue == 1)) 292 | { 293 | GameData->HIDButtons[Usage] = ElementValue; 294 | 295 | switch(Usage) 296 | { 297 | case 1: 298 | OSXProcessKeyboardMessage(&Controller->ActionLeft, ElementValue); 299 | break; 300 | 301 | case 2: 302 | OSXProcessKeyboardMessage(&Controller->ActionDown, ElementValue); 303 | break; 304 | 305 | case 3: 306 | OSXProcessKeyboardMessage(&Controller->ActionRight, ElementValue); 307 | break; 308 | 309 | case 4: 310 | OSXProcessKeyboardMessage(&Controller->ActionUp, ElementValue); 311 | break; 312 | 313 | case 6: 314 | Controller->ClutchMax = ElementValue ? 1.0 : 0.0; 315 | break; 316 | 317 | case 9: 318 | OSXProcessKeyboardMessage(&Controller->Back, ElementValue); 319 | break; 320 | 321 | case 10: 322 | OSXProcessKeyboardMessage(&Controller->Start, ElementValue); 323 | break; 324 | 325 | default: 326 | break; 327 | } 328 | } 329 | else 330 | { 331 | printf("Gamepad Element: Cookie: %ld Page: %d Usage: %d Value: %d _HIDX: %d\n", 332 | (long)Cookie, UsagePage, Usage, ElementValue, GameData->HIDX); 333 | } 334 | } 335 | else if (UsagePage == 7) // Keyboard 336 | { 337 | // NOTE(jeff): Moved to main loop event processing... 338 | } 339 | else 340 | { 341 | //printf("Gamepad Element: %@ Type: %d Page: %d Usage: %d Name: %@ Cookie: %i Value: %ld _HIDX: %d\n", 342 | // element, type, usagePage, usage, name, cookie, elementValue, GameData->HIDX); 343 | } 344 | } 345 | 346 | 347 | 348 | 349 | void OSXHIDAdded(void* Context, IOReturn Result, void* Sender, IOHIDDeviceRef DeviceRef) 350 | { 351 | #pragma unused(Result) 352 | #pragma unused(Sender) 353 | 354 | osx_game_data* GameData = (osx_game_data*)Context; 355 | 356 | CFStringRef ManufacturerCFSR = (CFStringRef)IOHIDDeviceGetProperty(DeviceRef, CFSTR(kIOHIDManufacturerKey)); 357 | CFStringRef ProductCFSR = (CFStringRef)IOHIDDeviceGetProperty(DeviceRef, CFSTR(kIOHIDProductKey)); 358 | 359 | const char* Manufacturer = CFStringGetCStringPtr(ManufacturerCFSR, kCFStringEncodingMacRoman); 360 | const char* Product = CFStringGetCStringPtr(ProductCFSR, kCFStringEncodingMacRoman); 361 | 362 | if (Manufacturer == NULL) Manufacturer = "[unknown]"; 363 | if (Product == NULL) Product = "[unknown]"; 364 | 365 | printf("Gamepad was detected: %s %s", Manufacturer, Product); 366 | 367 | 368 | osx_hid_device* Device = OSXHIDDeviceCreate(DeviceRef, Manufacturer, Product, GameData); 369 | 370 | 371 | CFArrayRef ElementArray = IOHIDDeviceCopyMatchingElements(DeviceRef, NULL, kIOHIDOptionsTypeNone); 372 | int ElementArrayCount = CFArrayGetCount(ElementArray); 373 | 374 | for (int i = 0; i < ElementArrayCount; ++i) 375 | { 376 | IOHIDElementRef ElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(ElementArray, i); 377 | 378 | IOHIDElementCookie Cookie = IOHIDElementGetCookie(ElementRef); 379 | IOHIDElementType ElementType = IOHIDElementGetType(ElementRef); 380 | 381 | #if 0 382 | switch(ElementType) 383 | { 384 | case kIOHIDElementTypeInput_Misc: printf("[misc] "); break; 385 | case kIOHIDElementTypeInput_Button: printf("[button] "); break; 386 | case kIOHIDElementTypeInput_Axis: printf("[axis] "); break; 387 | case kIOHIDElementTypeInput_ScanCodes: printf("[scancode] "); break; 388 | default: continue; 389 | } 390 | #endif 391 | 392 | uint32_t ReportSize = IOHIDElementGetReportSize(ElementRef); 393 | uint32_t ReportCount = IOHIDElementGetReportCount(ElementRef); 394 | if ((ReportSize * ReportCount) > 64) 395 | { 396 | continue; 397 | } 398 | 399 | uint32_t UsagePage = IOHIDElementGetUsagePage(ElementRef); 400 | uint32_t Usage = IOHIDElementGetUsage(ElementRef); 401 | 402 | if (!UsagePage || !Usage) 403 | { 404 | continue; 405 | } 406 | if (Usage == -1) 407 | { 408 | continue; 409 | } 410 | 411 | CFIndex LogicalMin = IOHIDElementGetLogicalMin(ElementRef); 412 | CFIndex LogicalMax = IOHIDElementGetLogicalMax(ElementRef); 413 | 414 | osx_hid_element* Element = &(Device->Elements[Device->ElementCount++]); 415 | OSXHIDElementInitialize(Element, Cookie, ElementType, UsagePage, Usage, LogicalMin, LogicalMax); 416 | } 417 | 418 | CFRelease(ElementArray); 419 | 420 | IOHIDDeviceRegisterInputValueCallback(DeviceRef, OSXHIDAction, Device); 421 | } 422 | 423 | 424 | 425 | void OSXHIDRemoved(void* context, IOReturn result, void* sender, IOHIDDeviceRef device) 426 | { 427 | #pragma unused(context) 428 | #pragma unused(result) 429 | #pragma unused(sender) 430 | #pragma unused(device) 431 | 432 | printf("Gamepad was unplugged\n"); 433 | } 434 | 435 | 436 | 437 | void OSXSetupGamepad(osx_game_data* game_data) 438 | { 439 | game_data->HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); 440 | 441 | if (game_data->HIDManager) 442 | { 443 | CFStringRef keys[2]; 444 | keys[0] = CFSTR(kIOHIDDeviceUsagePageKey); 445 | keys[1] = CFSTR(kIOHIDDeviceUsageKey); 446 | 447 | 448 | int usageValues[3] = { 449 | kHIDUsage_GD_Joystick, 450 | kHIDUsage_GD_GamePad, 451 | kHIDUsage_GD_MultiAxisController 452 | }; 453 | int usageValuesCount = sizeof(usageValues) / sizeof(int); 454 | 455 | CFDictionaryRef dictionaries[usageValuesCount]; 456 | 457 | for (int i = 0; i < usageValuesCount; ++i) 458 | { 459 | CFNumberRef values[2]; 460 | 461 | int pageGDValue = kHIDPage_GenericDesktop; 462 | values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pageGDValue); 463 | values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &(usageValues[i])); 464 | 465 | dictionaries[i] = CFDictionaryCreate(kCFAllocatorDefault, 466 | (const void**)keys, 467 | (const void**)values, 468 | 2, 469 | &kCFTypeDictionaryKeyCallBacks, 470 | &kCFTypeDictionaryValueCallBacks); 471 | CFRelease(values[0]); 472 | CFRelease(values[1]); 473 | } 474 | 475 | #if 0 476 | NSArray* criteria = @[ @{ [NSString stringWithUTF8String:kIOHIDDeviceUsagePageKey]: 477 | [NSNumber numberWithInt:kHIDPage_GenericDesktop], 478 | [NSString stringWithUTF8String:kIOHIDDeviceUsageKey]: 479 | [NSNumber numberWithInt:kHIDUsage_GD_Joystick] 480 | }, 481 | @{ (NSString*)CFSTR(kIOHIDDeviceUsagePageKey): 482 | [NSNumber numberWithInt:kHIDPage_GenericDesktop], 483 | (NSString*)CFSTR(kIOHIDDeviceUsageKey): 484 | [NSNumber numberWithInt:kHIDUsage_GD_GamePad] 485 | }, 486 | @{ (NSString*)CFSTR(kIOHIDDeviceUsagePageKey): 487 | [NSNumber numberWithInt:kHIDPage_GenericDesktop], 488 | (NSString*)CFSTR(kIOHIDDeviceUsageKey): 489 | [NSNumber numberWithInt:kHIDUsage_GD_MultiAxisController] 490 | } 491 | #if 0 492 | , 493 | @{ (NSString*)CFSTR(kIOHIDDeviceUsagePageKey): 494 | [NSNumber numberWithInt:kHIDPage_GenericDesktop], 495 | (NSString*)CFSTR(kIOHIDDeviceUsageKey): 496 | [NSNumber numberWithInt:kHIDUsage_GD_Keyboard] 497 | } 498 | #endif 499 | ]; 500 | #endif 501 | 502 | CFArrayRef criteria = CFArrayCreate(kCFAllocatorDefault, 503 | (const void**)dictionaries, 504 | usageValuesCount, 505 | &kCFTypeArrayCallBacks); 506 | 507 | 508 | // NOTE(jeff): These all return void, so no error checking... 509 | IOHIDManagerSetDeviceMatchingMultiple(game_data->HIDManager, criteria); 510 | IOHIDManagerRegisterDeviceMatchingCallback(game_data->HIDManager, OSXHIDAdded, (void*)game_data); 511 | IOHIDManagerRegisterDeviceRemovalCallback(game_data->HIDManager, OSXHIDRemoved, (void*)game_data); 512 | IOHIDManagerScheduleWithRunLoop(game_data->HIDManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); 513 | 514 | if (IOHIDManagerOpen(game_data->HIDManager, kIOHIDOptionsTypeNone) == kIOReturnSuccess) 515 | { 516 | //IOHIDManagerRegisterInputValueCallback(game_data->HIDManager, OSXHIDAction, (void*)game_data); 517 | } 518 | else 519 | { 520 | // TODO(jeff): Diagnostic 521 | } 522 | 523 | 524 | for (int i = 0; i < usageValuesCount; ++i) 525 | { 526 | CFRelease(dictionaries[i]); 527 | } 528 | 529 | CFRelease(criteria); 530 | } 531 | else 532 | { 533 | // TODO(jeff): Diagnostic 534 | } 535 | } 536 | 537 | 538 | -------------------------------------------------------------------------------- /code/osx_handmade_memory.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | void* OSXSimpleAllocateMemory(umm Size) 4 | { 5 | void* P = (void*)mmap(0, Size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); 6 | 7 | if (P == MAP_FAILED) 8 | { 9 | printf("OSXAllocateMemory: mmap error: %d %s", errno, strerror(errno)); 10 | } 11 | 12 | Assert(P); 13 | 14 | return P; 15 | } 16 | 17 | 18 | //#define PLATFORM_ALLOCATE_MEMORY(name) platform_memory_block* name(memory_index Size, u64 Flags) 19 | PLATFORM_ALLOCATE_MEMORY(OSXAllocateMemory) 20 | { 21 | // NOTE(casey): We require memory block headers not to change the cache 22 | // line alignment of an allocation 23 | Assert(sizeof(osx_memory_block) == 128); 24 | 25 | umm PageSize = 4096; 26 | umm TotalSize = Size + sizeof(osx_memory_block); 27 | umm BaseOffset = sizeof(osx_memory_block); 28 | umm ProtectOffset = 0; 29 | 30 | if (Flags & PlatformMemory_UnderflowCheck) 31 | { 32 | TotalSize += Size + 2 * PageSize; 33 | BaseOffset = 2 * PageSize; 34 | ProtectOffset = PageSize; 35 | } 36 | else if (Flags & PlatformMemory_OverflowCheck) 37 | { 38 | umm SizeRoundedUp = AlignPow2(Size, PageSize); 39 | TotalSize += SizeRoundedUp + 2 * PageSize; 40 | BaseOffset = PageSize + SizeRoundedUp - Size; 41 | ProtectOffset = PageSize + SizeRoundedUp; 42 | } 43 | 44 | osx_memory_block* Block = (osx_memory_block*)mmap(0, 45 | TotalSize, 46 | PROT_READ | PROT_WRITE, 47 | MAP_PRIVATE | MAP_ANON, 48 | -1, 49 | 0); 50 | if (Block == MAP_FAILED) 51 | { 52 | printf("OSXAllocateMemory: mmap error: %d %s", errno, strerror(errno)); 53 | } 54 | 55 | Assert(Block); 56 | Block->Block.Base = (u8*)Block + BaseOffset; 57 | Assert(Block->Block.Used == 0); 58 | Assert(Block->Block.ArenaPrev == 0); 59 | 60 | if (Flags & (PlatformMemory_UnderflowCheck|PlatformMemory_OverflowCheck)) 61 | { 62 | int ProtectResult = mprotect((u8*)Block + ProtectOffset, PageSize, PROT_NONE); 63 | if (ProtectResult != 0) 64 | { 65 | } 66 | else 67 | { 68 | printf("OSXAllocateMemory: Underflow mprotect error: %d %s", errno, strerror(errno)); 69 | } 70 | } 71 | 72 | osx_memory_block* Sentinel = &GlobalOSXState.MemorySentinel; 73 | Block->Next = Sentinel; 74 | Block->Block.Size = Size; 75 | Block->TotalAllocatedSize = TotalSize; 76 | Block->Block.Flags = Flags; 77 | Block->LoopingFlags = 0; 78 | if (OSXIsInLoop(&GlobalOSXState) && !(Flags & PlatformMemory_NotRestored)) 79 | { 80 | Block->LoopingFlags = OSXMem_AllocatedDuringLooping; 81 | } 82 | 83 | BeginTicketMutex(&GlobalOSXState.MemoryMutex); 84 | Block->Prev = Sentinel->Prev; 85 | Block->Prev->Next = Block; 86 | Block->Next->Prev = Block; 87 | EndTicketMutex(&GlobalOSXState.MemoryMutex); 88 | 89 | platform_memory_block* PlatBlock = &Block->Block; 90 | return PlatBlock; 91 | } 92 | 93 | 94 | void OSXFreeMemoryBlock(osx_memory_block* Block) 95 | { 96 | BeginTicketMutex(&GlobalOSXState.MemoryMutex); 97 | Block->Prev->Next = Block->Next; 98 | Block->Next->Prev = Block->Prev; 99 | EndTicketMutex(&GlobalOSXState.MemoryMutex); 100 | 101 | if (munmap(Block, Block->TotalAllocatedSize) != 0) 102 | { 103 | printf("OSXFreeMemoryBlock: munmap error: %d %s", errno, strerror(errno)); 104 | } 105 | } 106 | 107 | //#define PLATFORM_DEALLOCATE_MEMORY(name) void name(platform_memory_block* Memory) 108 | PLATFORM_DEALLOCATE_MEMORY(OSXDeallocateMemory) 109 | { 110 | if (Block) 111 | { 112 | osx_memory_block* OSXBlock = (osx_memory_block*)Block; 113 | 114 | if (OSXIsInLoop(&GlobalOSXState) && !(OSXBlock->Block.Flags & PlatformMemory_NotRestored)) 115 | { 116 | OSXBlock->LoopingFlags = OSXMem_FreedDuringLooping; 117 | } 118 | else 119 | { 120 | OSXFreeMemoryBlock(OSXBlock); 121 | } 122 | } 123 | } 124 | 125 | -------------------------------------------------------------------------------- /code/osx_handmade_opengl.cpp: -------------------------------------------------------------------------------- 1 | 2 | // NOTE(jeff): This is a weak reference that is 3 | // updated during a hot reload. The "real" one 4 | // is kept in the OpenGL.Header.Platform 5 | extern NSOpenGLContext* GlobalGLContext; 6 | 7 | 8 | void OSXDebugInternalLogOpenGLErrors(const char* label) 9 | { 10 | GLenum err = glGetError(); 11 | const char* errString = "No error"; 12 | 13 | while (err != GL_NO_ERROR) 14 | { 15 | switch(err) 16 | { 17 | case GL_INVALID_ENUM: 18 | errString = "Invalid Enum"; 19 | break; 20 | 21 | case GL_INVALID_VALUE: 22 | errString = "Invalid Value"; 23 | break; 24 | 25 | case GL_INVALID_OPERATION: 26 | errString = "Invalid Operation"; 27 | break; 28 | 29 | /* 30 | case GL_INVALID_FRAMEBUFFER_OPERATION: 31 | errString = "Invalid Framebuffer Operation"; 32 | break; 33 | */ 34 | case GL_OUT_OF_MEMORY: 35 | errString = "Out of Memory"; 36 | break; 37 | 38 | case GL_STACK_UNDERFLOW: 39 | errString = "Stack Underflow"; 40 | break; 41 | 42 | case GL_STACK_OVERFLOW: 43 | errString = "Stack Overflow"; 44 | break; 45 | 46 | default: 47 | errString = "Unknown Error"; 48 | break; 49 | } 50 | printf("glError on %s: %s\n", label, errString); 51 | 52 | err = glGetError(); 53 | } 54 | } 55 | 56 | 57 | 58 | internal void PlatformOpenGLSetVSync(open_gl* Renderer, b32x VSyncEnabled) 59 | { 60 | NSOpenGLContext* GLContext = (NSOpenGLContext*)Renderer->Header.Platform; 61 | Assert(GLContext); 62 | 63 | GLint SwapInterval = VSyncEnabled ? 1 : 0; 64 | 65 | 66 | [GLContext setValues:&SwapInterval forParameter:NSOpenGLCPSwapInterval]; 67 | } 68 | 69 | 70 | extern "C" RENDERER_BEGIN_FRAME(OSXBeginFrame) 71 | { 72 | NSOpenGLContext* GLContext = (NSOpenGLContext*)Renderer->Platform; 73 | 74 | [GLContext makeCurrentContext]; 75 | game_render_commands* Result = OpenGLBeginFrame((open_gl*)Renderer, OSWindowDim, RenderDim, DrawRegion); 76 | 77 | return Result; 78 | } 79 | 80 | 81 | extern "C" RENDERER_END_FRAME(OSXEndFrame) 82 | { 83 | 84 | OpenGLEndFrame((open_gl*)Renderer, Frame); 85 | 86 | // flushes and forces vsync 87 | // 88 | NSOpenGLContext* GLContext = (NSOpenGLContext*)Renderer->Platform; 89 | [GLContext flushBuffer]; 90 | 91 | #if 0 92 | #if HANDMADE_USE_VSYNC 93 | [GlobalGLContext flushBuffer]; 94 | #else 95 | glFlush(); 96 | #endif 97 | #endif 98 | } 99 | 100 | internal open_gl* OSXInitOpenGL(platform_renderer_limits* Limits) 101 | { 102 | open_gl* OpenGL = (open_gl*)OSXRendererAlloc(sizeof(open_gl)); 103 | 104 | InitTextureQueue(&OpenGL->Header.TextureQueue, 105 | Limits->TextureTransferBufferSize, 106 | OSXRendererAlloc(Limits->TextureTransferBufferSize)); 107 | 108 | u32 MaxVertexCount = Limits->MaxQuadCountPerFrame * 4; 109 | u32 MaxIndexCount = Limits->MaxQuadCountPerFrame * 6; 110 | OpenGL->MaxTextureCount = Limits->MaxTextureCount; 111 | OpenGL->MaxVertexCount = MaxVertexCount; 112 | OpenGL->MaxIndexCount = MaxIndexCount; 113 | OpenGL->MaxSpecialTextureCount = Limits->MaxSpecialTextureCount; 114 | 115 | // NOTE(casey): This is wayyyyyy overkill because you would not render all your quads 116 | // as separate textures, so this wastes a ton of memory. At some point we may want 117 | // to restrict the number of these you could draw with separate textures. 118 | OpenGL->MaxQuadTextureCount = Limits->MaxQuadCountPerFrame; 119 | 120 | OpenGL->VertexArray = (textured_vertex*)OSXRendererAlloc(MaxVertexCount * sizeof(textured_vertex)); 121 | OpenGL->IndexArray = (u16*)OSXRendererAlloc(MaxIndexCount * sizeof(u16)); 122 | OpenGL->BitmapArray = (renderer_texture*)OSXRendererAlloc(OpenGL->MaxQuadTextureCount * sizeof(renderer_texture)); 123 | 124 | if (Limits->MaxSpecialTextureCount) 125 | { 126 | OpenGL->SpecialTextureHandles = (GLuint*)OSXRendererAlloc(Limits->MaxSpecialTextureCount * sizeof(GLuint)); 127 | } 128 | else 129 | { 130 | OpenGL->SpecialTextureHandles = NULL; 131 | } 132 | 133 | 134 | v3s LightAtlasVoxelDim = V3S(LIGHT_LOOKUP_VOXEL_DIM_X, LIGHT_LOOKUP_VOXEL_DIM_Y, LIGHT_LOOKUP_VOXEL_DIM_Z); 135 | 136 | u32 LIGHT_COLOR_LOOKUP_SQUARE_DIM = (LIGHTING_OCTAHEDRAL_MAP_DIM+2); 137 | v2u LightAtlasTileDim = V2U(LIGHT_COLOR_LOOKUP_SQUARE_DIM, LIGHT_COLOR_LOOKUP_SQUARE_DIM); 138 | OpenGL->DiffuseLightAtlas = MakeLightAtlas(LightAtlasVoxelDim, LightAtlasTileDim); 139 | SetLightAtlasTexels(&OpenGL->DiffuseLightAtlas, 140 | OSXRendererAlloc(GetLightAtlasSize(&OpenGL->DiffuseLightAtlas))); 141 | OpenGL->SpecularLightAtlas = MakeLightAtlas(LightAtlasVoxelDim, LightAtlasTileDim); 142 | SetLightAtlasTexels(&OpenGL->SpecularLightAtlas, 143 | OSXRendererAlloc(GetLightAtlasSize(&OpenGL->SpecularLightAtlas))); 144 | 145 | void* Image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); 146 | if (Image) 147 | { 148 | #define OSXGetOpenGLFunction(Module, Name) OpenGL->Name = (type_##Name *)dlsym(Module, #Name) 149 | 150 | OSXGetOpenGLFunction(Image, glTexImage2DMultisample); 151 | OSXGetOpenGLFunction(Image, glBindFramebuffer); 152 | OSXGetOpenGLFunction(Image, glGenFramebuffers); 153 | OSXGetOpenGLFunction(Image, glFramebufferTexture2D); 154 | OSXGetOpenGLFunction(Image, glCheckFramebufferStatus); 155 | OSXGetOpenGLFunction(Image, glBlitFramebuffer); 156 | OSXGetOpenGLFunction(Image, glAttachShader); 157 | OSXGetOpenGLFunction(Image, glCompileShader); 158 | OSXGetOpenGLFunction(Image, glCreateProgram); 159 | OSXGetOpenGLFunction(Image, glCreateShader); 160 | OSXGetOpenGLFunction(Image, glLinkProgram); 161 | OSXGetOpenGLFunction(Image, glShaderSource); 162 | OSXGetOpenGLFunction(Image, glUseProgram); 163 | OSXGetOpenGLFunction(Image, glGetProgramInfoLog); 164 | OSXGetOpenGLFunction(Image, glGetShaderInfoLog); 165 | OSXGetOpenGLFunction(Image, glValidateProgram); 166 | OSXGetOpenGLFunction(Image, glGetProgramiv); 167 | OSXGetOpenGLFunction(Image, glGetUniformLocation); 168 | OSXGetOpenGLFunction(Image, glUniform4fv); 169 | OSXGetOpenGLFunction(Image, glUniformMatrix4fv); 170 | OSXGetOpenGLFunction(Image, glUniform1i); 171 | OSXGetOpenGLFunction(Image, glUniform1f); 172 | OSXGetOpenGLFunction(Image, glUniform2fv); 173 | OSXGetOpenGLFunction(Image, glUniform3fv); 174 | OSXGetOpenGLFunction(Image, glEnableVertexAttribArray); 175 | OSXGetOpenGLFunction(Image, glDisableVertexAttribArray); 176 | OSXGetOpenGLFunction(Image, glGetAttribLocation); 177 | OSXGetOpenGLFunction(Image, glVertexAttribPointer); 178 | OSXGetOpenGLFunction(Image, glVertexAttribIPointer); 179 | OSXGetOpenGLFunction(Image, glDebugMessageCallbackARB); 180 | OSXGetOpenGLFunction(Image, glBindVertexArray); 181 | OSXGetOpenGLFunction(Image, glGenVertexArrays); 182 | OSXGetOpenGLFunction(Image, glBindBuffer); 183 | OSXGetOpenGLFunction(Image, glGenBuffers); 184 | OSXGetOpenGLFunction(Image, glBufferData); 185 | OSXGetOpenGLFunction(Image, glActiveTexture); 186 | OSXGetOpenGLFunction(Image, glGetStringi); 187 | OSXGetOpenGLFunction(Image, glDeleteProgram); 188 | OSXGetOpenGLFunction(Image, glDeleteShader); 189 | OSXGetOpenGLFunction(Image, glDeleteFramebuffers); 190 | OSXGetOpenGLFunction(Image, glDrawBuffers); 191 | OSXGetOpenGLFunction(Image, glTexImage3D); 192 | OSXGetOpenGLFunction(Image, glTexSubImage3D); 193 | OSXGetOpenGLFunction(Image, glDrawElementsBaseVertex); 194 | 195 | opengl_info Info = OpenGLGetInfo(OpenGL, true); 196 | 197 | //OpenGL.SupportsSRGBFramebuffer = true; 198 | OpenGLInit(OpenGL, Info, OpenGL->SupportsSRGBFramebuffer); 199 | 200 | #if 0 201 | OpenGLDefaultInternalTextureFormat = GL_RGBA8; 202 | //OpenGLDefaultInternalTextureFormat = GL_SRGB8_ALPHA8; 203 | glEnable(GL_FRAMEBUFFER_SRGB); 204 | #endif 205 | } 206 | else 207 | { 208 | printf("Could not dynamically load OpenGL\n"); 209 | } 210 | 211 | return OpenGL; 212 | } 213 | 214 | 215 | extern "C" 216 | { 217 | OSX_LOAD_RENDERER_ENTRY() 218 | { 219 | void* GLContext = OSXInitOpenGLView(Window); 220 | platform_renderer* Result = (platform_renderer*)OSXInitOpenGL(Limits); 221 | Result->Platform = GLContext; 222 | 223 | return Result; 224 | } 225 | } 226 | 227 | 228 | #if 0 229 | void OSXDisplayBufferInWindow(platform_work_queue* RenderQueue, 230 | game_offscreen_buffer* RenderBuffer, 231 | game_render_commands* Commands, 232 | rectangle2i DrawRegion, 233 | u32 WindowWidth, 234 | u32 WindowHeight, 235 | memory_arena* TempArena) 236 | { 237 | temporary_memory TempMem = BeginTemporaryMemory(TempArena); 238 | 239 | if (!GlobalSoftwareRendering) 240 | { 241 | BEGIN_BLOCK("OpenGLRenderCommands"); 242 | 243 | OpenGLRenderCommands(Commands, DrawRegion, WindowWidth, WindowHeight); 244 | END_BLOCK(); 245 | } 246 | else 247 | { 248 | software_texture OutputTarget; 249 | OutputTarget.Memory = RenderBuffer->Memory; 250 | OutputTarget.Width = RenderBuffer->Width; 251 | OutputTarget.Height = RenderBuffer->Height; 252 | OutputTarget.Pitch = RenderBuffer->Pitch; 253 | 254 | //BEGIN_BLOCK("SoftwareRenderCommands"); 255 | SoftwareRenderCommands(RenderQueue, Commands, &OutputTarget, TempArena); 256 | //END_BLOCK(); 257 | 258 | // We always display via hardware 259 | 260 | v4 ClearColor = {}; 261 | 262 | OpenGLDisplayBitmap(RenderBuffer->Width, RenderBuffer->Height, 263 | RenderBuffer->Memory, RenderBuffer->Pitch, 264 | DrawRegion, 265 | ClearColor, 266 | OpenGL.ReservedBlitTexture); 267 | //SwapBuffers(); 268 | } 269 | 270 | EndTemporaryMemory(TempMem); 271 | } 272 | #endif 273 | 274 | -------------------------------------------------------------------------------- /code/osx_handmade_opengl.h: -------------------------------------------------------------------------------- 1 | 2 | #define GL_BGRA_EXT 0x80E1 3 | #define GL_NUM_EXTENSIONS 0x821D 4 | 5 | typedef char GLchar; 6 | 7 | typedef void type_glTexImage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, 8 | GLsizei width, GLsizei height, GLboolean fixedsamplelocations); 9 | typedef void type_glBindFramebuffer(GLenum target, GLuint framebuffer); 10 | typedef void type_glGenFramebuffers(GLsizei n, GLuint *framebuffers); 11 | typedef void type_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); 12 | typedef GLenum type_glCheckFramebufferStatus(GLenum target); 13 | typedef void type_glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); 14 | typedef void type_glAttachShader(GLuint program, GLuint shader); 15 | typedef void type_glCompileShader(GLuint shader); 16 | typedef GLuint type_glCreateProgram(void); 17 | typedef GLuint type_glCreateShader(GLenum type); 18 | typedef void type_glLinkProgram(GLuint program); 19 | typedef void type_glShaderSource(GLuint shader, GLsizei count, GLchar **string, GLint *length); 20 | typedef void type_glUseProgram(GLuint program); 21 | typedef void type_glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); 22 | typedef void type_glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); 23 | typedef void type_glValidateProgram(GLuint program); 24 | typedef void type_glGetProgramiv(GLuint program, GLenum pname, GLint *params); 25 | 26 | 27 | ///////// 28 | // New 29 | typedef GLint type_glGetUniformLocation(GLuint program, const GLchar *name); 30 | typedef void type_glUniform4fv(GLint location, GLsizei count, const GLfloat *value); 31 | typedef void type_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 32 | typedef void type_glUniform1i(GLint location, GLint v0); 33 | typedef void type_glUniform1f(GLint location, GLfloat v0); 34 | typedef void type_glUniform2fv(GLint location, GLsizei count, const GLfloat *value); 35 | typedef void type_glUniform3fv(GLint location, GLsizei count, const GLfloat *value); 36 | 37 | typedef void type_glEnableVertexAttribArray(GLuint index); 38 | typedef void type_glDisableVertexAttribArray(GLuint index); 39 | typedef GLint type_glGetAttribLocation(GLuint program, const GLchar *name); 40 | typedef void type_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); 41 | typedef void type_glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); 42 | 43 | typedef void type_glBindBuffer (GLenum target, GLuint buffer); 44 | typedef void type_glGenBuffers (GLsizei n, GLuint *buffers); 45 | typedef void type_glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); 46 | typedef void type_glActiveTexture (GLenum texture); 47 | typedef void type_glDeleteProgram (GLuint program); 48 | typedef void type_glDeleteShader (GLuint shader); 49 | typedef void type_glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers); 50 | typedef void type_glDrawBuffers (GLsizei n, const GLenum *bufs); 51 | typedef void type_glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); 52 | typedef void type_glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); 53 | // 54 | //////// 55 | 56 | 57 | typedef void type_glBindVertexArray(GLuint array); 58 | typedef void type_glGenVertexArrays(GLsizei n, GLuint *arrays); 59 | typedef GLubyte* type_glGetStringi(GLenum name, GLuint index); 60 | typedef void type_glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers); 61 | typedef void type_glDrawBuffers(GLsizei n, const GLenum* bufs); 62 | typedef void type_glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); 63 | typedef void type_glDrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); 64 | 65 | #if 0 66 | global gl_tex_image_2d_multisample *glTexImage2DMultisample; 67 | global gl_bind_framebuffer* glBindFramebuffer; 68 | global gl_gen_framebuffers* glGenFramebuffers; 69 | global gl_framebuffer_texture_2D* glFramebufferTexture2D; 70 | global gl_check_framebuffer_status* glCheckFramebufferStatus; 71 | global gl_blit_framebuffer *glBlitFramebuffer; 72 | #endif 73 | 74 | #define GL_DEBUG_CALLBACK(Name) void Name(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam) 75 | typedef GL_DEBUG_CALLBACK(GLDEBUGPROC); 76 | typedef void type_glDebugMessageCallbackARB(GLDEBUGPROC *callback, const void *userParam); 77 | 78 | -------------------------------------------------------------------------------- /code/osx_handmade_opengl.mm: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define GL_GLEXT_LEGACY 4 | #import 5 | #import 6 | #include 7 | 8 | #import "handmade_types.h" 9 | #import "handmade_intrinsics.h" 10 | #import "handmade_math.h" 11 | #import "handmade_shared.h" 12 | #import "handmade_light_atlas.h" 13 | #import "handmade_renderer.h" 14 | #import "handmade_image.h" 15 | 16 | #import "handmade_simd.h" 17 | #import "handmade_sampling_spheres.inl" 18 | 19 | #import "osx_handmade_opengl.h" 20 | #import "handmade_renderer_opengl.h" 21 | 22 | #import "osx_handmade_cocoa.h" 23 | #import "osx_handmade_renderer.h" 24 | 25 | NSOpenGLContext* OSXInitOpenGLView(NSWindow* Window); 26 | #import "osx_handmade_opengl.cpp" 27 | 28 | #import "handmade_renderer_opengl.cpp" 29 | #import "handmade_image.cpp" 30 | #import "handmade_light_atlas.cpp" 31 | 32 | 33 | /////////////////////////////////////////////////////////////////////// 34 | @interface HandmadeView : NSOpenGLView 35 | { 36 | } 37 | @end 38 | 39 | @implementation HandmadeView 40 | 41 | - (id)init 42 | { 43 | self = [super init]; 44 | 45 | return self; 46 | } 47 | 48 | 49 | - (void)prepareOpenGL 50 | { 51 | [super prepareOpenGL]; 52 | [[self openGLContext] makeCurrentContext]; 53 | } 54 | 55 | NSOpenGLContext* InternalGLContext; 56 | 57 | - (void)reshape 58 | { 59 | [super reshape]; 60 | 61 | NSRect bounds = [self bounds]; 62 | [InternalGLContext makeCurrentContext]; 63 | [InternalGLContext update]; 64 | glViewport(0, 0, bounds.size.width, bounds.size.height); 65 | } 66 | 67 | @end 68 | 69 | 70 | NSOpenGLContext* OSXInitOpenGLView(NSWindow* Window) 71 | { 72 | NSView* CV = [Window contentView]; 73 | 74 | // All hardware NSOpenGLPixelFormats support an sRGB framebuffer. 75 | NSOpenGLPixelFormatAttribute openGLAttributes[] = 76 | { 77 | NSOpenGLPFAAccelerated, 78 | NSOpenGLPFADoubleBuffer, 79 | NSOpenGLPFAColorSize, 24, 80 | NSOpenGLPFAAlphaSize, 8, 81 | NSOpenGLPFADepthSize, 24, 82 | NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, 83 | 0 84 | }; 85 | NSOpenGLPixelFormat* PixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:openGLAttributes]; 86 | NSOpenGLContext* GLContext = [[NSOpenGLContext alloc] initWithFormat:PixelFormat shareContext:NULL]; 87 | 88 | InternalGLContext = GLContext; 89 | 90 | HandmadeView* GLView = [[HandmadeView alloc] init]; 91 | [GLView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; 92 | [GLView setPixelFormat:PixelFormat]; 93 | [GLView setOpenGLContext:GLContext]; 94 | [GLView setFrame:[CV bounds]]; 95 | 96 | [CV addSubview:GLView]; 97 | 98 | [PixelFormat release]; 99 | 100 | /////////////////////////////////////////////////////////////////// 101 | // OpenGL setup with Cocoa 102 | #if HANDMADE_USE_VSYNC 103 | GLint swapInt = 1; 104 | #else 105 | GLint swapInt = 0; 106 | #endif 107 | [GLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; 108 | 109 | [GLContext setView:[Window contentView]]; 110 | [GLContext makeCurrentContext]; 111 | 112 | return GLContext; 113 | } 114 | 115 | 116 | #if 0 117 | NSWindow* OSXInitOpenGLWindow(OSXCocoaContext* CocoaContext, NSString* AppName, 118 | float WindowWidth, float WindowHeight) 119 | { 120 | NSRect ScreenRect = [[NSScreen mainScreen] frame]; 121 | 122 | NSRect InitialFrame = NSMakeRect((ScreenRect.size.width - WindowWidth) * 0.5, 123 | (ScreenRect.size.height - WindowHeight) * 0.5, 124 | WindowWidth, 125 | WindowHeight); 126 | 127 | NSWindow* Window = [[NSWindow alloc] initWithContentRect:InitialFrame 128 | styleMask:NSWindowStyleMaskTitled 129 | | NSWindowStyleMaskClosable 130 | | NSWindowStyleMaskMiniaturizable 131 | | NSWindowStyleMaskResizable 132 | backing:NSBackingStoreBuffered 133 | defer:NO]; 134 | 135 | [Window setBackgroundColor: NSColor.redColor]; 136 | [Window setDelegate:CocoaContext->AppDelegate]; 137 | 138 | NSView* CV = [Window contentView]; 139 | [CV setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; 140 | [CV setAutoresizesSubviews:YES]; 141 | 142 | // All hardware NSOpenGLPixelFormats support an sRGB framebuffer. 143 | NSOpenGLPixelFormatAttribute openGLAttributes[] = 144 | { 145 | NSOpenGLPFAAccelerated, 146 | NSOpenGLPFADoubleBuffer, 147 | NSOpenGLPFAColorSize, 24, 148 | NSOpenGLPFAAlphaSize, 8, 149 | NSOpenGLPFADepthSize, 24, 150 | NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, 151 | 0 152 | }; 153 | NSOpenGLPixelFormat* PixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:openGLAttributes]; 154 | GlobalGLContext = [[NSOpenGLContext alloc] initWithFormat:PixelFormat shareContext:NULL]; 155 | 156 | HandmadeView* GLView = [[HandmadeView alloc] init]; 157 | [GLView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; 158 | [GLView setPixelFormat:PixelFormat]; 159 | [GLView setOpenGLContext:GlobalGLContext]; 160 | [GLView setFrame:[CV bounds]]; 161 | 162 | [CV addSubview:GLView]; 163 | 164 | [PixelFormat release]; 165 | 166 | [Window setMinSize:NSMakeSize(160, 90)]; 167 | [Window setTitle:AppName]; 168 | [Window makeKeyAndOrderFront:nil]; 169 | 170 | /////////////////////////////////////////////////////////////////// 171 | // OpenGL setup with Cocoa 172 | #if HANDMADE_USE_VSYNC 173 | GLint swapInt = 1; 174 | #else 175 | GLint swapInt = 0; 176 | #endif 177 | [GlobalGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; 178 | 179 | [GlobalGLContext setView:[Window contentView]]; 180 | [GlobalGLContext makeCurrentContext]; 181 | 182 | CocoaContext->Window = Window; 183 | 184 | return Window; 185 | } 186 | #endif 187 | 188 | -------------------------------------------------------------------------------- /code/osx_handmade_playback.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////// 2 | // osx_handmade_playback.cpp 3 | // 4 | // Jeff Buck 5 | // Copyright 2014-2016. All Rights Reserved. 6 | // 7 | 8 | void OSXGetInputFileLocation(osx_state* State, bool32 InputStream, int SlotIndex, int DestCount, char* Dest) 9 | { 10 | char Temp[64]; 11 | sprintf(Temp, "loop_edit_%d_%s.hmi", SlotIndex, InputStream ? "input" : "state"); 12 | OSXBuildAppPathFilename(State, Temp, DestCount, Dest); 13 | } 14 | 15 | #if 0 16 | static osx_replay_buffer* 17 | OSXGetReplayBuffer(osx_state* State, int unsigned Index) 18 | { 19 | Assert(Index < ArrayCount(State->ReplayBuffers)); 20 | osx_replay_buffer* Result = &State->ReplayBuffers[Index]; 21 | 22 | return Result; 23 | } 24 | #endif 25 | 26 | 27 | void OSXBeginRecordingInput(osx_state* State, int InputRecordingIndex) 28 | { 29 | printf("beginning recording input\n"); 30 | 31 | char Filename[FILENAME_MAX]; 32 | OSXGetInputFileLocation(State, true, InputRecordingIndex, 33 | sizeof(Filename), Filename); 34 | State->RecordingHandle = open(Filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); 35 | 36 | if (State->RecordingHandle != -1) 37 | { 38 | // Test case: OSXVerifyMemoryListIntegrity(); 39 | 40 | State->InputRecordingIndex = InputRecordingIndex; 41 | osx_memory_block* Sentinel = &GlobalOSXState.MemorySentinel; 42 | 43 | BeginTicketMutex(&GlobalOSXState.MemoryMutex); 44 | 45 | for (osx_memory_block* SourceBlock = Sentinel->Next; 46 | SourceBlock != Sentinel; 47 | SourceBlock = SourceBlock->Next) 48 | { 49 | if (!(SourceBlock->Block.Flags & PlatformMemory_NotRestored)) 50 | { 51 | osx_saved_memory_block DestBlock; 52 | void* BasePointer = SourceBlock->Block.Base; 53 | DestBlock.BasePointer = (u64)BasePointer; 54 | DestBlock.Size = SourceBlock->Block.Size; 55 | 56 | ssize_t BytesWritten; 57 | BytesWritten = write(State->RecordingHandle, &DestBlock, sizeof(DestBlock)); 58 | 59 | if (BytesWritten == sizeof(DestBlock)) 60 | { 61 | Assert(DestBlock.Size <= U32Max); 62 | BytesWritten = write(State->RecordingHandle, BasePointer, 63 | (u32)DestBlock.Size); 64 | 65 | if (BytesWritten != DestBlock.Size) 66 | { 67 | printf("OSXBeginRecordingInput: Could not write Block contents\n"); 68 | } 69 | } 70 | else 71 | { 72 | printf("OSXBeginRecordingInput: Could not write Block header\n"); 73 | } 74 | } 75 | } 76 | 77 | EndTicketMutex(&GlobalOSXState.MemoryMutex); 78 | 79 | osx_saved_memory_block DestBlock = {}; 80 | write(State->RecordingHandle, &DestBlock, sizeof(DestBlock)); 81 | } 82 | } 83 | 84 | 85 | void OSXEndRecordingInput(osx_state* State) 86 | { 87 | close(State->RecordingHandle); 88 | State->RecordingHandle = -1; 89 | State->InputRecordingIndex = 0; 90 | printf("ended recording input\n"); 91 | } 92 | 93 | void OSXClearBlocksByMask(osx_state* State, u64 Mask) 94 | { 95 | for (osx_memory_block* BlockIter = State->MemorySentinel.Next; 96 | BlockIter != &State->MemorySentinel; 97 | ) 98 | { 99 | osx_memory_block* Block = BlockIter; 100 | BlockIter = BlockIter->Next; 101 | 102 | if ((Block->LoopingFlags & Mask) == Mask) 103 | { 104 | OSXFreeMemoryBlock(Block); 105 | } 106 | else 107 | { 108 | Block->LoopingFlags = 0; 109 | } 110 | } 111 | } 112 | 113 | void OSXBeginInputPlayback(osx_state* State, int InputPlayingIndex) 114 | { 115 | OSXClearBlocksByMask(State, OSXMem_AllocatedDuringLooping); 116 | 117 | printf("beginning input playback\n"); 118 | char Filename[FILENAME_MAX]; 119 | OSXGetInputFileLocation(State, true, InputPlayingIndex, sizeof(Filename), Filename); 120 | State->PlaybackHandle = open(Filename, O_RDONLY); 121 | 122 | if (State->PlaybackHandle != -1) 123 | { 124 | State->InputPlayingIndex = InputPlayingIndex; 125 | 126 | for (;;) 127 | { 128 | osx_saved_memory_block Block = {}; 129 | 130 | ssize_t BytesRead; 131 | BytesRead = read(State->PlaybackHandle, &Block, sizeof(Block)); 132 | 133 | if (Block.BasePointer != 0) 134 | { 135 | void* BasePointer = (void*)Block.BasePointer; 136 | Assert(Block.Size <= U32Max); 137 | BytesRead = read(State->PlaybackHandle, BasePointer, (u32)Block.Size); 138 | } 139 | else 140 | { 141 | break; 142 | } 143 | } 144 | } 145 | else 146 | { 147 | printf("Could not open playback file %s\n", Filename); 148 | } 149 | } 150 | 151 | 152 | void OSXEndInputPlayback(osx_state* State) 153 | { 154 | OSXClearBlocksByMask(State, OSXMem_FreedDuringLooping); 155 | 156 | close(State->PlaybackHandle); 157 | State->PlaybackHandle = -1; 158 | State->InputPlayingIndex = 0; 159 | 160 | printf("ended input playback\n"); 161 | } 162 | 163 | 164 | void OSXRecordInput(osx_state* State, game_input* NewInput) 165 | { 166 | uint32 BytesWritten = write(State->RecordingHandle, NewInput, sizeof(*NewInput)); 167 | 168 | if (BytesWritten != sizeof(*NewInput)) 169 | { 170 | printf("write error recording input: %d: %s\n", errno, strerror(errno)); 171 | } 172 | } 173 | 174 | 175 | void OSXPlaybackInput(osx_state* State, game_input* NewInput) 176 | { 177 | size_t BytesRead = read(State->PlaybackHandle, NewInput, sizeof(*NewInput)); 178 | 179 | if (BytesRead == 0) 180 | { 181 | // NOTE(casey): We've hit the end of the stream, go back to the beginning 182 | int PlayingIndex = State->InputPlayingIndex; 183 | OSXEndInputPlayback(State); 184 | OSXBeginInputPlayback(State, PlayingIndex); 185 | 186 | BytesRead = read(State->PlaybackHandle, NewInput, sizeof(*NewInput)); 187 | 188 | if (BytesRead != sizeof(*NewInput)) 189 | { 190 | printf("read error rewinding playback input: %d: %s\n", errno, strerror(errno)); 191 | } 192 | else 193 | { 194 | printf("rewinding playback...\n"); 195 | } 196 | } 197 | } 198 | 199 | 200 | -------------------------------------------------------------------------------- /code/osx_handmade_process.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////// 2 | // osx_handmade_process.cpp 3 | // 4 | // Jeff Buck 5 | // Copyright 2014-2016. All Rights Reserved. 6 | // 7 | 8 | 9 | /////////////////////////////////////////////////////////////////////// 10 | // External Process Control 11 | 12 | #define STRINGIFY(S) #S 13 | 14 | #if HANDMADE_INTERNAL 15 | DEBUG_PLATFORM_EXECUTE_SYSTEM_COMMAND(DEBUGExecuteSystemCommand) 16 | { 17 | debug_executing_process Result = {}; 18 | 19 | char* Args[] = {"/bin/sh", 20 | STRINGIFY(DYNAMIC_COMPILE_COMMAND), 21 | 0}; 22 | 23 | char* WorkingDirectory = STRINGIFY(DYNAMIC_COMPILE_PATH); 24 | 25 | int PID = fork(); 26 | 27 | switch(PID) 28 | { 29 | case -1: 30 | printf("Error forking process: %d\n", PID); 31 | break; 32 | 33 | case 0: 34 | { 35 | // child 36 | chdir(WorkingDirectory); 37 | int ExecCode = execvp(Args[0], Args); 38 | if (ExecCode == -1) 39 | { 40 | printf("Error in execve: %d\n", errno); 41 | } 42 | break; 43 | } 44 | 45 | default: 46 | // parent 47 | printf("Launched child process %d\n", PID); 48 | break; 49 | } 50 | 51 | 52 | Result.OSHandle = PID; 53 | 54 | return(Result); 55 | } 56 | 57 | 58 | DEBUG_PLATFORM_GET_PROCESS_STATE(DEBUGGetProcessState) 59 | { 60 | debug_process_state Result = {}; 61 | 62 | int PID = (int)Process.OSHandle; 63 | int ExitCode = 0; 64 | 65 | if (PID > 0) 66 | { 67 | Result.StartedSuccessfully = true; 68 | } 69 | 70 | if (waitpid(PID, &ExitCode, WNOHANG) == PID) 71 | { 72 | Result.ReturnCode = WEXITSTATUS(ExitCode); 73 | printf("Child process %d exited with code %d...\n", PID, ExitCode); 74 | } 75 | else 76 | { 77 | Result.IsRunning = true; 78 | } 79 | 80 | return(Result); 81 | } 82 | #endif 83 | 84 | 85 | -------------------------------------------------------------------------------- /code/osx_handmade_renderer.h: -------------------------------------------------------------------------------- 1 | #define OSX_LOAD_RENDERER(name) platform_renderer* name(NSWindow* Window, platform_renderer_limits* Limits) 2 | typedef OSX_LOAD_RENDERER(osx_load_renderer); 3 | #define OSX_LOAD_RENDERER_ENTRY() OSX_LOAD_RENDERER(OSXLoadRenderer) 4 | 5 | 6 | struct osx_renderer_function_table 7 | { 8 | osx_load_renderer* LoadRenderer; 9 | renderer_begin_frame* BeginFrame; 10 | renderer_end_frame* EndFrame; 11 | }; 12 | 13 | 14 | global char* OSXRendererFunctionTableNames[] = 15 | { 16 | "OSXLoadRenderer", 17 | "OSXBeginFrame", 18 | "OSXEndFrame", 19 | }; 20 | 21 | 22 | void* OSXRendererAlloc(umm Size) 23 | { 24 | void* P = (void*)mmap(0, Size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); 25 | 26 | if (P == MAP_FAILED) 27 | { 28 | printf("OSXRendererAlloc: mmap error: %d %s. Requested size = %lu\n", errno, strerror(errno), Size); 29 | } 30 | 31 | Assert(P); 32 | 33 | return P; 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /code/osx_handmade_thread.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////// 2 | // osx_handmade_thread.cpp 3 | // 4 | // Jeff Buck 5 | // Copyright 2014-2016. All Rights Reserved. 6 | // 7 | 8 | 9 | void* OSXQueueThreadProc(void *data) 10 | { 11 | //platform_work_queue* Queue = (platform_work_queue*)data; 12 | osx_thread_startup* Thread = (osx_thread_startup*)data; 13 | platform_work_queue* Queue = Thread->Queue; 14 | 15 | for(;;) 16 | { 17 | if(OSXDoNextWorkQueueEntry(Queue)) 18 | { 19 | dispatch_semaphore_wait(Queue->SemaphoreHandle, DISPATCH_TIME_FOREVER); 20 | } 21 | } 22 | 23 | return(0); 24 | } 25 | 26 | 27 | 28 | void OSXMakeQueue(platform_work_queue* Queue, uint32 ThreadCount, osx_thread_startup* Startups) 29 | { 30 | Queue->CompletionGoal = 0; 31 | Queue->CompletionCount = 0; 32 | 33 | Queue->NextEntryToWrite = 0; 34 | Queue->NextEntryToRead = 0; 35 | 36 | Queue->SemaphoreHandle = dispatch_semaphore_create(0); 37 | 38 | for (uint32 ThreadIndex = 0; 39 | ThreadIndex < ThreadCount; 40 | ++ThreadIndex) 41 | { 42 | osx_thread_startup* Startup = Startups + ThreadIndex; 43 | Startup->Queue = Queue; 44 | 45 | pthread_t ThreadId; 46 | int r = pthread_create(&ThreadId, NULL, OSXQueueThreadProc, Startup); 47 | if (r != 0) 48 | { 49 | printf("Error creating thread %d\n", ThreadIndex); 50 | } 51 | } 52 | } 53 | 54 | 55 | void OSXAddEntry(platform_work_queue* Queue, platform_work_queue_callback* Callback, void* Data) 56 | { 57 | // TODO(casey): Switch to InterlockedCompareExchange eventually 58 | // so that any thread can add? 59 | uint32 NewNextEntryToWrite = (Queue->NextEntryToWrite + 1) % ArrayCount(Queue->Entries); 60 | Assert(NewNextEntryToWrite != Queue->NextEntryToRead); 61 | platform_work_queue_entry *Entry = Queue->Entries + Queue->NextEntryToWrite; 62 | Entry->Callback = Callback; 63 | Entry->Data = Data; 64 | ++Queue->CompletionGoal; 65 | OSMemoryBarrier(); 66 | // Not needed: _mm_sfence(); 67 | Queue->NextEntryToWrite = NewNextEntryToWrite; 68 | dispatch_semaphore_signal(Queue->SemaphoreHandle); 69 | 70 | #if 0 71 | int r = dispatch_semaphore_signal(Queue->SemaphoreHandle); 72 | if (r > 0) 73 | { 74 | printf(" dispatch_semaphore_signal: A thread was woken\n"); 75 | } 76 | else 77 | { 78 | printf(" dispatch_semaphore_signal: No thread was woken\n"); 79 | } 80 | #endif 81 | } 82 | 83 | bool32 OSXDoNextWorkQueueEntry(platform_work_queue* Queue) 84 | { 85 | bool32 WeShouldSleep = false; 86 | 87 | uint32 OriginalNextEntryToRead = Queue->NextEntryToRead; 88 | uint32 NewNextEntryToRead = (OriginalNextEntryToRead + 1) % ArrayCount(Queue->Entries); 89 | 90 | if(OriginalNextEntryToRead != Queue->NextEntryToWrite) 91 | { 92 | // NOTE(jeff): OSAtomicCompareAndSwapXXX functions return 1 if the swap took place, 0 otherwise! 93 | uint32 SwapOccurred = OSAtomicCompareAndSwapIntBarrier(OriginalNextEntryToRead, 94 | NewNextEntryToRead, 95 | (int volatile*)&Queue->NextEntryToRead); 96 | 97 | if (SwapOccurred) 98 | { 99 | platform_work_queue_entry Entry = Queue->Entries[OriginalNextEntryToRead]; 100 | Entry.Callback(Queue, Entry.Data); 101 | //InterlockedIncrement((int volatile *)&Queue->CompletionCount); 102 | OSAtomicIncrement32Barrier((int volatile *)&Queue->CompletionCount); 103 | } 104 | else 105 | { 106 | } 107 | } 108 | else 109 | { 110 | WeShouldSleep = true; 111 | } 112 | 113 | return(WeShouldSleep); 114 | } 115 | 116 | void OSXCompleteAllWork(platform_work_queue *Queue) 117 | { 118 | while (Queue->CompletionGoal != Queue->CompletionCount) 119 | { 120 | OSXDoNextWorkQueueEntry(Queue); 121 | } 122 | 123 | Queue->CompletionGoal = 0; 124 | Queue->CompletionCount = 0; 125 | } 126 | 127 | -------------------------------------------------------------------------------- /code/osx_main.mm: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////// 2 | // osx_main.mm 3 | // 4 | // Jeff Buck 5 | // Copyright 2014-2020. All Rights Reserved. 6 | // 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include // for OSMemoryBarrier 25 | #include 26 | 27 | extern "C" 28 | { 29 | __attribute__((visibility("default"))) unsigned long NvOptimusEnablement = 1; 30 | __attribute__((visibility("default"))) int AmdPowerXpressRequestHighPerformance = 1; 31 | } 32 | 33 | // Let the command line override 34 | #ifndef HANDMADE_USE_VSYNC 35 | #define HANDMADE_USE_VSYNC 1 36 | #endif 37 | 38 | 39 | #define Maximum(A, B) ((A > B) ? (A) : (B)) 40 | 41 | #import "handmade_platform.h" 42 | #import "handmade_intrinsics.h" 43 | #import "handmade_math.h" 44 | 45 | #import "handmade_shared.h" 46 | #import "handmade_light_atlas.h" 47 | #import "handmade_memory.h" 48 | #import "handmade_renderer.h" 49 | 50 | #import "osx_handmade_events.h" 51 | #import "osx_handmade_renderer.h" 52 | #import "osx_handmade.h" 53 | #import "osx_handmade_cocoa.h" 54 | 55 | platform_api Platform; 56 | 57 | osx_state GlobalOSXState; 58 | global b32 GlobalSoftwareRendering; 59 | global GLuint OpenGLDefaultInternalTextureFormat; 60 | 61 | global b32 GlobalRunning = 1; 62 | global b32 GlobalPause; 63 | //global v2 GlobalAspectRatio = {16.0, 9.0}; 64 | 65 | v2 DefaultWindowDimension = 66 | { 67 | //192.0, 108.0 68 | //480.0, 270.0 69 | 960.0, 540.0 70 | //1280.0, 720.0 71 | //1279.0, 719.0 72 | //1920.0, 1080.0 73 | //2560.0, 1440.0 74 | }; 75 | 76 | 77 | #if 0 78 | const r32 DefaultWindowWidth = 960; 79 | const r32 DefaultWindowHeight = 540; 80 | 81 | const r32 GlobalRenderWidth = 960; 82 | const r32 GlobalRenderHeight = 540; 83 | #endif 84 | 85 | //#import "handmade_renderer.cpp" 86 | 87 | #import "osx_handmade_memory.cpp" 88 | #import "osx_handmade_debug.cpp" 89 | #import "osx_handmade_file.cpp" 90 | #import "osx_handmade_process.cpp" 91 | #import "osx_handmade_thread.cpp" 92 | #import "osx_handmade_audio.cpp" 93 | #import "osx_handmade_hid.cpp" 94 | #import "osx_handmade_dylib.cpp" 95 | #import "osx_handmade_playback.cpp" 96 | #import "osx_handmade_game.cpp" 97 | 98 | // Generic Cocoa boilerplate NSApplicationDelegate, NSWindow, NSOpenGLView, MTKView classes 99 | #import "osx_handmade_cocoa.mm" 100 | 101 | 102 | void OSXProcessPendingMessages(osx_game_data* GameData) 103 | { 104 | NSEvent* Event; 105 | 106 | ZeroStruct(GameData->NewInput->FKeyPressed); 107 | memcpy(GameData->OldKeyboardState, GameData->KeyboardState, sizeof(GameData->KeyboardState)); 108 | 109 | do 110 | { 111 | Event = [NSApp nextEventMatchingMask:NSAnyEventMask 112 | untilDate:nil 113 | inMode:NSDefaultRunLoopMode 114 | dequeue:YES]; 115 | 116 | switch ([Event type]) 117 | { 118 | case NSKeyDown: 119 | case NSKeyUp: 120 | { 121 | u32 KeyCode = [Event keyCode]; 122 | unichar C = [[Event charactersIgnoringModifiers] characterAtIndex:0]; 123 | u32 ModifierFlags = [Event modifierFlags]; 124 | int CommandKeyFlag = (ModifierFlags & NSCommandKeyMask) > 0; 125 | int ControlKeyFlag = (ModifierFlags & NSControlKeyMask) > 0; 126 | int AlternateKeyFlag = (ModifierFlags & NSAlternateKeyMask) > 0; 127 | int ShiftKeyFlag = (ModifierFlags & NSShiftKeyMask) > 0; 128 | 129 | int KeyDownFlag = ([Event type] == NSKeyDown) ? 1 : 0; 130 | GameData->KeyboardState[KeyCode] = KeyDownFlag; 131 | 132 | //printf("%s: keyCode: %d unichar: %c\n", NSKeyDown ? "KeyDown" : "KeyUp", [Event keyCode], C); 133 | 134 | OSXKeyProcessing(KeyDownFlag, KeyCode, C, 135 | ShiftKeyFlag, CommandKeyFlag, ControlKeyFlag, AlternateKeyFlag, 136 | GameData->NewInput, GameData); 137 | } break; 138 | 139 | case NSFlagsChanged: 140 | { 141 | u32 KeyCode = 0; 142 | u32 ModifierFlags = [Event modifierFlags]; 143 | int CommandKeyFlag = (ModifierFlags & NSCommandKeyMask) > 0; 144 | int ControlKeyFlag = (ModifierFlags & NSControlKeyMask) > 0; 145 | int AlternateKeyFlag = (ModifierFlags & NSAlternateKeyMask) > 0; 146 | int ShiftKeyFlag = (ModifierFlags & NSShiftKeyMask) > 0; 147 | 148 | GameData->KeyboardState[kVK_Command] = CommandKeyFlag; 149 | GameData->KeyboardState[kVK_Control] = ControlKeyFlag; 150 | GameData->KeyboardState[kVK_Alternate] = AlternateKeyFlag; 151 | GameData->KeyboardState[kVK_Shift] = ShiftKeyFlag; 152 | 153 | int KeyDownFlag = 0; 154 | 155 | if (CommandKeyFlag != GameData->OldKeyboardState[kVK_Command]) 156 | { 157 | KeyCode = kVK_Command; 158 | 159 | if (CommandKeyFlag) 160 | { 161 | KeyDownFlag = 1; 162 | } 163 | } 164 | 165 | if (ControlKeyFlag != GameData->OldKeyboardState[kVK_Control]) 166 | { 167 | KeyCode = kVK_Control; 168 | 169 | if (ControlKeyFlag) 170 | { 171 | KeyDownFlag = 1; 172 | } 173 | } 174 | 175 | if (AlternateKeyFlag != GameData->OldKeyboardState[kVK_Alternate]) 176 | { 177 | KeyCode = kVK_Option; 178 | 179 | if (AlternateKeyFlag) 180 | { 181 | KeyDownFlag = 1; 182 | } 183 | } 184 | 185 | if (ShiftKeyFlag != GameData->OldKeyboardState[kVK_Shift]) 186 | { 187 | if (ShiftKeyFlag) 188 | { 189 | KeyDownFlag = 1; 190 | } 191 | 192 | KeyCode = kVK_Shift; 193 | } 194 | 195 | //printf("Keyboard flags changed: Cmd: %d Ctrl: %d Opt: %d Shift: %d\n", 196 | // CommandKeyFlag, ControlKeyFlag, AlternateKeyFlag, ShiftKeyFlag); 197 | 198 | OSXKeyProcessing(-1, KeyCode, KeyCode, 199 | ShiftKeyFlag, CommandKeyFlag, ControlKeyFlag, AlternateKeyFlag, 200 | GameData->NewInput, GameData); 201 | } break; 202 | 203 | default: 204 | [NSApp sendEvent:Event]; 205 | } 206 | } while (Event != nil); 207 | 208 | } 209 | 210 | 211 | /////////////////////////////////////////////////////////////////////// 212 | 213 | int main(int argc, const char* argv[]) 214 | { 215 | #pragma unused(argc) 216 | #pragma unused(argv) 217 | 218 | SetDefaultFPBehavior(); 219 | 220 | @autoreleasepool 221 | { 222 | NSString* AppName = @"Handmade Hero"; 223 | OSXCocoaContext OSXAppContext = OSXInitCocoaContext(AppName, 224 | DefaultWindowDimension.Width, 225 | DefaultWindowDimension.Height); 226 | 227 | OSXCreateSimpleMainMenu(AppName); 228 | 229 | DEBUGSetEventRecording(true); 230 | 231 | // game_data holds the OS X platform layer non-Cocoa data structures 232 | osx_game_data GameData = {}; 233 | OSXSetupGameData(OSXAppContext.Window, &GameData); 234 | 235 | 236 | /////////////////////////////////////////////////////////////////// 237 | // Run loop 238 | // 239 | 240 | //u64 tickCounter = 0; 241 | 242 | u64 CurrentTime = mach_absolute_time(); 243 | GameData.LastCounter = CurrentTime; 244 | float frameTime = 0.0f; 245 | 246 | while (OSXIsGameRunning()) 247 | { 248 | OSXInitializeGameInputForNewFrame(&GameData); 249 | 250 | OSXProcessPendingMessages(&GameData); 251 | 252 | 253 | /////////////////////////////////////////////////////////////// 254 | // Main Game Function 255 | // 256 | osx_mouse_data MouseData = OSXGetMouseData(&OSXAppContext); 257 | 258 | CGRect ContentViewFrame = [[OSXAppContext.Window contentView] frame]; 259 | 260 | CGFloat BackingScaleFactor = [OSXAppContext.Window backingScaleFactor]; 261 | //NSLog(@"BackingScaleFactor = %f", BackingScaleFactor); 262 | 263 | CGRect ScaledFrame = ContentViewFrame; 264 | ScaledFrame.size.width *= BackingScaleFactor; 265 | ScaledFrame.size.height *= BackingScaleFactor; 266 | 267 | OSXProcessFrameAndRunGameLogic(&GameData, ScaledFrame, &MouseData); 268 | 269 | u64 EndCounter = mach_absolute_time(); 270 | 271 | f32 MeasuredSecondsPerFrame = OSXGetSecondsElapsed(GameData.LastCounter, EndCounter); 272 | f32 ExactTargetFramesPerUpdate = MeasuredSecondsPerFrame * (f32)GameData.MonitorRefreshHz; 273 | u32 NewExpectedFramesPerUpdate = RoundReal32ToInt32(ExactTargetFramesPerUpdate); 274 | GameData.ExpectedFramesPerUpdate = NewExpectedFramesPerUpdate; 275 | 276 | GameData.TargetSecondsPerFrame = MeasuredSecondsPerFrame; 277 | 278 | FRAME_MARKER(MeasuredSecondsPerFrame); 279 | 280 | frameTime += MeasuredSecondsPerFrame; 281 | GameData.LastCounter = EndCounter; 282 | 283 | #if 0 284 | ++tickCounter; 285 | if (tickCounter == 60) 286 | { 287 | float avgFrameTime = frameTime / 60.0f; 288 | tickCounter = 0; 289 | frameTime = 0.0f; 290 | //printf("frame time = %f\n", avgFrameTime); 291 | } 292 | #endif 293 | } 294 | 295 | 296 | OSXStopCoreAudio(&GameData.SoundOutput); 297 | 298 | 299 | printf("Handmade Hero finished running\n"); 300 | 301 | 302 | } // @autoreleasepool 303 | } 304 | 305 | -------------------------------------------------------------------------------- /code/osx_tabview.info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDocumentTypes 8 | 9 | 10 | CFBundleTypeExtensions 11 | 12 | dump 13 | 14 | CFBundleTypeIconFile 15 | 16 | CFBundleTypeName 17 | DocumentType 18 | CFBundleTypeOSTypes 19 | 20 | ???? 21 | 22 | CFBundleTypeRole 23 | Editor 24 | NSDocumentClass 25 | TabDocument 26 | 27 | 28 | CFBundleExecutable 29 | HandmadeTabView 30 | CFBundleIconFile 31 | 32 | CFBundleIdentifier 33 | org.HandmadeHero.osx 34 | CFBundleInfoDictionaryVersion 35 | 6.0 36 | CFBundleName 37 | HandmadeTabView 38 | CFBundlePackageType 39 | APPL 40 | CFBundleSignature 41 | ???? 42 | CFBundleVersion 43 | 1.0 44 | NSHumanReadableCopyright 45 | Copyright 2018 Jeff Buck 46 | NSPrincipalClass 47 | NSApplication 48 | 49 | 50 | -------------------------------------------------------------------------------- /code/vsprintf.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | int _snprintf_s(char* buffer, size_t offset, size_t junk, char* fmt, ...) 3 | { 4 | va_list args; 5 | va_start(args, fmt); 6 | int n = vsprintf(buffer, fmt, args); 7 | va_end(args); 8 | return n; 9 | } 10 | 11 | int _snprintf_s(char* buffer, size_t offset, char* fmt, ...) 12 | { 13 | va_list args; 14 | va_start(args, fmt); 15 | int n = vsprintf(buffer, fmt, args); 16 | va_end(args); 17 | return n; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /cpp/code/README.md: -------------------------------------------------------------------------------- 1 | To build this project, you need to copy the appropriate 2 | versions of the game code from Casey's 3 | code snapshots to this directory. The top level 4 | README.md file contains information on the specific 5 | files to copy as well as which version of 6 | Casey's code (e.g. Day 035) is compatible with this 7 | OS X port. 8 | 9 | 10 | -------------------------------------------------------------------------------- /cpp/code/vsprintf.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | int _snprintf_s(char* buffer, size_t offset, size_t junk, char* fmt, ...) 3 | { 4 | va_list args; 5 | va_start(args, fmt); 6 | int n = vsprintf(buffer, fmt, args); 7 | va_end(args); 8 | return n; 9 | } 10 | 11 | int _snprintf_s(char* buffer, size_t offset, char* fmt, ...) 12 | { 13 | va_list args; 14 | va_start(args, fmt); 15 | int n = vsprintf(buffer, fmt, args); 16 | va_end(args); 17 | return n; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /fix_handmade_hero_source.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | patch cpp/code/hhlightprof.cpp -i patches/hhlightprof.cpp.day615.patch 4 | #patch cpp/code/handmade_renderer_opengl.cpp -i patches/handmade_renderer_opengl.cpp.day475.patch 5 | 6 | -------------------------------------------------------------------------------- /fonts/AUTHORS: -------------------------------------------------------------------------------- 1 | AUTHORS 2 | 3 | Current Contributors (sorted alphabetically): 4 | - Pravin Satpute 5 | Project Owner (Current) 6 | Red Hat, Inc. 7 | 8 | Previous Contributors 9 | 10 | - Steve Matteson 11 | Original Designer 12 | Ascender, Inc. 13 | -------------------------------------------------------------------------------- /fonts/LICENSE: -------------------------------------------------------------------------------- 1 | Digitized data copyright (c) 2010 Google Corporation 2 | with Reserved Font Arimo, Tinos and Cousine. 3 | Copyright (c) 2012 Red Hat, Inc. 4 | with Reserved Font Name Liberation. 5 | 6 | This Font Software is licensed under the SIL Open Font License, 7 | Version 1.1. 8 | 9 | This license is copied below, and is also available with a FAQ at: 10 | http://scripts.sil.org/OFL 11 | 12 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 13 | 14 | PREAMBLE The goals of the Open Font License (OFL) are to stimulate 15 | worldwide development of collaborative font projects, to support the font 16 | creation efforts of academic and linguistic communities, and to provide 17 | a free and open framework in which fonts may be shared and improved in 18 | partnership with others. 19 | 20 | The OFL allows the licensed fonts to be used, studied, modified and 21 | redistributed freely as long as they are not sold by themselves. 22 | The fonts, including any derivative works, can be bundled, embedded, 23 | redistributed and/or sold with any software provided that any reserved 24 | names are not used by derivative works. The fonts and derivatives, 25 | however, cannot be released under any other type of license. The 26 | requirement for fonts to remain under this license does not apply to 27 | any document created using the fonts or their derivatives. 28 | 29 | 30 | 31 | DEFINITIONS 32 | "Font Software" refers to the set of files released by the Copyright 33 | Holder(s) under this license and clearly marked as such. 34 | This may include source files, build scripts and documentation. 35 | 36 | "Reserved Font Name" refers to any names specified as such after the 37 | copyright statement(s). 38 | 39 | "Original Version" refers to the collection of Font Software components 40 | as distributed by the Copyright Holder(s). 41 | 42 | "Modified Version" refers to any derivative made by adding to, deleting, 43 | or substituting ? in part or in whole ? 44 | any of the components of the Original Version, by changing formats or 45 | by porting the Font Software to a new environment. 46 | 47 | "Author" refers to any designer, engineer, programmer, technical writer 48 | or other person who contributed to the Font Software. 49 | 50 | 51 | PERMISSION & CONDITIONS 52 | 53 | Permission is hereby granted, free of charge, to any person obtaining a 54 | copy of the Font Software, to use, study, copy, merge, embed, modify, 55 | redistribute, and sell modified and unmodified copies of the Font 56 | Software, subject to the following conditions: 57 | 58 | 1) Neither the Font Software nor any of its individual components,in 59 | Original or Modified Versions, may be sold by itself. 60 | 61 | 2) Original or Modified Versions of the Font Software may be bundled, 62 | redistributed and/or sold with any software, provided that each copy 63 | contains the above copyright notice and this license. These can be 64 | included either as stand-alone text files, human-readable headers or 65 | in the appropriate machine-readable metadata fields within text or 66 | binary files as long as those fields can be easily viewed by the user. 67 | 68 | 3) No Modified Version of the Font Software may use the Reserved Font 69 | Name(s) unless explicit written permission is granted by the 70 | corresponding Copyright Holder. This restriction only applies to the 71 | primary font name as presented to the users. 72 | 73 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 74 | Software shall not be used to promote, endorse or advertise any 75 | Modified Version, except to acknowledge the contribution(s) of the 76 | Copyright Holder(s) and the Author(s) or with their explicit written 77 | permission. 78 | 79 | 5) The Font Software, modified or unmodified, in part or in whole, must 80 | be distributed entirely under this license, and must not be distributed 81 | under any other license. The requirement for fonts to remain under 82 | this license does not apply to any document created using the Font 83 | Software. 84 | 85 | 86 | 87 | TERMINATION 88 | This license becomes null and void if any of the above conditions are not met. 89 | 90 | 91 | 92 | DISCLAIMER 93 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 94 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 95 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 96 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 97 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 98 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 99 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 100 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER 101 | DEALINGS IN THE FONT SOFTWARE. 102 | 103 | -------------------------------------------------------------------------------- /fonts/LiberationMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itfrombit/osx_handmade/85e9828512d0e87dfe762494e30e4e800a930d47/fonts/LiberationMono-Regular.ttf -------------------------------------------------------------------------------- /fonts/LiberationSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itfrombit/osx_handmade/85e9828512d0e87dfe762494e30e4e800a930d47/fonts/LiberationSans-Regular.ttf -------------------------------------------------------------------------------- /fonts/LiberationSerif-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itfrombit/osx_handmade/85e9828512d0e87dfe762494e30e4e800a930d47/fonts/LiberationSerif-Regular.ttf -------------------------------------------------------------------------------- /patches/handmade_brain.cpp.day399.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_brain.cpp 2018-08-04 01:07:54.000000000 -0400 2 | +++ handmade_brain.cpp 2018-08-04 01:07:24.000000000 -0400 3 | @@ -269,10 +269,15 @@ 4 | 5 | ConHero->RecenterTimer = ClampAboveZero(ConHero->RecenterTimer - dt); 6 | 7 | + f32 ddPLen = Length(ddP); 8 | + if (ddPLen > 10.0f) 9 | + { 10 | + ddP *= (10.0f / ddPLen); 11 | + } 12 | Head->ddP = ddP; 13 | } 14 | 15 | - if(Body) 16 | + if (Head && Body) 17 | { 18 | Body->FacingDirection = Head->FacingDirection; 19 | Body->dP = V3(0, 0, 0); 20 | -------------------------------------------------------------------------------- /patches/handmade_dev_ui.cpp.day492.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_dev_ui.cpp 2019-08-18 14:19:34.000000000 -0700 2 | +++ handmade_dev_ui.cpp 2019-08-18 14:19:31.000000000 -0700 3 | @@ -530,7 +530,7 @@ 4 | internal void 5 | EditableBoolean(dev_ui_layout *Layout, dev_id ID, char *LabelText, b32 *Value) 6 | { 7 | - if(Button(Layout, ID, *Value ? "*" : "-")) 8 | + if(Button(Layout, ID, *Value ? (char*)"*" : (char*)"-")) 9 | { 10 | *Value = !*Value; 11 | Layout->EditOccurred = true; 12 | -------------------------------------------------------------------------------- /patches/handmade_lighting.cpp.day434.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_lighting.cpp 2018-08-09 17:06:27.000000000 -0400 2 | +++ handmade_lighting.cpp 2018-08-09 17:06:18.000000000 -0400 3 | @@ -215,12 +215,27 @@ 4 | } 5 | else if(AnyTrue(Mask)) 6 | { 7 | - f32_4x BoxSurfaceIndex = U32_4x(0) & (tBoxMin.x == tMin); 8 | - BoxSurfaceIndex |= U32_4x(1) & (tBoxMax.x == tMin); 9 | - BoxSurfaceIndex |= U32_4x(2) & (tBoxMin.y == tMin); 10 | - BoxSurfaceIndex |= U32_4x(3) & (tBoxMax.y == tMin); 11 | - BoxSurfaceIndex |= U32_4x(4) & (tBoxMin.z == tMin); 12 | - BoxSurfaceIndex |= U32_4x(5) & (tBoxMax.z == tMin); 13 | + f32_4x BoxSurfaceIndex = ZeroF32_4x(); 14 | + f32_4x RunningMask = (tBoxMin.x == tMin); 15 | + 16 | + f32_4x ThisMask = (tBoxMax.x == tMin); 17 | + BoxSurfaceIndex |= U32_4x(1) & AndNot(ThisMask, RunningMask); 18 | + RunningMask |= ThisMask; 19 | + 20 | + ThisMask = (tBoxMin.y == tMin); 21 | + BoxSurfaceIndex |= U32_4x(2) & AndNot(ThisMask, RunningMask); 22 | + RunningMask |= ThisMask; 23 | + 24 | + ThisMask = (tBoxMax.y == tMin); 25 | + BoxSurfaceIndex |= U32_4x(3) & AndNot(ThisMask, RunningMask); 26 | + RunningMask |= ThisMask; 27 | + 28 | + ThisMask = (tBoxMin.z == tMin); 29 | + BoxSurfaceIndex |= U32_4x(4) & AndNot(ThisMask, RunningMask); 30 | + RunningMask |= ThisMask; 31 | + 32 | + ThisMask = (tBoxMax.z == tMin); 33 | + BoxSurfaceIndex |= U32_4x(5) & AndNot(ThisMask, RunningMask); 34 | 35 | Result.tRay = Select(Result.tRay, Mask, tMin); 36 | Result.Hit |= Mask; 37 | -------------------------------------------------------------------------------- /patches/handmade_memory.h.day541.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_memory.h 2020-06-14 20:49:47.000000000 -0700 2 | +++ handmade_memory.h 2020-06-14 20:49:42.000000000 -0700 3 | @@ -132,14 +132,14 @@ 4 | #define INTERNAL_MEMORY_PASS 5 | #endif 6 | 7 | -#define PushStruct(Arena, type, ...) (type *)PushSize_(DEBUG_MEMORY_NAME("PushStruct") Arena, sizeof(type), __VA_ARGS__) 8 | -#define PushArray(Arena, Count, type, ...) (type *)PushSize_(DEBUG_MEMORY_NAME("PushArray") Arena, (Count)*sizeof(type), __VA_ARGS__) 9 | -#define PushSize(Arena, Size, ...) PushSize_(DEBUG_MEMORY_NAME("PushSize") Arena, Size, __VA_ARGS__) 10 | +#define PushStruct(Arena, type, ...) (type *)PushSize_(DEBUG_MEMORY_NAME("PushStruct") Arena, sizeof(type), ## __VA_ARGS__) 11 | +#define PushArray(Arena, Count, type, ...) (type *)PushSize_(DEBUG_MEMORY_NAME("PushArray") Arena, (Count)*sizeof(type), ## __VA_ARGS__) 12 | +#define PushSize(Arena, Size, ...) PushSize_(DEBUG_MEMORY_NAME("PushSize") Arena, Size, ## __VA_ARGS__) 13 | #define PushCopy(...) PushCopy_(DEBUG_MEMORY_NAME("PushCopy") __VA_ARGS__) 14 | #define PushStringZ(...) PushStringZ_(DEBUG_MEMORY_NAME("PushStringZ") __VA_ARGS__) 15 | #define PushString(...) PushString_(DEBUG_MEMORY_NAME("PushString") __VA_ARGS__) 16 | #define PushBuffer(...) PushBuffer_(DEBUG_MEMORY_NAME("PushBuffer") __VA_ARGS__) 17 | -#define PushAndNullTerminate(...) PushAndNullTerminate_(DEBUG_MEMORY_NAME("PushAndNullTerminate") ## __VA_ARGS__) 18 | +#define PushAndNullTerminate(...) PushAndNullTerminate_(DEBUG_MEMORY_NAME("PushAndNullTerminate") __VA_ARGS__) 19 | #define BootstrapPushStruct(type, Member, ...) (type *)BootstrapPushSize_(DEBUG_MEMORY_NAME("BootstrapPushSize") sizeof(type), OffsetOf(type, Member), ## __VA_ARGS__) 20 | 21 | inline memory_index 22 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day373.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2017-04-01 11:37:10.000000000 -0700 2 | +++ handmade_opengl.cpp 2017-04-01 11:31:33.000000000 -0700 3 | @@ -105,7 +105,7 @@ 4 | Result.ShadingLanguageVersion = "(none)"; 5 | } 6 | 7 | - Result.Extensions = (char *)glGetString(GL_EXTENSIONS); 8 | + Result.Extensions = ""; //(char *)glGetString(GL_EXTENSIONS); 9 | 10 | for(char *At = Result.Extensions; 11 | *At; 12 | @@ -705,7 +705,7 @@ 13 | 14 | char Defines[1024]; 15 | FormatString(sizeof(Defines), Defines, 16 | - "#version 130\n" 17 | + "#version 150\n" 18 | "#define ShaderSimTexWriteSRGB %d\n" 19 | "#define ShaderSimTexReadSRGB %d\n", 20 | ShaderSimTexWriteSRGB, 21 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day374.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2017-04-01 22:11:32.000000000 -0700 2 | +++ handmade_opengl.cpp 2017-04-01 22:13:05.000000000 -0700 3 | @@ -704,7 +704,7 @@ 4 | 5 | char Defines[1024]; 6 | FormatString(sizeof(Defines), Defines, 7 | - "#version 130\n" 8 | + "#version 150\n" 9 | "#define ShaderSimTexWriteSRGB %d\n" 10 | "#define ShaderSimTexReadSRGB %d\n", 11 | ShaderSimTexWriteSRGB, 12 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day375.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2017-04-04 10:54:54.000000000 -0700 2 | +++ handmade_opengl.cpp 2017-04-04 10:55:13.000000000 -0700 3 | @@ -689,7 +689,7 @@ 4 | 5 | char Defines[1024]; 6 | FormatString(sizeof(Defines), Defines, 7 | - "#version 130\n" 8 | + "#version 150\n" 9 | "#define ShaderSimTexWriteSRGB %d\n" 10 | "#define ShaderSimTexReadSRGB %d\n", 11 | ShaderSimTexWriteSRGB, 12 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day380.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2017-04-29 16:31:43.000000000 -0400 2 | +++ handmade_opengl.cpp 2017-04-29 16:34:46.000000000 -0400 3 | @@ -669,7 +669,7 @@ 4 | { 5 | char Defines[1024]; 6 | FormatString(sizeof(Defines), Defines, 7 | - "#version 130\n" 8 | + "#version 150\n" 9 | "#define ShaderSimTexWriteSRGB %d\n" 10 | "#define ShaderSimTexReadSRGB %d\n" 11 | "#define DepthPeel %d\n", 12 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day384.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2017-05-09 12:41:47.000000000 -0400 2 | +++ handmade_opengl.cpp 2017-05-09 12:42:19.000000000 -0400 3 | @@ -608,7 +608,7 @@ 4 | { 5 | char Defines[1024]; 6 | FormatString(sizeof(Defines), Defines, 7 | - "#version 130\n" 8 | + "#version 150\n" 9 | "#define ShaderSimTexWriteSRGB %d\n" 10 | "#define ShaderSimTexReadSRGB %d\n" 11 | "#define DepthPeel %d\n", 12 | @@ -728,7 +728,7 @@ 13 | { 14 | char Defines[1024]; 15 | FormatString(sizeof(Defines), Defines, 16 | - "#version 130\n" 17 | + "#version 150\n" 18 | "#define ShaderSimTexWriteSRGB %d\n" 19 | "#define ShaderSimTexReadSRGB %d\n" 20 | "#define DepthPeel %d\n", 21 | @@ -813,7 +813,7 @@ 22 | { 23 | char Defines[1024]; 24 | FormatString(sizeof(Defines), Defines, 25 | - "#version 130\n" 26 | + "#version 150\n" 27 | "#define ShaderSimTexWriteSRGB %d\n" 28 | "#define ShaderSimTexReadSRGB %d\n", 29 | OpenGL.ShaderSimTexWriteSRGB, 30 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day387.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2017-06-06 10:02:32.000000000 -0400 2 | +++ handmade_opengl.cpp 2017-06-06 10:03:07.000000000 -0400 3 | @@ -611,7 +611,7 @@ 4 | { 5 | char Defines[1024]; 6 | FormatString(sizeof(Defines), Defines, 7 | - "#version 130\n" 8 | + "#version 150\n" 9 | "#define ShaderSimTexWriteSRGB %d\n" 10 | "#define ShaderSimTexReadSRGB %d\n" 11 | "#define DepthPeel %d\n", 12 | @@ -742,7 +742,7 @@ 13 | { 14 | char Defines[1024]; 15 | FormatString(sizeof(Defines), Defines, 16 | - "#version 130\n" 17 | + "#version 150\n" 18 | "#define ShaderSimTexWriteSRGB %d\n" 19 | "#define ShaderSimTexReadSRGB %d\n" 20 | "#define DepthPeel %d\n", 21 | @@ -957,7 +957,7 @@ 22 | { 23 | char Defines[1024]; 24 | FormatString(sizeof(Defines), Defines, 25 | - "#version 130\n" 26 | + "#version 150\n" 27 | "#define ShaderSimTexWriteSRGB %d\n" 28 | "#define ShaderSimTexReadSRGB %d\n", 29 | OpenGL.ShaderSimTexWriteSRGB, 30 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day388.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-02 00:07:03.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-02 00:05:39.000000000 -0400 3 | @@ -612,7 +612,7 @@ 4 | { 5 | char Defines[1024]; 6 | FormatString(sizeof(Defines), Defines, 7 | - "#version 130\n" 8 | + "#version 150\n" 9 | "#define ShaderSimTexWriteSRGB %d\n" 10 | "#define ShaderSimTexReadSRGB %d\n" 11 | "#define DepthPeel %d\n", 12 | @@ -733,7 +733,7 @@ 13 | { 14 | char Defines[1024]; 15 | FormatString(sizeof(Defines), Defines, 16 | - "#version 130\n" 17 | + "#version 150\n" 18 | "#define ShaderSimTexWriteSRGB %d\n" 19 | "#define ShaderSimTexReadSRGB %d\n" 20 | "#define DepthPeel %d\n", 21 | @@ -861,7 +861,8 @@ 22 | DepthMax = max(DepthMax, Depth); 23 | } 24 | 25 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 26 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 27 | + gl_FragDepth = DepthMax; 28 | 29 | v4 CombinedColor = V4(0, 0, 0, 0); 30 | for(s32 SampleIndex = 0; 31 | @@ -952,7 +953,7 @@ 32 | { 33 | char Defines[1024]; 34 | FormatString(sizeof(Defines), Defines, 35 | - "#version 130\n" 36 | + "#version 150\n" 37 | "#define ShaderSimTexWriteSRGB %d\n" 38 | "#define ShaderSimTexReadSRGB %d\n", 39 | OpenGL.ShaderSimTexWriteSRGB, 40 | @@ -1360,7 +1361,7 @@ 41 | GL_STREAM_DRAW); 42 | 43 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 44 | - f32 AlphaThreshold = 0.0f; 45 | + f32 AlphaThreshold = 0.02f; 46 | if(Peeling) 47 | { 48 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 49 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day393.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-02 02:20:00.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-02 02:19:53.000000000 -0400 3 | @@ -676,7 +676,7 @@ 4 | { 5 | char Defines[1024]; 6 | FormatString(sizeof(Defines), Defines, 7 | - "#version 130\n" 8 | + "#version 150\n" 9 | "#define ShaderSimTexWriteSRGB %d\n" 10 | "#define ShaderSimTexReadSRGB %d\n" 11 | "#define DepthPeel %d\n", 12 | @@ -841,7 +841,7 @@ 13 | { 14 | char Defines[1024]; 15 | FormatString(sizeof(Defines), Defines, 16 | - "#version 130\n" 17 | + "#version 150\n" 18 | "#define ShaderSimTexWriteSRGB %d\n" 19 | "#define ShaderSimTexReadSRGB %d\n" 20 | "#define DepthPeel %d\n", 21 | @@ -965,7 +965,8 @@ 22 | DepthMax = max(DepthMax, Depth); 23 | } 24 | 25 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 26 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 27 | + gl_FragDepth = DepthMax; 28 | 29 | v4 CombinedColor = V4(0, 0, 0, 0); 30 | for(s32 SampleIndex = 0; 31 | @@ -1052,7 +1053,7 @@ 32 | { 33 | char Defines[1024]; 34 | FormatString(sizeof(Defines), Defines, 35 | - "#version 130\n" 36 | + "#version 150\n" 37 | "#define ShaderSimTexWriteSRGB %d\n" 38 | "#define ShaderSimTexReadSRGB %d\n", 39 | OpenGL.ShaderSimTexWriteSRGB, 40 | @@ -1523,7 +1524,7 @@ 41 | GL_STREAM_DRAW); 42 | 43 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 44 | - f32 AlphaThreshold = 0.0f; 45 | + f32 AlphaThreshold = 0.02f; 46 | if(Peeling) 47 | { 48 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 49 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day394.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-02 13:25:30.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-02 13:25:17.000000000 -0400 3 | @@ -693,7 +693,7 @@ 4 | { 5 | char Defines[1024]; 6 | FormatString(sizeof(Defines), Defines, 7 | - "#version 130\n" 8 | + "#version 150\n" 9 | "#define ShaderSimTexWriteSRGB %d\n" 10 | "#define ShaderSimTexReadSRGB %d\n" 11 | "#define DepthPeel %d\n", 12 | @@ -858,7 +858,7 @@ 13 | { 14 | char Defines[1024]; 15 | FormatString(sizeof(Defines), Defines, 16 | - "#version 130\n" 17 | + "#version 150\n" 18 | "#define ShaderSimTexWriteSRGB %d\n" 19 | "#define ShaderSimTexReadSRGB %d\n" 20 | "#define DepthPeel %d\n", 21 | @@ -982,7 +982,8 @@ 22 | DepthMax = max(DepthMax, Depth); 23 | } 24 | 25 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 26 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 27 | + gl_FragDepth = DepthMax; 28 | 29 | v4 CombinedColor = V4(0, 0, 0, 0); 30 | for(s32 SampleIndex = 0; 31 | @@ -1069,7 +1070,7 @@ 32 | { 33 | char Defines[1024]; 34 | FormatString(sizeof(Defines), Defines, 35 | - "#version 130\n" 36 | + "#version 150\n" 37 | "#define ShaderSimTexWriteSRGB %d\n" 38 | "#define ShaderSimTexReadSRGB %d\n", 39 | OpenGL.ShaderSimTexWriteSRGB, 40 | @@ -1121,6 +1122,7 @@ 41 | char *FragmentCode = R"FOO( 42 | // Fragment code 43 | uniform v3 LightP; 44 | + out vec4 FragData[4]; 45 | void main(void) 46 | { 47 | v3 FrontEmit = V3(0, 0, 0); 48 | @@ -1141,10 +1143,10 @@ 49 | NP = V3(1, 0, 0); 50 | } 51 | 52 | - gl_FragData[0].rgb = FrontEmit; 53 | - gl_FragData[1].rgb = BackEmit; 54 | - gl_FragData[2].rgb = SurfaceColor; 55 | - gl_FragData[3].rgb = NP; 56 | + FragData[0].rgb = FrontEmit; 57 | + FragData[1].rgb = BackEmit; 58 | + FragData[2].rgb = SurfaceColor; 59 | + FragData[3].rgb = NP; 60 | } 61 | )FOO"; 62 | 63 | @@ -1178,6 +1180,7 @@ 64 | uniform sampler2D SourceSurfaceColorTex; 65 | uniform sampler2D SourceNPTex; 66 | smooth in vec2 FragUV; 67 | + out vec4 FragData[4]; 68 | void main(void) 69 | { 70 | v3 SourceFrontEmit = texture(SourceFrontEmitTex, FragUV).rgb; 71 | @@ -1190,10 +1193,10 @@ 72 | v3 SurfaceColor = SourceSurfaceColor; 73 | v3 NP = SourceNP; 74 | 75 | - gl_FragData[0].rgb = FrontEmit; 76 | - gl_FragData[1].rgb = BackEmit; 77 | - gl_FragData[2].rgb = SurfaceColor; 78 | - gl_FragData[3].rgb = NP; 79 | + FragData[0].rgb = FrontEmit; 80 | + FragData[1].rgb = BackEmit; 81 | + FragData[2].rgb = SurfaceColor; 82 | + FragData[3].rgb = NP; 83 | } 84 | )FOO"; 85 | 86 | @@ -1741,7 +1744,7 @@ 87 | GL_STREAM_DRAW); 88 | 89 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 90 | - f32 AlphaThreshold = 0.0f; 91 | + f32 AlphaThreshold = 0.02f; 92 | if(Peeling) 93 | { 94 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 95 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day395.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-02 16:05:14.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-02 16:05:10.000000000 -0400 3 | @@ -709,7 +709,7 @@ 4 | { 5 | char Defines[1024]; 6 | FormatString(sizeof(Defines), Defines, 7 | - "#version 130\n" 8 | + "#version 150\n" 9 | "#define ShaderSimTexWriteSRGB %d\n" 10 | "#define ShaderSimTexReadSRGB %d\n" 11 | "#define DepthPeel %d\n", 12 | @@ -874,7 +874,7 @@ 13 | { 14 | char Defines[1024]; 15 | FormatString(sizeof(Defines), Defines, 16 | - "#version 130\n" 17 | + "#version 150\n" 18 | "#define ShaderSimTexWriteSRGB %d\n" 19 | "#define ShaderSimTexReadSRGB %d\n" 20 | "#define DepthPeel %d\n", 21 | @@ -998,7 +998,8 @@ 22 | DepthMax = max(DepthMax, Depth); 23 | } 24 | 25 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 26 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 27 | + gl_FragDepth = DepthMax; 28 | 29 | v4 CombinedColor = V4(0, 0, 0, 0); 30 | for(s32 SampleIndex = 0; 31 | @@ -1085,7 +1086,7 @@ 32 | { 33 | char Defines[1024]; 34 | FormatString(sizeof(Defines), Defines, 35 | - "#version 130\n" 36 | + "#version 150\n" 37 | "#define ShaderSimTexWriteSRGB %d\n" 38 | "#define ShaderSimTexReadSRGB %d\n", 39 | OpenGL.ShaderSimTexWriteSRGB, 40 | @@ -1137,6 +1138,7 @@ 41 | char *FragmentCode = R"FOO( 42 | // Fragment code 43 | uniform v3 LightP; 44 | + out vec4 FragData[4]; 45 | 46 | v3 FrontEmit = V3(0, 0, 0); 47 | v3 BackEmit = V3(0, 0, 0); 48 | @@ -1163,10 +1165,10 @@ 49 | { 50 | Light(LightP.xy, 10.0f, V3(100.0f, 0, 0), V3(0, 100.0f, 0), V3(1, 0, 0)); 51 | Light(LightP.xy + V2(0.5f, 0.0f), 10.0f, V3(0, 10.0f, 0), V3(0, 0, 10.0f), V3(0, 1, 1)); 52 | - gl_FragData[0].rgb = FrontEmit; 53 | - gl_FragData[1].rgb = BackEmit; 54 | - gl_FragData[2].rgb = SurfaceColor; 55 | - gl_FragData[3].rgb = NP; 56 | + FragData[0].rgb = FrontEmit; 57 | + FragData[1].rgb = BackEmit; 58 | + FragData[2].rgb = SurfaceColor; 59 | + FragData[3].rgb = NP; 60 | } 61 | )FOO"; 62 | 63 | @@ -1200,6 +1202,7 @@ 64 | uniform sampler2D SourceSurfaceColorTex; 65 | uniform sampler2D SourceNPTex; 66 | smooth in vec2 FragUV; 67 | + out vec4 FragData[4]; 68 | 69 | v3 ManualSample(sampler2D Sampler) 70 | { 71 | @@ -1219,10 +1222,10 @@ 72 | v3 SurfaceColor = SourceSurfaceColor; 73 | v3 NP = SourceNP; 74 | 75 | - gl_FragData[0].rgb = FrontEmit; 76 | - gl_FragData[1].rgb = BackEmit; 77 | - gl_FragData[2].rgb = SurfaceColor; 78 | - gl_FragData[3].rgb = NP; 79 | + FragData[0].rgb = FrontEmit; 80 | + FragData[1].rgb = BackEmit; 81 | + FragData[2].rgb = SurfaceColor; 82 | + FragData[3].rgb = NP; 83 | } 84 | )FOO"; 85 | 86 | @@ -1265,6 +1268,7 @@ 87 | uniform v2 UVStep; 88 | 89 | smooth in vec2 FragUV; 90 | + out vec4 FragData[2]; 91 | 92 | struct light_value 93 | { 94 | @@ -1325,8 +1329,8 @@ 95 | TransferLight(Up.P, Up.N, Up.BackEmit, RefP, RefN, RefC) + 96 | TransferLight(Down.P, Down.N, Down.BackEmit, RefP, RefN, RefC)); 97 | 98 | - gl_FragData[0].rgb = DestFrontEmit; 99 | - gl_FragData[1].rgb = DestBackEmit; 100 | + FragData[0].rgb = DestFrontEmit; 101 | + FragData[1].rgb = DestBackEmit; 102 | } 103 | )FOO"; 104 | 105 | @@ -1895,7 +1899,7 @@ 106 | GL_STREAM_DRAW); 107 | 108 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 109 | - f32 AlphaThreshold = 0.0f; 110 | + f32 AlphaThreshold = 0.02f; 111 | if(Peeling) 112 | { 113 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 114 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day396.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-03 01:14:34.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-03 01:14:31.000000000 -0400 3 | @@ -751,7 +751,7 @@ 4 | { 5 | char Defines[1024]; 6 | FormatString(sizeof(Defines), Defines, 7 | - "#version 130\n" 8 | + "#version 150\n" 9 | "#define ShaderSimTexWriteSRGB %d\n" 10 | "#define ShaderSimTexReadSRGB %d\n" 11 | "#define DepthPeel %d\n", 12 | @@ -821,7 +821,7 @@ 13 | smooth in vec3 WorldP; 14 | smooth in vec3 WorldN; 15 | 16 | - layout(location = 0) out v4 BlendUnitColor[3]; 17 | + out v4 BlendUnitColor[3]; 18 | 19 | void main(void) 20 | { 21 | @@ -897,7 +897,7 @@ 22 | { 23 | char Defines[1024]; 24 | FormatString(sizeof(Defines), Defines, 25 | - "#version 130\n" 26 | + "#version 150\n" 27 | "#define ShaderSimTexWriteSRGB %d\n" 28 | "#define ShaderSimTexReadSRGB %d\n" 29 | "#define DepthPeel %d\n", 30 | @@ -1010,7 +1010,7 @@ 31 | uniform sampler2DMS DepthSampler; 32 | uniform s32 SampleCount; 33 | 34 | - layout(location = 0) out v4 BlendUnitColor[3]; 35 | + out v4 BlendUnitColor[3]; 36 | void main(void) 37 | { 38 | 39 | @@ -1027,7 +1027,8 @@ 40 | DepthMax = max(DepthMax, Depth); 41 | } 42 | 43 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 44 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 45 | + gl_FragDepth = DepthMax; 46 | 47 | v4 CombinedColor = V4(0, 0, 0, 0); 48 | v4 CombinedEmit = V4(0, 0, 0, 0); 49 | @@ -1123,7 +1124,7 @@ 50 | { 51 | char Defines[1024]; 52 | FormatString(sizeof(Defines), Defines, 53 | - "#version 130\n" 54 | + "#version 150\n" 55 | "#define ShaderSimTexWriteSRGB %d\n" 56 | "#define ShaderSimTexReadSRGB %d\n", 57 | OpenGL.ShaderSimTexWriteSRGB, 58 | @@ -1181,7 +1182,7 @@ 59 | // Fragment code 60 | uniform v3 LightP; 61 | 62 | - layout(location = 0) out v4 BlendUnitColor[4]; 63 | + out v4 BlendUnitColor[4]; 64 | 65 | v3 FrontEmit = V3(0, 0, 0); 66 | v3 BackEmit = V3(0, 0, 0); 67 | @@ -1246,7 +1247,7 @@ 68 | uniform sampler2D SourceNPTex; 69 | smooth in vec2 FragUV; 70 | 71 | - layout(location = 0) out v4 BlendUnitColor[4]; 72 | + out v4 BlendUnitColor[4]; 73 | 74 | v3 ManualSample(sampler2D Sampler) 75 | { 76 | @@ -1349,7 +1350,7 @@ 77 | uniform v2 SourceUVStep; 78 | 79 | smooth in vec2 FragUV; 80 | - layout(location = 0) out v4 BlendUnitColor[2]; 81 | + out v4 BlendUnitColor[2]; 82 | 83 | struct light_value 84 | { 85 | @@ -1989,7 +1990,7 @@ 86 | GL_STREAM_DRAW); 87 | 88 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 89 | - f32 AlphaThreshold = 0.0f; 90 | + f32 AlphaThreshold = 0.02f; 91 | if(Peeling) 92 | { 93 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 94 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day397.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-03 01:53:57.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-03 01:53:54.000000000 -0400 3 | @@ -774,7 +774,7 @@ 4 | { 5 | char Defines[1024]; 6 | FormatString(sizeof(Defines), Defines, 7 | - "#version 130\n" 8 | + "#version 150\n" 9 | "#define ShaderSimTexWriteSRGB %d\n" 10 | "#define ShaderSimTexReadSRGB %d\n" 11 | "#define DepthPeel %d\n", 12 | @@ -844,7 +844,7 @@ 13 | smooth in vec3 WorldP; 14 | smooth in vec3 WorldN; 15 | 16 | - layout(location = 0) out v4 BlendUnitColor[3]; 17 | + out v4 BlendUnitColor[3]; 18 | 19 | void main(void) 20 | { 21 | @@ -920,7 +920,7 @@ 22 | { 23 | char Defines[1024]; 24 | FormatString(sizeof(Defines), Defines, 25 | - "#version 130\n" 26 | + "#version 150\n" 27 | "#define ShaderSimTexWriteSRGB %d\n" 28 | "#define ShaderSimTexReadSRGB %d\n" 29 | "#define DepthPeel %d\n", 30 | @@ -1029,7 +1029,7 @@ 31 | uniform sampler2DMS DepthSampler; 32 | uniform s32 SampleCount; 33 | 34 | - layout(location = 0) out v4 BlendUnitColor[3]; 35 | + out v4 BlendUnitColor[3]; 36 | void main(void) 37 | { 38 | 39 | @@ -1046,7 +1046,8 @@ 40 | DepthMax = max(DepthMax, Depth); 41 | } 42 | 43 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 44 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 45 | + gl_FragDepth = DepthMax; 46 | 47 | v4 CombinedColor = V4(0, 0, 0, 0); 48 | v4 CombinedEmit = V4(0, 0, 0, 0); 49 | @@ -1138,7 +1139,7 @@ 50 | { 51 | char Defines[1024]; 52 | FormatString(sizeof(Defines), Defines, 53 | - "#version 130\n" 54 | + "#version 150\n" 55 | "#define ShaderSimTexWriteSRGB %d\n" 56 | "#define ShaderSimTexReadSRGB %d\n", 57 | OpenGL.ShaderSimTexWriteSRGB, 58 | @@ -1196,7 +1197,7 @@ 59 | // Fragment code 60 | uniform v3 LightP; 61 | 62 | - layout(location = 0) out v4 BlendUnitColor[4]; 63 | + out v4 BlendUnitColor[4]; 64 | 65 | v3 FrontEmit = V3(0, 0, 0); 66 | v3 BackEmit = V3(0, 0, 0); 67 | @@ -1239,7 +1240,7 @@ 68 | { 69 | char Defines[1024]; 70 | FormatString(sizeof(Defines), Defines, 71 | - "#version 130\n"); 72 | + "#version 150\n"); 73 | 74 | char *VertexCode = R"FOO( 75 | // Vertex code 76 | @@ -1258,7 +1259,7 @@ 77 | uniform sampler2D EmitSampler; 78 | uniform sampler2D NPLSampler; 79 | 80 | - layout(location = 0) out v4 BlendUnitColor[4]; 81 | + out v4 BlendUnitColor[4]; 82 | 83 | void main(void) 84 | { 85 | @@ -1323,7 +1324,7 @@ 86 | uniform sampler2D SourceNPTex; 87 | smooth in vec2 FragUV; 88 | 89 | - layout(location = 0) out v4 BlendUnitColor[4]; 90 | + out v4 BlendUnitColor[4]; 91 | 92 | v3 ManualSample(sampler2D Sampler) 93 | { 94 | @@ -1423,7 +1424,7 @@ 95 | uniform v2 SourceUVStep; 96 | 97 | smooth in vec2 FragUV; 98 | - layout(location = 0) out v4 BlendUnitColor[2]; 99 | + out v4 BlendUnitColor[2]; 100 | 101 | struct light_value 102 | { 103 | @@ -2078,7 +2079,7 @@ 104 | GL_STREAM_DRAW); 105 | 106 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 107 | - f32 AlphaThreshold = 0.0f; 108 | + f32 AlphaThreshold = 0.02f; 109 | if(Peeling) 110 | { 111 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 112 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day398.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-03 02:12:46.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-03 02:12:41.000000000 -0400 3 | @@ -803,7 +803,7 @@ 4 | { 5 | char Defines[1024]; 6 | FormatString(sizeof(Defines), Defines, 7 | - "#version 130\n" 8 | + "#version 150\n" 9 | "#define ShaderSimTexWriteSRGB %d\n" 10 | "#define ShaderSimTexReadSRGB %d\n" 11 | "#define DepthPeel %d\n", 12 | @@ -873,7 +873,7 @@ 13 | smooth in vec3 WorldP; 14 | smooth in vec3 WorldN; 15 | 16 | - layout(location = 0) out v4 BlendUnitColor[3]; 17 | + out v4 BlendUnitColor[3]; 18 | 19 | void main(void) 20 | { 21 | @@ -948,7 +948,7 @@ 22 | { 23 | char Defines[1024]; 24 | FormatString(sizeof(Defines), Defines, 25 | - "#version 130\n" 26 | + "#version 150\n" 27 | "#define ShaderSimTexWriteSRGB %d\n" 28 | "#define ShaderSimTexReadSRGB %d\n" 29 | "#define DepthPeel %d\n", 30 | @@ -1118,7 +1118,7 @@ 31 | uniform sampler2DMS DepthSampler; 32 | uniform s32 SampleCount; 33 | 34 | - layout(location = 0) out v4 BlendUnitColor[3]; 35 | + out v4 BlendUnitColor[3]; 36 | void main(void) 37 | { 38 | 39 | @@ -1135,7 +1135,8 @@ 40 | DepthMax = max(DepthMax, Depth); 41 | } 42 | 43 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 44 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 45 | + gl_FragDepth = DepthMax; 46 | 47 | v4 CombinedColor = V4(0, 0, 0, 0); 48 | v4 CombinedEmit = V4(0, 0, 0, 0); 49 | @@ -1227,7 +1228,7 @@ 50 | { 51 | char Defines[1024]; 52 | FormatString(sizeof(Defines), Defines, 53 | - "#version 130\n" 54 | + "#version 150\n" 55 | "#define ShaderSimTexWriteSRGB %d\n" 56 | "#define ShaderSimTexReadSRGB %d\n", 57 | OpenGL.ShaderSimTexWriteSRGB, 58 | @@ -1285,7 +1286,7 @@ 59 | // Fragment code 60 | uniform v3 LightP; 61 | 62 | - layout(location = 0) out v4 BlendUnitColor[4]; 63 | + out v4 BlendUnitColor[4]; 64 | 65 | v3 FrontEmit = V3(0, 0, 0); 66 | v3 BackEmit = V3(0, 0, 0); 67 | @@ -1328,7 +1329,7 @@ 68 | { 69 | char Defines[1024]; 70 | FormatString(sizeof(Defines), Defines, 71 | - "#version 130\n"); 72 | + "#version 150\n"); 73 | 74 | char *VertexCode = R"FOO( 75 | // Vertex code 76 | @@ -1350,7 +1351,7 @@ 77 | uniform sampler2D EmitSampler; 78 | uniform sampler2D NPLSampler; 79 | 80 | - layout(location = 0) out v4 BlendUnitColor[4]; 81 | + out v4 BlendUnitColor[4]; 82 | 83 | smooth in v2 FragUV; 84 | 85 | @@ -1422,7 +1423,7 @@ 86 | uniform sampler2D SourceNPTex; 87 | smooth in vec2 FragUV; 88 | 89 | - layout(location = 0) out v4 BlendUnitColor[4]; 90 | + out v4 BlendUnitColor[4]; 91 | 92 | v3 ManualSample(sampler2D Sampler) 93 | { 94 | @@ -1486,7 +1487,7 @@ 95 | uniform v2 SourceUVStep; 96 | 97 | smooth in vec2 FragUV; 98 | - layout(location = 0) out v4 BlendUnitColor[2]; 99 | + out v4 BlendUnitColor[2]; 100 | 101 | struct light_value 102 | { 103 | @@ -2140,7 +2141,7 @@ 104 | GL_STREAM_DRAW); 105 | 106 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 107 | - f32 AlphaThreshold = 0.0f; 108 | + f32 AlphaThreshold = 0.02f; 109 | if(Peeling) 110 | { 111 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 112 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day405.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-04 03:28:43.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-04 03:28:38.000000000 -0400 3 | @@ -1174,7 +1174,8 @@ 4 | DepthMax = max(DepthMax, Depth); 5 | } 6 | 7 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 8 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 9 | + gl_FragDepth = DepthMax; 10 | 11 | v4 CombinedColor = V4(0, 0, 0, 0); 12 | v4 CombinedEmit = V4(0, 0, 0, 0); 13 | @@ -2199,7 +2200,7 @@ 14 | GL_STREAM_DRAW); 15 | 16 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 17 | - f32 AlphaThreshold = 0.0f; 18 | + f32 AlphaThreshold = 0.02f; 19 | if(Peeling) 20 | { 21 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 22 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day410.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-04 17:30:55.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-04 17:30:51.000000000 -0400 3 | @@ -1262,7 +1262,8 @@ 4 | DepthMax = max(DepthMax, Depth); 5 | } 6 | 7 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 8 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 9 | + gl_FragDepth = DepthMax; 10 | 11 | v4 CombinedColor = V4(0, 0, 0, 0); 12 | v4 CombinedEmit = V4(0, 0, 0, 0); 13 | @@ -2309,7 +2310,7 @@ 14 | GL_STREAM_DRAW); 15 | 16 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 17 | - f32 AlphaThreshold = 0.0f; 18 | + f32 AlphaThreshold = 0.02f; 19 | if(Peeling) 20 | { 21 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 22 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day414.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-05 11:46:30.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-05 11:46:24.000000000 -0400 3 | @@ -1288,7 +1288,8 @@ 4 | DepthMax = max(DepthMax, Depth); 5 | } 6 | 7 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 8 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 9 | + gl_FragDepth = DepthMax; 10 | 11 | v4 CombinedColor = V4(0, 0, 0, 0); 12 | v4 CombinedEmit = V4(0, 0, 0, 0); 13 | @@ -2335,7 +2336,7 @@ 14 | GL_STREAM_DRAW); 15 | 16 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 17 | - f32 AlphaThreshold = 0.0f; 18 | + f32 AlphaThreshold = 0.02f; 19 | if(Peeling) 20 | { 21 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 22 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day415.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-05 12:35:48.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-05 12:35:46.000000000 -0400 3 | @@ -901,8 +901,8 @@ 4 | in v3 VertN; 5 | in v2 VertUV; 6 | in v4 VertColor; 7 | - in unsigned int VertLightIndex; 8 | - in unsigned int VertLightCount; 9 | + in uint VertLightIndex; 10 | + in uint VertLightCount; 11 | 12 | smooth out v2 FragUV; 13 | smooth out v4 FragColor; 14 | @@ -910,8 +910,8 @@ 15 | smooth out v3 WorldP; 16 | smooth out v3 WorldN; 17 | 18 | - flat out unsigned int FragLightIndex; 19 | - flat out unsigned int FragLightCount; 20 | + flat out uint FragLightIndex; 21 | + flat out uint FragLightCount; 22 | 23 | void main(void) 24 | { 25 | @@ -996,8 +996,8 @@ 26 | smooth in vec3 WorldP; 27 | smooth in vec3 WorldN; 28 | 29 | - flat in unsigned int FragLightIndex; 30 | - flat in unsigned int FragLightCount; 31 | + flat in uint FragLightIndex; 32 | + flat in uint FragLightCount; 33 | 34 | layout(location = 0) out v4 BlendUnitColor[3]; 35 | 36 | @@ -1377,7 +1377,8 @@ 37 | DepthMax = max(DepthMax, Depth); 38 | } 39 | 40 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 41 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 42 | + gl_FragDepth = DepthMax; 43 | 44 | v4 CombinedColor = V4(0, 0, 0, 0); 45 | v4 CombinedEmit = V4(0, 0, 0, 0); 46 | @@ -2424,7 +2425,7 @@ 47 | GL_STREAM_DRAW); 48 | 49 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 50 | - f32 AlphaThreshold = 0.0f; 51 | + f32 AlphaThreshold = 0.02f; 52 | if(Peeling) 53 | { 54 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 55 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day416.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-05 13:36:16.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-05 13:36:14.000000000 -0400 3 | @@ -1369,7 +1369,8 @@ 4 | DepthMax = max(DepthMax, Depth); 5 | } 6 | 7 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 8 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 9 | + gl_FragDepth = DepthMax; 10 | 11 | v4 CombinedColor = V4(0, 0, 0, 0); 12 | v4 CombinedEmit = V4(0, 0, 0, 0); 13 | @@ -2416,7 +2417,7 @@ 14 | GL_STREAM_DRAW); 15 | 16 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 17 | - f32 AlphaThreshold = 0.0f; 18 | + f32 AlphaThreshold = 0.02f; 19 | if(Peeling) 20 | { 21 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 22 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day420.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-06 14:23:14.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-06 14:23:09.000000000 -0400 3 | @@ -1277,7 +1277,8 @@ 4 | DepthMax = max(DepthMax, Depth); 5 | } 6 | 7 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 8 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 9 | + gl_FragDepth = DepthMax; 10 | 11 | v4 CombinedColor = V4(0, 0, 0, 0); 12 | v4 CombinedEmit = V4(0, 0, 0, 0); 13 | @@ -2305,7 +2306,7 @@ 14 | GL_STREAM_DRAW); 15 | 16 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 17 | - f32 AlphaThreshold = 0.0f; 18 | + f32 AlphaThreshold = 0.02f; 19 | if(Peeling) 20 | { 21 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 22 | -------------------------------------------------------------------------------- /patches/handmade_opengl.cpp.day430.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_opengl.cpp 2018-08-08 21:28:02.000000000 -0400 2 | +++ handmade_opengl.cpp 2018-08-08 21:28:00.000000000 -0400 3 | @@ -1281,7 +1281,8 @@ 4 | DepthMax = max(DepthMax, Depth); 5 | } 6 | 7 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 8 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 9 | + gl_FragDepth = DepthMax; 10 | 11 | v4 CombinedColor = V4(0, 0, 0, 0); 12 | v4 CombinedEmit = V4(0, 0, 0, 0); 13 | @@ -2312,7 +2313,7 @@ 14 | GL_STREAM_DRAW); 15 | 16 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 17 | - f32 AlphaThreshold = 0.0f; 18 | + f32 AlphaThreshold = 0.02f; 19 | if(Peeling) 20 | { 21 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 22 | -------------------------------------------------------------------------------- /patches/handmade_renderer_opengl.cpp.day471.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_renderer_opengl.cpp 2018-09-06 00:42:18.000000000 -0400 2 | +++ handmade_renderer_opengl.cpp 2018-09-06 00:42:15.000000000 -0400 3 | @@ -1250,7 +1250,8 @@ 4 | DepthMax = max(DepthMax, Depth); 5 | } 6 | 7 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 8 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 9 | + gl_FragDepth = DepthMax; 10 | 11 | v4 CombinedColor = V4(0, 0, 0, 0); 12 | v4 CombinedEmit = V4(0, 0, 0, 0); 13 | @@ -2277,7 +2278,8 @@ 14 | GL_STREAM_DRAW); 15 | 16 | zbias_program *Prog = &OpenGL.ZBiasNoDepthPeel; 17 | - f32 AlphaThreshold = 0.0f; 18 | + //f32 AlphaThreshold = 0.0f; 19 | + f32 AlphaThreshold = 0.02f; 20 | if(Peeling) 21 | { 22 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OnPeelIndex - 1); 23 | -------------------------------------------------------------------------------- /patches/handmade_renderer_opengl.cpp.day475.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_renderer_opengl.cpp 2018-09-17 23:49:35.000000000 -0400 2 | +++ handmade_renderer_opengl.cpp 2018-09-17 23:49:32.000000000 -0400 3 | @@ -1216,7 +1216,8 @@ 4 | DepthMax = max(DepthMax, Depth); 5 | } 6 | 7 | - gl_FragDepth = 0.5f*(DepthMin+DepthMax); 8 | + //gl_FragDepth = 0.5f*(DepthMin+DepthMax); 9 | + gl_FragDepth = DepthMax; 10 | 11 | v4 CombinedColor = V4(0, 0, 0, 0); 12 | v4 CombinedEmit = V4(0, 0, 0, 0); 13 | @@ -1985,7 +1986,8 @@ 14 | GL_STREAM_DRAW); 15 | 16 | zbias_program *Prog = &OpenGL->ZBiasNoDepthPeel; 17 | - f32 AlphaThreshold = 0.0f; 18 | + //f32 AlphaThreshold = 0.0f; 19 | + f32 AlphaThreshold = 0.02f; 20 | if(Peeling) 21 | { 22 | opengl_framebuffer *PeelBuffer = GetDepthPeelReadBuffer(OpenGL, OnPeelIndex - 1); 23 | -------------------------------------------------------------------------------- /patches/handmade_sampling_spheres.inl.day552.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_sampling_spheres.inl 2020-06-15 13:00:51.000000000 -0700 2 | +++ handmade_sampling_spheres.inl 2020-06-15 13:00:45.000000000 -0700 3 | @@ -9,7 +9,7 @@ 4 | f32 CubeSideWeight[LIGHT_SAMPLING_TOTAL_RAYS_PER_SPHERE][6]; 5 | }; 6 | 7 | -global alignas(16) f32 LightSamplingSphereFloatTable[] = 8 | +alignas(16) global f32 LightSamplingSphereFloatTable[] = 9 | { 10 | 0.200641f, 0.200641f, 0.200641f, 0.200641f, -0.732799f, -0.732799f, -0.732799f, -0.732799f, 0.650192f, 0.650192f, 0.650192f, 0.650192f, 11 | 0.139531f, 0.139531f, 0.139531f, 0.139531f, 0.142273f, 0.142273f, 0.142273f, 0.142273f, -0.979944f, -0.979944f, -0.979944f, -0.979944f, 12 | @@ -1452,4 +1452,4 @@ 13 | 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 14 | 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 15 | }; 16 | -global alignas(16) light_sampling_sphere *LightSamplingSphereTable = (light_sampling_sphere *)LightSamplingSphereFloatTable; 17 | +alignas(16) global light_sampling_sphere *LightSamplingSphereTable = (light_sampling_sphere *)LightSamplingSphereFloatTable; 18 | -------------------------------------------------------------------------------- /patches/handmade_simd.h.day434.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/handmade_simd.h 2018-08-09 17:06:27.000000000 -0400 2 | +++ handmade_simd.h 2018-08-09 17:06:23.000000000 -0400 3 | @@ -413,6 +413,18 @@ 4 | return(Result); 5 | } 6 | 7 | + 8 | +inline f32_4x 9 | +AndNot(f32_4x A, f32_4x B) // NOTE(casey): _B_ gets notted 10 | +{ 11 | + f32_4x Result; 12 | + 13 | + Result.P = _mm_andnot_ps(B.P, A.P); 14 | + 15 | + return(Result); 16 | +} 17 | + 18 | + 19 | inline f32_4x 20 | Select(f32_4x A, f32_4x Mask, f32_4x B) 21 | { 22 | -------------------------------------------------------------------------------- /patches/hhlightprof.cpp.day593.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/hhlightprof.cpp 2020-06-25 12:30:24.000000000 -0700 2 | +++ hhlightprof.cpp 2020-06-25 12:30:12.000000000 -0700 3 | @@ -12,6 +12,12 @@ 4 | #undef HANDMADE_SLOW 5 | #define HANDMADE_SLOW 0 6 | 7 | +#ifdef HANDMADE_OSX 8 | +#include 9 | +#include 10 | +#include 11 | +#endif 12 | + 13 | #include "handmade_platform.h" 14 | #include "handmade_intrinsics.h" 15 | #include "handmade_math.h" 16 | @@ -35,7 +41,9 @@ 17 | #include "handmade_lighting.h" 18 | #include "handmade_config.h" 19 | 20 | +#ifndef HANDMADE_OSX 21 | #include 22 | +#endif 23 | 24 | #define DevMode_lighting 0 25 | 26 | @@ -123,6 +131,46 @@ 27 | return(Result); 28 | } 29 | 30 | +#ifdef HANDMADE_OSX 31 | +typedef struct { 32 | + uint64_t QuadPart; 33 | +} LARGE_INTEGER; 34 | + 35 | + 36 | +void QueryPerformanceCounter(LARGE_INTEGER* Counter) 37 | +{ 38 | + *((uint64_t*)Counter) = mach_absolute_time(); 39 | +} 40 | + 41 | +// Dummy function to possibly avoid extra patches 42 | +// while this file is getting changed frequently. 43 | +void QueryPerformanceFrequency(LARGE_INTEGER* Counter) 44 | +{ 45 | + *((uint64_t*)Counter) = 0; 46 | +} 47 | + 48 | +float OSXGetSecondsElapsed(u64 Then, u64 Now) 49 | +{ 50 | + // This can overflow if used for long elapsed times. 51 | + // Better to use 128-bit arithmetic to do the 52 | + // calculation. 53 | + static mach_timebase_info_data_t tb; 54 | + 55 | + u64 Elapsed = Now - Then; 56 | + 57 | + if (tb.denom == 0) 58 | + { 59 | + // First time we need to get the timebase 60 | + mach_timebase_info(&tb); 61 | + } 62 | + 63 | + u64 Nanos = Elapsed * tb.numer / tb.denom; 64 | + float Result = (float)Nanos * 1.0E-9; 65 | + 66 | + return Result; 67 | +} 68 | +#endif 69 | + 70 | internal void 71 | ProfileRun(u32 RepeatCount) 72 | { 73 | @@ -209,8 +257,12 @@ 74 | } 75 | else 76 | { 77 | +#ifdef HANDMADE_OSX 78 | + float TotalSeconds = OSXGetSecondsElapsed(StartTime.QuadPart, EndTime.QuadPart); 79 | +#else 80 | double Diff = (double)(EndTime.QuadPart - StartTime.QuadPart); 81 | double TotalSeconds = Diff / (double)Freq.QuadPart; 82 | +#endif 83 | fprintf(stdout, "Total Seconds Elapsed: %f\n", TotalSeconds); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /patches/hhlightprof.cpp.day594.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/hhlightprof.cpp 2020-06-25 22:21:54.000000000 -0700 2 | +++ hhlightprof.cpp 2020-06-25 22:21:51.000000000 -0700 3 | @@ -12,6 +12,12 @@ 4 | #undef HANDMADE_SLOW 5 | #define HANDMADE_SLOW 0 6 | 7 | +#ifdef HANDMADE_OSX 8 | +#include 9 | +#include 10 | +#include 11 | +#endif 12 | + 13 | #include "handmade_platform.h" 14 | #include "handmade_intrinsics.h" 15 | #include "handmade_math.h" 16 | @@ -35,7 +41,9 @@ 17 | #include "handmade_lighting.h" 18 | #include "handmade_config.h" 19 | 20 | +#ifndef HANDMADE_OSX 21 | #include 22 | +#endif 23 | #include 24 | #include 25 | #include 26 | @@ -134,6 +142,46 @@ 27 | return(Result); 28 | } 29 | 30 | +#ifdef HANDMADE_OSX 31 | +typedef struct { 32 | + uint64_t QuadPart; 33 | +} LARGE_INTEGER; 34 | + 35 | + 36 | +void QueryPerformanceCounter(LARGE_INTEGER* Counter) 37 | +{ 38 | + *((uint64_t*)Counter) = mach_absolute_time(); 39 | +} 40 | + 41 | +// Dummy function to possibly avoid extra patches 42 | +// while this file is getting changed frequently. 43 | +void QueryPerformanceFrequency(LARGE_INTEGER* Counter) 44 | +{ 45 | + *((uint64_t*)Counter) = 0; 46 | +} 47 | + 48 | +float OSXGetSecondsElapsed(u64 Then, u64 Now) 49 | +{ 50 | + // This can overflow if used for long elapsed times. 51 | + // Better to use 128-bit arithmetic to do the 52 | + // calculation. 53 | + static mach_timebase_info_data_t tb; 54 | + 55 | + u64 Elapsed = Now - Then; 56 | + 57 | + if (tb.denom == 0) 58 | + { 59 | + // First time we need to get the timebase 60 | + mach_timebase_info(&tb); 61 | + } 62 | + 63 | + u64 Nanos = Elapsed * tb.numer / tb.denom; 64 | + float Result = (float)Nanos * 1.0E-9; 65 | + 66 | + return Result; 67 | +} 68 | +#endif 69 | + 70 | internal void 71 | ProfileRun(u32 RepeatCount) 72 | { 73 | @@ -238,8 +286,12 @@ 74 | } 75 | else 76 | { 77 | +#ifdef HANDMADE_OSX 78 | + float TotalSeconds = OSXGetSecondsElapsed(StartTime.QuadPart, EndTime.QuadPart); 79 | +#else 80 | double Diff = (double)(EndTime.QuadPart - StartTime.QuadPart); 81 | double TotalSeconds = Diff / (double)Freq.QuadPart; 82 | +#endif 83 | fprintf(stdout, "Total Seconds Elapsed: %f\n", TotalSeconds); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /patches/hhlightprof.cpp.day595.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/hhlightprof.cpp 2020-06-25 22:32:00.000000000 -0700 2 | +++ hhlightprof.cpp 2020-06-25 22:31:32.000000000 -0700 3 | @@ -12,6 +12,12 @@ 4 | #undef HANDMADE_SLOW 5 | #define HANDMADE_SLOW 0 6 | 7 | +#if HANDMADE_OSX 8 | +#include 9 | +#include 10 | +#include 11 | +#endif 12 | + 13 | #include "handmade_platform.h" 14 | #include "handmade_intrinsics.h" 15 | #include "handmade_math.h" 16 | @@ -35,7 +41,9 @@ 17 | #include "handmade_lighting.h" 18 | #include "handmade_config.h" 19 | 20 | +#if !HANDMADE_OSX 21 | #include 22 | +#endif 23 | #include 24 | #include 25 | #include 26 | @@ -134,6 +142,46 @@ 27 | return(Result); 28 | } 29 | 30 | +#if HANDMADE_OSX 31 | +typedef struct { 32 | + uint64_t QuadPart; 33 | +} LARGE_INTEGER; 34 | + 35 | + 36 | +void QueryPerformanceCounter(LARGE_INTEGER* Counter) 37 | +{ 38 | + *((uint64_t*)Counter) = mach_absolute_time(); 39 | +} 40 | + 41 | +// Dummy function to possibly avoid extra patches 42 | +// while this file is getting changed frequently. 43 | +void QueryPerformanceFrequency(LARGE_INTEGER* Counter) 44 | +{ 45 | + *((uint64_t*)Counter) = 0; 46 | +} 47 | + 48 | +float OSXGetSecondsElapsed(u64 Then, u64 Now) 49 | +{ 50 | + // This can overflow if used for long elapsed times. 51 | + // Better to use 128-bit arithmetic to do the 52 | + // calculation. 53 | + static mach_timebase_info_data_t tb; 54 | + 55 | + u64 Elapsed = Now - Then; 56 | + 57 | + if (tb.denom == 0) 58 | + { 59 | + // First time we need to get the timebase 60 | + mach_timebase_info(&tb); 61 | + } 62 | + 63 | + u64 Nanos = Elapsed * tb.numer / tb.denom; 64 | + float Result = (float)Nanos * 1.0E-9; 65 | + 66 | + return Result; 67 | +} 68 | +#endif 69 | + 70 | internal void 71 | ProfileRun(u32 RepeatCount) 72 | { 73 | @@ -253,8 +301,12 @@ 74 | } 75 | else 76 | { 77 | +#if HANDMADE_OSX 78 | + float TotalSeconds = OSXGetSecondsElapsed(StartTime.QuadPart, EndTime.QuadPart); 79 | +#else 80 | double Diff = (double)(EndTime.QuadPart - StartTime.QuadPart); 81 | double TotalSeconds = Diff / (double)Freq.QuadPart; 82 | +#endif 83 | fprintf(stdout, "T:%.0f P:%.0f L:%.0f P/L:%.2f\n", 84 | (double)TotalPartitionsTested + (double)TotalLeavesTested, 85 | (double)TotalPartitionsTested, (double)TotalLeavesTested, 86 | -------------------------------------------------------------------------------- /patches/hhlightprof.cpp.day615.patch: -------------------------------------------------------------------------------- 1 | --- cpp/code/hhlightprof.cpp 2020-07-14 12:57:31.000000000 -0700 2 | +++ hhlightprof.cpp 2020-07-14 12:57:28.000000000 -0700 3 | @@ -12,6 +12,12 @@ 4 | #undef HANDMADE_SLOW 5 | #define HANDMADE_SLOW 0 6 | 7 | +#if HANDMADE_OSX 8 | +#include 9 | +#include 10 | +#include 11 | +#endif 12 | + 13 | #include "handmade_platform.h" 14 | #include "handmade_intrinsics.h" 15 | #include "handmade_math.h" 16 | @@ -37,7 +43,9 @@ 17 | #include "handmade_lighting.h" 18 | #include "handmade_config.h" 19 | 20 | +#if !HANDMADE_OSX 21 | #include 22 | +#endif 23 | #include 24 | #include 25 | #include 26 | @@ -109,6 +117,46 @@ 27 | return(Result); 28 | } 29 | 30 | +#if HANDMADE_OSX 31 | +typedef struct { 32 | + uint64_t QuadPart; 33 | +} LARGE_INTEGER; 34 | + 35 | + 36 | +void QueryPerformanceCounter(LARGE_INTEGER* Counter) 37 | +{ 38 | + *((uint64_t*)Counter) = mach_absolute_time(); 39 | +} 40 | + 41 | +// Dummy function to possibly avoid extra patches 42 | +// while this file is getting changed frequently. 43 | +void QueryPerformanceFrequency(LARGE_INTEGER* Counter) 44 | +{ 45 | + *((uint64_t*)Counter) = 0; 46 | +} 47 | + 48 | +float OSXGetSecondsElapsed(u64 Then, u64 Now) 49 | +{ 50 | + // This can overflow if used for long elapsed times. 51 | + // Better to use 128-bit arithmetic to do the 52 | + // calculation. 53 | + static mach_timebase_info_data_t tb; 54 | + 55 | + u64 Elapsed = Now - Then; 56 | + 57 | + if (tb.denom == 0) 58 | + { 59 | + // First time we need to get the timebase 60 | + mach_timebase_info(&tb); 61 | + } 62 | + 63 | + u64 Nanos = Elapsed * tb.numer / tb.denom; 64 | + float Result = (float)Nanos * 1.0E-9; 65 | + 66 | + return Result; 67 | +} 68 | +#endif 69 | + 70 | internal void 71 | ProfileRun(u32 RepeatCount) 72 | { 73 | @@ -221,7 +269,7 @@ 74 | lighting_spatial_grid_leaf Leaf = 75 | Solution->SpatialGridLeaves[LeafIndexIndex]; 76 | f32_4x Valid = (Leaf.BoxMin.x != Leaf.BoxMax.x); 77 | - u32 ValidCount = __popcnt(_mm_movemask_ps(Valid.P)); 78 | + u32 ValidCount = _mm_popcnt_u32(_mm_movemask_ps(Valid.P)); 79 | BoxCount += ValidCount; 80 | } 81 | 82 | @@ -246,8 +294,12 @@ 83 | } 84 | else 85 | { 86 | +#if HANDMADE_OSX 87 | + float TotalSeconds = OSXGetSecondsElapsed(StartTime.QuadPart, EndTime.QuadPart); 88 | +#else 89 | double Diff = (double)(EndTime.QuadPart - StartTime.QuadPart); 90 | double TotalSeconds = Diff / (double)Freq.QuadPart; 91 | +#endif 92 | fprintf(stdout, "T:%.0f P:%.0f L:%.0f P/L:%.2f\n", 93 | (double)TotalPartitionsTested + (double)TotalLeavesTested, 94 | (double)TotalPartitionsTested, (double)TotalLeavesTested, 95 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | Put a copy of gimp_test.png in this directory. 2 | -------------------------------------------------------------------------------- /xcode/Handmade Hero.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 47; 7 | objects = { 8 | 9 | /* Begin PBXFileReference section */ 10 | 4F7317F51C6E885D00D29A61 /* osx_handmade.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = osx_handmade.cpp; path = ../code/osx_handmade.cpp; sourceTree = ""; }; 11 | 4F7317F61C6E885D00D29A61 /* osx_handmade.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = osx_handmade.h; path = ../code/osx_handmade.h; sourceTree = ""; }; 12 | 4F7317F71C6E885D00D29A61 /* osx_main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = osx_main.mm; path = ../code/osx_main.mm; sourceTree = ""; }; 13 | 4F7317F81C6E887B00D29A61 /* osx_handmade_audio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = osx_handmade_audio.cpp; path = ../code/osx_handmade_audio.cpp; sourceTree = ""; }; 14 | 4F7317F91C6E887B00D29A61 /* osx_handmade_debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = osx_handmade_debug.cpp; path = ../code/osx_handmade_debug.cpp; sourceTree = ""; }; 15 | 4F7317FA1C6E887B00D29A61 /* osx_handmade_dylib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = osx_handmade_dylib.cpp; path = ../code/osx_handmade_dylib.cpp; sourceTree = ""; }; 16 | 4F7317FB1C6E887B00D29A61 /* osx_handmade_file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = osx_handmade_file.cpp; path = ../code/osx_handmade_file.cpp; sourceTree = ""; }; 17 | 4F7317FC1C6E887B00D29A61 /* osx_handmade_game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = osx_handmade_game.cpp; path = ../code/osx_handmade_game.cpp; sourceTree = ""; }; 18 | 4F7317FD1C6E887B00D29A61 /* osx_handmade_hid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = osx_handmade_hid.cpp; path = ../code/osx_handmade_hid.cpp; sourceTree = ""; }; 19 | 4F7317FE1C6E887B00D29A61 /* osx_handmade_playback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = osx_handmade_playback.cpp; path = ../code/osx_handmade_playback.cpp; sourceTree = ""; }; 20 | 4F7317FF1C6E887B00D29A61 /* osx_handmade_process.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = osx_handmade_process.cpp; path = ../code/osx_handmade_process.cpp; sourceTree = ""; }; 21 | 4F7318001C6E887B00D29A61 /* osx_handmade_thread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = osx_handmade_thread.cpp; path = ../code/osx_handmade_thread.cpp; sourceTree = ""; }; 22 | /* End PBXFileReference section */ 23 | 24 | /* Begin PBXGroup section */ 25 | 4F7317E91C6E850200D29A61 = { 26 | isa = PBXGroup; 27 | children = ( 28 | 4F7317F41C6E883000D29A61 /* code */, 29 | ); 30 | sourceTree = ""; 31 | }; 32 | 4F7317F41C6E883000D29A61 /* code */ = { 33 | isa = PBXGroup; 34 | children = ( 35 | 4F7317F81C6E887B00D29A61 /* osx_handmade_audio.cpp */, 36 | 4F7317F91C6E887B00D29A61 /* osx_handmade_debug.cpp */, 37 | 4F7317FA1C6E887B00D29A61 /* osx_handmade_dylib.cpp */, 38 | 4F7317FB1C6E887B00D29A61 /* osx_handmade_file.cpp */, 39 | 4F7317FC1C6E887B00D29A61 /* osx_handmade_game.cpp */, 40 | 4F7317FD1C6E887B00D29A61 /* osx_handmade_hid.cpp */, 41 | 4F7317FE1C6E887B00D29A61 /* osx_handmade_playback.cpp */, 42 | 4F7317FF1C6E887B00D29A61 /* osx_handmade_process.cpp */, 43 | 4F7318001C6E887B00D29A61 /* osx_handmade_thread.cpp */, 44 | 4F7317F51C6E885D00D29A61 /* osx_handmade.cpp */, 45 | 4F7317F61C6E885D00D29A61 /* osx_handmade.h */, 46 | 4F7317F71C6E885D00D29A61 /* osx_main.mm */, 47 | ); 48 | name = code; 49 | sourceTree = ""; 50 | }; 51 | /* End PBXGroup section */ 52 | 53 | /* Begin PBXLegacyTarget section */ 54 | 4F7317EE1C6E850200D29A61 /* Handmade Hero */ = { 55 | isa = PBXLegacyTarget; 56 | buildArgumentsString = "$(ACTION)"; 57 | buildConfigurationList = 4F7317F11C6E850200D29A61 /* Build configuration list for PBXLegacyTarget "Handmade Hero" */; 58 | buildPhases = ( 59 | ); 60 | buildToolPath = /usr/bin/make; 61 | buildWorkingDirectory = ../code; 62 | dependencies = ( 63 | ); 64 | name = "Handmade Hero"; 65 | passBuildSettingsInEnvironment = 1; 66 | productName = "Handmade Hero"; 67 | }; 68 | /* End PBXLegacyTarget section */ 69 | 70 | /* Begin PBXProject section */ 71 | 4F7317EA1C6E850200D29A61 /* Project object */ = { 72 | isa = PBXProject; 73 | attributes = { 74 | KnownAssetTags = ( 75 | New, 76 | ); 77 | LastUpgradeCheck = 0720; 78 | ORGANIZATIONNAME = "Jeff Buck"; 79 | TargetAttributes = { 80 | 4F7317EE1C6E850200D29A61 = { 81 | CreatedOnToolsVersion = 7.2.1; 82 | }; 83 | }; 84 | }; 85 | buildConfigurationList = 4F7317ED1C6E850200D29A61 /* Build configuration list for PBXProject "Handmade Hero" */; 86 | compatibilityVersion = "Xcode 6.3"; 87 | developmentRegion = English; 88 | hasScannedForEncodings = 0; 89 | knownRegions = ( 90 | en, 91 | Base, 92 | ); 93 | mainGroup = 4F7317E91C6E850200D29A61; 94 | productRefGroup = 4F7317E91C6E850200D29A61; 95 | projectDirPath = ""; 96 | projectRoot = ""; 97 | targets = ( 98 | 4F7317EE1C6E850200D29A61 /* Handmade Hero */, 99 | ); 100 | }; 101 | /* End PBXProject section */ 102 | 103 | /* Begin XCBuildConfiguration section */ 104 | 4F7317EF1C6E850200D29A61 /* Debug */ = { 105 | isa = XCBuildConfiguration; 106 | buildSettings = { 107 | ALWAYS_SEARCH_USER_PATHS = NO; 108 | CLANG_CXX_LANGUAGE_STANDARD = "c++11"; 109 | CLANG_CXX_LIBRARY = "libstdc++"; 110 | CLANG_ENABLE_MODULES = NO; 111 | CLANG_ENABLE_OBJC_ARC = NO; 112 | CLANG_WARN_BOOL_CONVERSION = YES; 113 | CLANG_WARN_CONSTANT_CONVERSION = YES; 114 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 115 | CLANG_WARN_EMPTY_BODY = YES; 116 | CLANG_WARN_ENUM_CONVERSION = YES; 117 | CLANG_WARN_INT_CONVERSION = YES; 118 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 119 | CLANG_WARN_UNREACHABLE_CODE = YES; 120 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 121 | COPY_PHASE_STRIP = NO; 122 | DEBUG_INFORMATION_FORMAT = dwarf; 123 | ENABLE_STRICT_OBJC_MSGSEND = YES; 124 | ENABLE_TESTABILITY = YES; 125 | GCC_C_LANGUAGE_STANDARD = gnu99; 126 | GCC_DYNAMIC_NO_PIC = NO; 127 | GCC_NO_COMMON_BLOCKS = YES; 128 | GCC_OPTIMIZATION_LEVEL = 0; 129 | GCC_PREPROCESSOR_DEFINITIONS = ( 130 | "DEBUG=1", 131 | "$(inherited)", 132 | ); 133 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 134 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 135 | GCC_WARN_UNDECLARED_SELECTOR = YES; 136 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 137 | GCC_WARN_UNUSED_FUNCTION = YES; 138 | GCC_WARN_UNUSED_VARIABLE = YES; 139 | MTL_ENABLE_DEBUG_INFO = YES; 140 | ONLY_ACTIVE_ARCH = YES; 141 | }; 142 | name = Debug; 143 | }; 144 | 4F7317F01C6E850200D29A61 /* Release */ = { 145 | isa = XCBuildConfiguration; 146 | buildSettings = { 147 | ALWAYS_SEARCH_USER_PATHS = NO; 148 | CLANG_CXX_LANGUAGE_STANDARD = "c++11"; 149 | CLANG_CXX_LIBRARY = "libstdc++"; 150 | CLANG_ENABLE_MODULES = NO; 151 | CLANG_ENABLE_OBJC_ARC = NO; 152 | CLANG_WARN_BOOL_CONVERSION = YES; 153 | CLANG_WARN_CONSTANT_CONVERSION = YES; 154 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 155 | CLANG_WARN_EMPTY_BODY = YES; 156 | CLANG_WARN_ENUM_CONVERSION = YES; 157 | CLANG_WARN_INT_CONVERSION = YES; 158 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 159 | CLANG_WARN_UNREACHABLE_CODE = YES; 160 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 161 | COPY_PHASE_STRIP = NO; 162 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 163 | ENABLE_NS_ASSERTIONS = NO; 164 | ENABLE_STRICT_OBJC_MSGSEND = YES; 165 | GCC_C_LANGUAGE_STANDARD = gnu99; 166 | GCC_NO_COMMON_BLOCKS = YES; 167 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 168 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 169 | GCC_WARN_UNDECLARED_SELECTOR = YES; 170 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 171 | GCC_WARN_UNUSED_FUNCTION = YES; 172 | GCC_WARN_UNUSED_VARIABLE = YES; 173 | MTL_ENABLE_DEBUG_INFO = NO; 174 | }; 175 | name = Release; 176 | }; 177 | 4F7317F21C6E850200D29A61 /* Debug */ = { 178 | isa = XCBuildConfiguration; 179 | buildSettings = { 180 | DEBUGGING_SYMBOLS = YES; 181 | DEBUG_INFORMATION_FORMAT = dwarf; 182 | GCC_GENERATE_DEBUGGING_SYMBOLS = YES; 183 | GCC_OPTIMIZATION_LEVEL = 0; 184 | OTHER_CFLAGS = ""; 185 | OTHER_LDFLAGS = ""; 186 | PRODUCT_NAME = "$(TARGET_NAME)"; 187 | }; 188 | name = Debug; 189 | }; 190 | 4F7317F31C6E850200D29A61 /* Release */ = { 191 | isa = XCBuildConfiguration; 192 | buildSettings = { 193 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 194 | OTHER_CFLAGS = ""; 195 | OTHER_LDFLAGS = ""; 196 | PRODUCT_NAME = "$(TARGET_NAME)"; 197 | }; 198 | name = Release; 199 | }; 200 | /* End XCBuildConfiguration section */ 201 | 202 | /* Begin XCConfigurationList section */ 203 | 4F7317ED1C6E850200D29A61 /* Build configuration list for PBXProject "Handmade Hero" */ = { 204 | isa = XCConfigurationList; 205 | buildConfigurations = ( 206 | 4F7317EF1C6E850200D29A61 /* Debug */, 207 | 4F7317F01C6E850200D29A61 /* Release */, 208 | ); 209 | defaultConfigurationIsVisible = 0; 210 | defaultConfigurationName = Release; 211 | }; 212 | 4F7317F11C6E850200D29A61 /* Build configuration list for PBXLegacyTarget "Handmade Hero" */ = { 213 | isa = XCConfigurationList; 214 | buildConfigurations = ( 215 | 4F7317F21C6E850200D29A61 /* Debug */, 216 | 4F7317F31C6E850200D29A61 /* Release */, 217 | ); 218 | defaultConfigurationIsVisible = 0; 219 | defaultConfigurationName = Release; 220 | }; 221 | /* End XCConfigurationList section */ 222 | }; 223 | rootObject = 4F7317EA1C6E850200D29A61 /* Project object */; 224 | } 225 | --------------------------------------------------------------------------------