Compare commits
1048 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b8477a470f | |||
| 2f44523e6d | |||
| 2fa5f6f242 | |||
| a86cce5d70 | |||
| 9856f170a7 | |||
| ba35619718 | |||
| 37331d8ead | |||
| d17784b231 | |||
| 18e1b45388 | |||
| 9b083f801c | |||
| f0907d6f96 | |||
| 71d58e3a67 | |||
| 37425d6fcd | |||
| 1f295bba5b | |||
| a50be7a912 | |||
| f9d52ea5b9 | |||
| e192869e15 | |||
| f1be9bbf6c | |||
| d331ff3193 | |||
| 035a187c42 | |||
| 3c37036f7a | |||
| 14b6d6291b | |||
| 5720a32bc5 | |||
| 11f57f259c | |||
| 3fc6375ec5 | |||
| f8e05f8e3c | |||
| 98c0b3a2b1 | |||
| 6423c23a9a | |||
| dece8a69f6 | |||
| 5724d2d4c7 | |||
| b1736b6411 | |||
| 703ec474f5 | |||
| 64a109d28a | |||
| dc2ec17886 | |||
| 1d9dd8d29d | |||
| 8b0e1d6c03 | |||
| f1a9f6263e | |||
| a049c6fd6b | |||
| 9609767c51 | |||
| 86a8e0716f | |||
| b5e9f09972 | |||
| 4d9a167f56 | |||
| b704cc8375 | |||
| e34c956196 | |||
| 7197dd751a | |||
| 0b9e4ffe54 | |||
| 486ba6121d | |||
| 1015c126d7 | |||
| 1caf81811a | |||
| 4c2a11b6d0 | |||
| 8fd3b26308 | |||
| 617d21fa84 | |||
| 4a88ffe250 | |||
| 41b68ef353 | |||
| 72c85744b9 | |||
| c7b5bbd467 | |||
| 082bbc7336 | |||
| 087dccd194 | |||
| 61450335a5 | |||
| 67649d7976 | |||
| 6247969ede | |||
| efd38fa940 | |||
| 551472220e | |||
| 01703b1350 | |||
| e9d785475e | |||
| 9e008996ab | |||
| bcfae17219 | |||
| ddea45160b | |||
| 53f13a9721 | |||
| 3e33f064bf | |||
| aa0afc9a4e | |||
| a0d1cf26d0 | |||
| 01d14aed80 | |||
| 3c4c830e20 | |||
| 0c9c481cee | |||
| 7dae376646 | |||
| ccb89bd76a | |||
| b2317543c8 | |||
| b812ef2771 | |||
| 7618e7f3fb | |||
| b6732fbae9 | |||
| 68fa377d13 | |||
| 7a9561b966 | |||
| c061991c43 | |||
| bdac1d9bfd | |||
| 266c4209c4 | |||
| fb26da1cb0 | |||
| d623720f4d | |||
| 9d4fcbf946 | |||
| 896db3806d | |||
| 691b986e36 | |||
| 5416f60643 | |||
| 67e2e154fa | |||
| 330dea181a | |||
| 7bc673002f | |||
| ae8d1a3a60 | |||
| 27975e9dfd | |||
| bff938ccf5 | |||
| 53f317e076 | |||
| 0a7df9d02e | |||
| 408ffd3d2c | |||
| a211895e28 | |||
| 19763f8973 | |||
| 99d6f9c7a9 | |||
| 63e4ac80bd | |||
| 24983ea329 | |||
| 6cab5b5591 | |||
| c9d2aed286 | |||
| a16cc3ac8a | |||
| ba1699a831 | |||
| 20c69a0e3e | |||
| bdc5ed094b | |||
| 088d22675b | |||
| fc9b3c13e6 | |||
| 14a64e2529 | |||
| f5415fb4ac | |||
| 20076ed57e | |||
| 006b8574ae | |||
| 1de7ac3c67 | |||
| 8d1fc18941 | |||
| 06dc99ab85 | |||
| e4059dfe6a | |||
| 4048b1e515 | |||
| ccb46df905 | |||
| a16d8ba3ea | |||
| a485957130 | |||
| 56d34e0e80 | |||
| 11824b3916 | |||
| 5ca6381624 | |||
| 024b184008 | |||
| 7a105333dc | |||
| 332eb5fbd6 | |||
| 5b0dac797c | |||
| 86ddc00bb1 | |||
| 3107f37864 | |||
| 17f5fec538 | |||
| 03b76b4606 | |||
| a3e8a61547 | |||
| a8d5a8734a | |||
| 10bbb7fa1f | |||
| 8c5f2b249c | |||
| 332c512eed | |||
| d10584ac6c | |||
| d2b761b7de | |||
| 49c5ce30cc | |||
| 95725bf7fc | |||
| 94c62b1eec | |||
| 02febd3f65 | |||
| 497fbb17a8 | |||
| 5ddb1d6649 | |||
| 396c129d41 | |||
| f64a7bb820 | |||
| 4a9be0a8d2 | |||
| bf1756448e | |||
| ed8f60431f | |||
| 6f1f75bc8f | |||
| 963d150e93 | |||
| c1f1b1174d | |||
| 1ddeef71c6 | |||
| b7eefeac8b | |||
| e57f36fc5b | |||
| 32116086b3 | |||
| 878da3b474 | |||
| 73320d4180 | |||
| a1d31f640a | |||
| 9c7230e79f | |||
| 98687d474b | |||
| 7b57b8f2ca | |||
| 55c98bfaef | |||
| e9a45a2f45 | |||
| 2212a131ef | |||
| deacf05769 | |||
| 870224cde0 | |||
| e557c962fb | |||
| 5a3c218239 | |||
| 1e71deb0db | |||
| dea1d01de2 | |||
| e9bea1c742 | |||
| d51bb8b1cc | |||
| aad5283786 | |||
| 66df38957b | |||
| 7cbafd603a | |||
| 3e48c9744b | |||
| a982280400 | |||
| d62983e1a2 | |||
| 90ac24e524 | |||
| 0b2ba98238 | |||
| 916ce7899b | |||
| b978aa6dca | |||
| 6565855005 | |||
| 9f80a55652 | |||
| 9d895e6b15 | |||
| a7acb84b8b | |||
| 8d54453981 | |||
| 452fb59c74 | |||
| ba45daff35 | |||
| b3fb6d7d18 | |||
| 5dc3467337 | |||
| 729757b1dd | |||
| 393f9d329d | |||
| 820390b7ed | |||
| e0790f758e | |||
| 2f333424a6 | |||
| a67b347966 | |||
| dedf09017a | |||
| cd07ab5b5f | |||
| 6892cb1c7e | |||
| b518a9a338 | |||
| 54d078f379 | |||
| b0a0533a4f | |||
| 399f20ae54 | |||
| 554ba9d6a6 | |||
| 2c05e9719d | |||
| cb9e7358d2 | |||
| ae01e1d2c3 | |||
| 2766e5ca6f | |||
| ca0c4f2cc0 | |||
| 70c98fff19 | |||
| b5698ee101 | |||
| 379138af27 | |||
| 1864419561 | |||
| c4a8bb26fb | |||
| a9ddb1d3b3 | |||
| 314670a347 | |||
| ad49c54531 | |||
| 43ac33c2b4 | |||
| 83fdcff178 | |||
| ee4009e123 | |||
| 2decf1ecda | |||
| 1d7fbd6a9a | |||
| 1213708b72 | |||
| 6cc5428d5e | |||
| 8fcebebae3 | |||
| f801dc6558 | |||
| 8716ac554f | |||
| d7b4753007 | |||
| a9b0d25c01 | |||
| 4c7fc8a70a | |||
| f8e9ea45ba | |||
| 1b6c14be8d | |||
| a5bb925a3d | |||
| 6a14849381 | |||
| f93dbb8f49 | |||
| f83b19cecf | |||
| 1e09be19f5 | |||
| c1de0bc28c | |||
| 1a5a0f5eca | |||
| 8b0cd60be9 | |||
| 2239a52e9b | |||
| c9214ce6c0 | |||
| bb9b5e6aff | |||
| 0327ecc5c1 | |||
| ccdea1c4ad | |||
| c22e1e71f0 | |||
| aff63028d4 | |||
| 7a7b168af3 | |||
| bdf6a1c70e | |||
| d1e07434a1 | |||
| c0d823f1d8 | |||
| 8d0947f07f | |||
| 161d8ef47a | |||
| 8c139206d7 | |||
| e3a7fddddf | |||
| 923ba6f3bb | |||
| 729cd9284e | |||
| 140c5bfc3e | |||
| a5f0faefc3 | |||
| 608f8de347 | |||
| 3e8a00d264 | |||
| 7d5a72c9e0 | |||
| 48d0f80a86 | |||
| bd6c187fcd | |||
| 585837a3f0 | |||
| b4e821c28d | |||
| 589ac1c5d4 | |||
| c9e8b87c60 | |||
| 41f5158247 | |||
| d2993474fb | |||
| 77e312fb99 | |||
| cd6ef2958b | |||
| 40f3adc45f | |||
| cfa2d4aaa8 | |||
| bdefeaf6f9 | |||
| 0958c10f88 | |||
| 4adf412049 | |||
| 03332c340d | |||
| 63ecb56b51 | |||
| cbd895a29c | |||
| 9cbe77904d | |||
| a6350d5dd1 | |||
| 19b5b47b26 | |||
| 52a0b38379 | |||
| a4fdbf0a88 | |||
| 3990e2d3e6 | |||
| 53af2dbb3f | |||
| 5bdd1cf837 | |||
| 5dfe3f414d | |||
| 324fa10918 | |||
| aad06faf1f | |||
| 1a3c01154a | |||
| df338f0552 | |||
| e5d0e035d0 | |||
| 6d91a9fe6f | |||
| 935e398930 | |||
| 2afc7cbaaa | |||
| 1b5cf118e7 | |||
| a3a4c0a906 | |||
| 3ae7debc17 | |||
| dab53f4e41 | |||
| 9da7910fc9 | |||
| 3609eb25c9 | |||
| 55c75d2c87 | |||
| ded828dfc9 | |||
| c69c70cf5f | |||
| 7cd79714fa | |||
| 87af905018 | |||
| 7205a93751 | |||
| f8097a428c | |||
| 228988ca2b | |||
| d2b0b019ec | |||
| a5d74c5e96 | |||
| 3e7e077fad | |||
| dbb03ae2d7 | |||
| 06d2c5357b | |||
| c8e7530e37 | |||
| cdffaa1598 | |||
| b836d2497d | |||
| bdd94f053c | |||
| f88c3ae417 | |||
| b09ac19e61 | |||
| 826dc7d5a6 | |||
| fa5a2b6a85 | |||
| 8b8120cfb7 | |||
| e6a3b59229 | |||
| 0eb0b1e1c9 | |||
| 1becd2f788 | |||
| 7c0b93f815 | |||
| fa852c7dbe | |||
| 73ca2119ed | |||
| 86dbb859b7 | |||
| e1e370999e | |||
| 038c708a0a | |||
| c71bc25090 | |||
| 52fe86b56c | |||
| 004ebfdaee | |||
| d0edd44a69 | |||
| ea5e837bd6 | |||
| bbf52f3cea | |||
| d788b12a8e | |||
| 8a9320c4ef | |||
| 5cc9bd7702 | |||
| aa7e2376ec | |||
| ff211a9508 | |||
| 930895a218 | |||
| 3452e18da1 | |||
| b5d4b5a21c | |||
| 2dc798d539 | |||
| 805d52987f | |||
| c2467b7b38 | |||
| 22b8cfd0ba | |||
| 10a55f16cc | |||
| 8e4451d1ab | |||
| 0b5c6350ae | |||
| 48cd56acc2 | |||
| 71e16bfac3 | |||
| b7c579adf9 | |||
| 461fa6a88a | |||
| dfee46604a | |||
| a7c9827ad4 | |||
| f580bee32c | |||
| de9d859f4a | |||
| 3aaa0172d5 | |||
| 29e7eda887 | |||
| 7cb32a3680 | |||
| a4d4ab1df9 | |||
| 4bef176e9b | |||
| d2de8a87bf | |||
| 12cad7c393 | |||
| be1238cc95 | |||
| 67378c7dea | |||
| c13039396c | |||
| e940632d93 | |||
| 6db25aa7fa | |||
| 0012f39384 | |||
| 0e7e5b59ae | |||
| d459da1378 | |||
| 3063369322 | |||
| a90ad62fc0 | |||
| cd01a1eb09 | |||
| 090a769bf6 | |||
| 014846cf31 | |||
| b83cb2dbf5 | |||
| 112b7f6571 | |||
| 68a878264c | |||
| a771f168eb | |||
| 79b5b79de1 | |||
| 7cc8380330 | |||
| e91df31f8c | |||
| 663b2c9c5e | |||
| 801467e565 | |||
| 447d2b6f93 | |||
| 9ccf39b27f | |||
| d4af8dd89a | |||
| 932f31e37b | |||
| 0878db4e17 | |||
| 037586d7bb | |||
| cb7cf40b5e | |||
| 3632412c48 | |||
| 4b858648e5 | |||
| 85bebebb36 | |||
| 980be9e0e8 | |||
| ad1027455a | |||
| 9dc238187f | |||
| 73d45f3bf0 | |||
| 96400234a8 | |||
| 2e5f321583 | |||
| 5a9b29b73a | |||
| 1b2260132b | |||
| 1479468730 | |||
| f0b7afd7cc | |||
| 870d26f9d8 | |||
| f6d465667a | |||
| aaae30cb84 | |||
| fbb9396813 | |||
| b9a4abce0e | |||
| d0cc5c0fc7 | |||
| b7c2bfbcde | |||
| 8be2a55ccc | |||
| 81270f3142 | |||
| eb0d006168 | |||
| a47bda026b | |||
| 5129d0da45 | |||
| b86ec2ffcf | |||
| 20eb4352fb | |||
| e76d8eb046 | |||
| c8fefc4434 | |||
| 2c18d67769 | |||
| 428771f1d7 | |||
| 038148bf06 | |||
| 6786734d95 | |||
| 1446254a03 | |||
| 3bcd76bd4e | |||
| 0bcece4585 | |||
| 035ab590ec | |||
| 8e6e57de86 | |||
| 4c1026436f | |||
| 9f97bab717 | |||
| 76518d4c59 | |||
| eba7d3b172 | |||
| b8311caa6b | |||
| 5b044a93c1 | |||
| f009d36811 | |||
| f43260bd58 | |||
| cf384795d2 | |||
| 423cc1685c | |||
| 0a23a5ef50 | |||
| 629d608d4f | |||
| 00be247913 | |||
| 5ed0cc293d | |||
| 5401cb7392 | |||
| e26ae9899c | |||
| 48296c2ba6 | |||
| b858fceb4f | |||
| 195fb1cf66 | |||
| 52acc23ecf | |||
| 0a34fc4bcd | |||
| bec91aab7b | |||
| 5a049d41fd | |||
| 6f4dbf4fcd | |||
| bf66c36ba4 | |||
| 0c10f47e85 | |||
| 1bad9a939f | |||
| 8d6504d6e3 | |||
| 04c187deb5 | |||
| bc938ce630 | |||
| e5f95a450d | |||
| b31d38eef7 | |||
| db402cb8af | |||
| 1af6550db7 | |||
| 7795f5207f | |||
| a9b8a50c31 | |||
| a9418fa1e7 | |||
| 08f48d27e8 | |||
| 25a66da4ca | |||
| ff61bc9e7c | |||
| 3e8f4ba018 | |||
| f9eb6a31bd | |||
| 4f8cac731b | |||
| 3e496f6625 | |||
| 2d62f9c4c5 | |||
| 78811b8816 | |||
| e38cd5149a | |||
| dc2a1e270a | |||
| 44ab50553d | |||
| 7c683c368d | |||
| 62ca7a9b60 | |||
| 632e36ab44 | |||
| 0057c89eaa | |||
| 9e9a55df46 | |||
| 9463238490 | |||
| b7ff2ecffb | |||
| fad89f1c3b | |||
| 5063eefa96 | |||
| 1b34fa26ac | |||
| 25827c12a3 | |||
| cb32fd15ee | |||
| d6dcab443d | |||
| c32fec774f | |||
| ddac4686a7 | |||
| 2865865382 | |||
| 7ce835e878 | |||
| 7e0fdbbe99 | |||
| fd1f2ca1c6 | |||
| a6a92f7b6b | |||
| 4f85f151fd | |||
| 478ae0715e | |||
| 714eb6dcc5 | |||
| 89942ed92a | |||
| 6ed9251f44 | |||
| 2c32a721fc | |||
| 08aaae7999 | |||
| 78bad361ab | |||
| 2005c89baa | |||
| 8c6aa9db31 | |||
| 58eef983e2 | |||
| 390b192f0a | |||
| 7b40859eff | |||
| d0126f0fa0 | |||
| 0c034ad7de | |||
| aeeceb7d0b | |||
| d5f16ce272 | |||
| c89362f6a2 | |||
| 8a029159cd | |||
| 891ebd0cb1 | |||
| 382509d778 | |||
| f9ee8978ff | |||
| e71c2df39d | |||
| cfc7865f82 | |||
| cf6606065d | |||
| 9feb92df1b | |||
| be26810cd7 | |||
| df79b6c238 | |||
| 82c86ed2f7 | |||
| 9077563dac | |||
| 8d15f44b33 | |||
| b3fbada10e | |||
| 31cdd7bdd2 | |||
| c464e90d5d | |||
| 670d2b191c | |||
| 7bddb87306 | |||
| 2025f02105 | |||
| 1078626eea | |||
| 16c6b44f55 | |||
| 6b3b06df25 | |||
| e3b3b0cda7 | |||
| bb2cc196a6 | |||
| d3bc96a201 | |||
| 11ba6e45ab | |||
| a742501a4f | |||
| 70346028c5 | |||
| 3359458175 | |||
| 6784301376 | |||
| 51d19e7c31 | |||
| 0652870204 | |||
| 67dd6754a6 | |||
| 34274ec391 | |||
| 28feea0447 | |||
| 53267e283b | |||
| 15ed963a29 | |||
| c652d0b183 | |||
| 22c55cbcfa | |||
| c24d89dd34 | |||
| f10ea1fb9b | |||
| eb72cc9f04 | |||
| ee288340b0 | |||
| a69248299d | |||
| caa83d20f7 | |||
| 486d48e4f8 | |||
| 8480674708 | |||
| 7c62574e59 | |||
| 22584fb2d1 | |||
| 90ac9165e2 | |||
| bcb69a54b2 | |||
| f93cb262ba | |||
| 67949bb5b7 | |||
| e56da4eb46 | |||
| f7fdfe52bc | |||
| 7de0ff337b | |||
| e1c0a917fa | |||
| ead180aa60 | |||
| 58d367d704 | |||
| a1ab6c28c1 | |||
| 59e46f09b7 | |||
| 7766076042 | |||
| b96864c7e6 | |||
| 79513f06a4 | |||
| 00ff53499a | |||
| 142b44d4be | |||
| 7f28489c70 | |||
| a58c12db0b | |||
| 12e1be2626 | |||
| f81674232e | |||
| eb086b0e3f | |||
| b6b9085773 | |||
| 241989c5fa | |||
| f944573b3c | |||
| c66b155dcb | |||
| 5662867730 | |||
| dbecf0fa50 | |||
| 62cb532460 | |||
| f9bc682115 | |||
| 6cf0c5cd6d | |||
| 8a2a76da1e | |||
| e07484f057 | |||
| 0070fce286 | |||
| a2e8e3090c | |||
| 0ac68def49 | |||
| def364fe28 | |||
| c06707c891 | |||
| d7a8d385d8 | |||
| 3567c43fb5 | |||
| aaaeb66cc8 | |||
| 4ed76a15ff | |||
| b5837d1271 | |||
| e4c3b1c2bd | |||
| ea916fd7e1 | |||
| 4bee8dc37f | |||
| 8b01d05146 | |||
| 376e564cff | |||
| caf02d1841 | |||
| 6cf73fad13 | |||
| cfe660ab35 | |||
| 8eaf76394c | |||
| a692adefd7 | |||
| e05f1c37ad | |||
| 923fcc3b3d | |||
| c50b9bc4b4 | |||
| e1f95ceb54 | |||
| eb77495d5f | |||
| 270d602a26 | |||
| dd41ee68de | |||
| 46dc40f3f1 | |||
| 7c7af2e102 | |||
| 36189b8c3b | |||
| cde802b16c | |||
| 1500e5f588 | |||
| fbe91fb245 | |||
| 321e7d6977 | |||
| 56488a4ac9 | |||
| 4a75f44d47 | |||
| deb4b03200 | |||
| df94c906da | |||
| 4d50d9daa4 | |||
| 0624bdc72d | |||
| ccec6e53c0 | |||
| 68d411918d | |||
| f14d47bfe6 | |||
| 0af452720e | |||
| db8e6fe7a7 | |||
| 631d7d0ce7 | |||
| ed345e5b65 | |||
| d3a66af7d6 | |||
| 52deff06ba | |||
| 838cbe1840 | |||
| 70804e2ba6 | |||
| 07c925223b | |||
| c2cbc62be6 | |||
| 9d74d42f2a | |||
| a36f25c7b2 | |||
| 86fb5412fa | |||
| c5b9ab3aca | |||
| bf6f43ec3a | |||
| 36159c2bd4 | |||
| 72e1d03860 | |||
| ed1b8f2545 | |||
| 1ad0f24ecd | |||
| 586440622b | |||
| 6231b07d2a | |||
| 1dcf5e4f85 | |||
| 9ba8f4795c | |||
| 951fe3491e | |||
| 6ae1f1b02c | |||
| 673e84920b | |||
| d1e1c14dc3 | |||
| 11db3151ae | |||
| 65f81aca0f | |||
| 187216096d | |||
| 3f9b699eef | |||
| 5f8564c655 | |||
| cbe0000d23 | |||
| 0e278d2299 | |||
| 21d725daa5 | |||
| 247e90b3d0 | |||
| 2b8eb8deb6 | |||
| 7262f3d0b7 | |||
| 6f80fd0063 | |||
| 7a51b7a019 | |||
| d9eb31000d | |||
| f8589de476 | |||
| f1c61067bc | |||
| 8a5620592b | |||
| 5227e65808 | |||
| c4c6dc19a5 | |||
| 7fc26b1fab | |||
| c0e121abef | |||
| 7db13fdeff | |||
| e68027b464 | |||
| 220b69058c | |||
| 9c3e55787e | |||
| c952e99f3e | |||
| 35322b5d14 | |||
| 6b96807112 | |||
| 57621d1c4e | |||
| e04b2eebc3 | |||
| 02b684b810 | |||
| 76b1acf99d | |||
| 18c120ab9f | |||
| f87dd91b52 | |||
| 4a8a161a43 | |||
| e3dec420a2 | |||
| 1e32311a65 | |||
| 92e5bb88e8 | |||
| 66581d115b | |||
| 4399324955 | |||
| 733f31f90e | |||
| bef2c50b03 | |||
| a96b4412d3 | |||
| bee76fc8d1 | |||
| d9cb1a6319 | |||
| 567d23d856 | |||
| c94a98e15a | |||
| 72e6e87d82 | |||
| 0055d84bd6 | |||
| d17d22139e | |||
| 87b6284275 | |||
| 2c6b974f24 | |||
| 020acc8235 | |||
| a8e0d261b7 | |||
| 6357b9a04f | |||
| 43a58df8a0 | |||
| b7bf316c1a | |||
| 41ee792f95 | |||
| 6c1b6c1704 | |||
| acadaeed3a | |||
| 96bde3df81 | |||
| 5cb70ddbd5 | |||
| b9b9a0465f | |||
| bd269bccaf | |||
| 5f618814f6 | |||
| 43c87e99b0 | |||
| 74a09a6338 | |||
| 2b9c407dc3 | |||
| 59ed222205 | |||
| 2c06043617 | |||
| ef884642e4 | |||
| e449111c33 | |||
| 066e53da55 | |||
| c74b2cb085 | |||
| eec11bfba9 | |||
| d254a5736b | |||
| b655e4aa47 | |||
| 1adec3d8e5 | |||
| db9b7db531 | |||
| 05099e2ae1 | |||
| 77352a2a86 | |||
| ae633292c0 | |||
| d6042cf891 | |||
| 534c63bf57 | |||
| fb29933d3d | |||
| 360c4d1554 | |||
| 4cfa9b11f3 | |||
| 908465b274 | |||
| a7f10d142e | |||
| e855673802 | |||
| 112ac7bd13 | |||
| ec7963df3d | |||
| 343d006ae2 | |||
| ed8e5498d1 | |||
| 3cfead4ca6 | |||
| c8947eee6a | |||
| 6c1ca7d797 | |||
| 2172974db9 | |||
| ba03df8511 | |||
| fb47d1f788 | |||
| 3c86e14ea4 | |||
| c16fb61bea | |||
| 2acead357b | |||
| 235db57f0e | |||
| cfbde005fb | |||
| 0a865bd9dc | |||
| 6b3f722ff0 | |||
| 3dbecada4e | |||
| d21f87af5d | |||
| 0bfec59af8 | |||
| 035a76f26d | |||
| 42f4e831a2 | |||
| d3686dbb75 | |||
| fb1c790350 | |||
| 0ef5743261 | |||
| e82bef425f | |||
| 24c246a9f6 | |||
| e39348ad96 | |||
| ca5f0444bf | |||
| 4a883ba6ea | |||
| bfe1a8673a | |||
| 0445ef393f | |||
| 7eb16e13bb | |||
| 03ad5c6830 | |||
| ab23e5ca0e | |||
| 35ecd00559 | |||
| e5603fec1e | |||
| e321765c54 | |||
| 62fdcf50ea | |||
| 09d293592e | |||
| f83c2f0b6b | |||
| d775c8dc73 | |||
| 8e07b19bc7 | |||
| cb8ef46ec7 | |||
| ee814cfd0c | |||
| a6a5292cd7 | |||
| b59f142d4e | |||
| 666a18f5e5 | |||
| dff4392c10 | |||
| b09b7c1184 | |||
| 6e05dcadb6 | |||
| bc7acf9f7a | |||
| cb19316a17 | |||
| 33c3977036 | |||
| 7a015b6fc0 | |||
| aa3aef4beb | |||
| 12a48fc6d1 | |||
| 72284b4530 | |||
| 65c04e4ddd | |||
| b382d3b3e9 | |||
| 61b882b2a6 | |||
| 36c8654fb8 | |||
| d25c401aec | |||
| aac874a842 | |||
| 5d934c8759 | |||
| e055d16b2c | |||
| 38745e5782 | |||
| d0c271e534 | |||
| 33635c5723 | |||
| f8d2830ac7 | |||
| a7e5c255b4 | |||
| 062c605eb1 | |||
| 2602be426f | |||
| 51dcb4a79d | |||
| 24e4e329ed | |||
| eb66302907 | |||
| b16cc618b5 | |||
| 77aa9e58f2 | |||
| 3a0b3a85a5 | |||
| 15a12afe25 | |||
| 427cf91447 | |||
| af8c661a64 | |||
| 7b694ebeb4 | |||
| d1e7837422 | |||
| 8efc22bd45 | |||
| 983439076b | |||
| 019f566239 | |||
| 332410d20b | |||
| c2a85bde08 | |||
| 13a0b88755 | |||
| 32f39fec1c | |||
| cad3a6c547 | |||
| 2aa5c437e8 | |||
| 67f48ce21c | |||
| 845a7d9968 | |||
| 924774d3ef | |||
| e0635cf65c | |||
| 3b8e3a9714 | |||
| 2bee096246 | |||
| 872655369a | |||
| 0892758994 | |||
| 22a24446c1 | |||
| b5d498ffda | |||
| bd90e3e37f | |||
| 8b6d615aa6 | |||
| 9e352da052 | |||
| ca9898e838 | |||
| 95b8467a76 | |||
| 2b674d4d8c | |||
| 487b572aa6 | |||
| 600c0ea5ba | |||
| 00e64920c8 | |||
| 9efedbe76a | |||
| d8e9382573 | |||
| ab248e170c | |||
| 27097cbcfe | |||
| 43952e18e2 | |||
| 5076da8f77 | |||
| 8228a4adcd | |||
| 721883f64e | |||
| b55c759f71 | |||
| 3f028fbb83 | |||
| f0cba1371c | |||
| 14fa96fdef | |||
| b954a41f2a | |||
| f1c65dcefc | |||
| d4c17ecda5 | |||
| a4458e2c8c | |||
| 16cc88dd0e | |||
| 280f5f0b54 | |||
| e38eaa7cd7 | |||
| a27bd2275c | |||
| 7d00c69a4f | |||
| a2c189b45a | |||
| 41320688b7 | |||
| f85c8584b0 | |||
| 6cf50f8f6c | |||
| d70ab11477 | |||
| cab4c78b7b | |||
| 14358d5e84 | |||
| 7553429130 | |||
| 3ddfa288cf | |||
| e89a568765 | |||
| 71f1021648 | |||
| 60cff6f3d4 | |||
| 5f010c2f4c | |||
| c0f3d1f06d | |||
| 6c18e00977 | |||
| 72ac1aa537 | |||
| 5bcaa25c02 | |||
| 85880ffded | |||
| 5b207c3b95 | |||
| 3087f15dd8 | |||
| 36f1193497 | |||
| 292af1e4cd | |||
| d4d5dc99f3 | |||
| 3e1344e4e4 | |||
| 6d37bc62a5 | |||
| e9f7c100a0 | |||
| 190676c982 | |||
| 28cbba5a7d | |||
| 0e7a705254 | |||
| 68931b4c43 | |||
| a4e28df9cf | |||
| 65c81c5e83 | |||
| ccd0d2046d | |||
| 0fec99e75b | |||
| f8d1f070f5 | |||
| 3dd48a24ce | |||
| 984e97cbdc | |||
| 50ea1a12c9 | |||
| 992a372fc7 | |||
| d789250976 | |||
| d7e1cf7dd2 | |||
| ea5f5aea5f | |||
| eaf0bbc108 | |||
| b1710bb712 | |||
| dfae7bd073 | |||
| 333fe9a561 | |||
| badb3dc2dd | |||
| 3ac819ee70 | |||
| 00f877e812 | |||
| 1e269751bf | |||
| 5b69eda39a | |||
| 71ca413067 | |||
| 0c7f9458c0 | |||
| ab365fe494 | |||
| e48f160a29 | |||
| cfda4d0ade | |||
| debfae06a8 | |||
| e6f2f8ad0d | |||
| 67785a918c | |||
| 50d80c64fa | |||
| 1378645413 | |||
| 3888b0429c | |||
| 70761a4ef0 | |||
| e37df998e9 | |||
| c30cdfb3a7 | |||
| 350b704cd7 | |||
| ad013d59f4 | |||
| d391133524 | |||
| 4b823469f7 | |||
| 7cd1e767be | |||
| 829a697c39 | |||
| fefab50e06 | |||
| 6e27ab60ca | |||
| 74274f6d77 | |||
| 908b2703f3 | |||
| c047ab6147 | |||
| 52fa69d93d | |||
| a83df01bfd | |||
| b32d989a10 | |||
| d1ee7c651f | |||
| dcbe8ef5f4 | |||
| bd5253047b | |||
| cdaa8cb5c4 | |||
| 083397a555 | |||
| e98eb4659e | |||
| d1988d384c | |||
| bc61835d97 | |||
| 8a50880613 | |||
| b05d12df0e | |||
| 733b46d51a | |||
| 8bc9868c1f | |||
| 3507cd0a37 | |||
| 21ec32b465 | |||
| 1c99a2e7fb | |||
| b68bdafadc | |||
| bacfa9be19 | |||
| 5265eb81e0 | |||
| 516da4ecdd | |||
| 6fcc68699a | |||
| 3cb5fd8ebc | |||
| fd7ea82965 | |||
| 0bd989b118 | |||
| bd0b292b39 | |||
| 31f0a0c064 | |||
| 3e445eff8e | |||
| 6dcd482dd0 | |||
| a28ab0a408 | |||
| a3eb5c2d63 | |||
| e2303f3378 | |||
| acb17b0298 | |||
| fde7cf1fab | |||
| c2cb7e1004 | |||
| 4075f5c497 | |||
| debd44fa9b | |||
| 0a5742587a | |||
| ad4df2d946 | |||
| bfe9580551 | |||
| 1e45437498 | |||
| f9c8f78000 | |||
| 4554eedd19 | |||
| 557f0c5a8a | |||
| 9fb8d449fe | |||
| 1bb7c74c93 | |||
| cc07e5306e | |||
| 34fa010601 | |||
| 7d56069243 | |||
| fc77fb9b4c | |||
| ebdf93e5dc | |||
| 5248240e10 | |||
| b66628baca | |||
| ba5ed5f380 | |||
| 8d5e119582 | |||
| d022e7cd27 | |||
| 5d7acda80e | |||
| 9b595c68a5 | |||
| 2d38d8a639 | |||
| dea8aa675a | |||
| 027eba2b59 | |||
| 91b8e7504e | |||
| 088931525d | |||
| ef9638e094 |
+9
-15
@@ -1,25 +1,18 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
ccache -s # debug
|
||||
|
||||
# Pull all the submodules except llvm
|
||||
# Note: Tried to use git submodule status, but it takes over 20 seconds
|
||||
# shellcheck disable=SC2046
|
||||
git submodule -q update --init $(awk '/path/ && !/llvm/ { print $3 }' .gitmodules)
|
||||
git submodule -q update --init --depth 1 $(awk '/path/ && !/llvm/ { print $3 }' .gitmodules)
|
||||
|
||||
# XXX Drop after Travis upgrades FreeBSD to 12.2 (see also .ci/install-freebsd.sh)
|
||||
case $(${CXX:-c++} --version) in
|
||||
*version\ 8.0.*)
|
||||
fetch https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/libcxx-10.0.0.src.tar.xz
|
||||
tar xf libcxx-10.0.0.src.tar.xz
|
||||
export CC=clang10 CXX=clang++10
|
||||
export CXXFLAGS="$CXXFLAGS -nostdinc++ -isystem $PWD/libcxx-10.0.0.src/include"
|
||||
;;
|
||||
esac
|
||||
# Prefer newer Clang than in base system (see also .ci/install-freebsd.sh)
|
||||
# libc++ isn't in llvm* packages, so download manually
|
||||
fetch https://github.com/llvm/llvm-project/releases/download/llvmorg-12.0.0/libcxx-12.0.0.src.tar.xz
|
||||
tar xf libcxx-12.0.0.src.tar.xz
|
||||
export CC=clang12 CXX=clang++12
|
||||
export CXXFLAGS="$CXXFLAGS -nostdinc++ -D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS -isystem $PWD/libcxx-12.0.0.src/include"
|
||||
|
||||
CONFIGURE_ARGS="
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
-DWITH_LLVM=OFF
|
||||
-DUSE_PRECOMPILED_HEADERS=OFF
|
||||
-DUSE_NATIVE_INSTRUCTIONS=OFF
|
||||
@@ -32,4 +25,5 @@ CONFIGURE_ARGS="
|
||||
cmake -B build -G Ninja $CONFIGURE_ARGS
|
||||
cmake --build build
|
||||
|
||||
ccache -s # debug
|
||||
ccache --show-stats
|
||||
ccache --zero-stats
|
||||
|
||||
+8
-6
@@ -5,7 +5,9 @@ export QT_BASE_DIR=/opt/qt${QTVERMIN}
|
||||
export PATH=$QT_BASE_DIR/bin:$PATH
|
||||
export LD_LIBRARY_PATH=$QT_BASE_DIR/lib/x86_64-linux-gnu:$QT_BASE_DIR/lib
|
||||
|
||||
cd rpcs3 || exit 1
|
||||
if [ -z "$CIRRUS_CI" ]; then
|
||||
cd rpcs3 || exit 1
|
||||
fi
|
||||
|
||||
# Pull all the submodules except llvm, since it is built separately and we just download that build
|
||||
# Note: Tried to use git submodule status, but it takes over 20 seconds
|
||||
@@ -55,11 +57,11 @@ ninja; build_status=$?;
|
||||
|
||||
cd ..
|
||||
|
||||
# If it compiled succesfully let's deploy depending on the build pipeline (Travis, Azure Pipelines).
|
||||
# Travis only deploys on master, and it publishes to GitHub releases. Azure publishes PRs as artifacts
|
||||
# only.
|
||||
{ [ "$IS_AZURE" = "true" ] ||
|
||||
{ [ "$TRAVIS_BRANCH" = "master" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ]; };
|
||||
shellcheck .ci/*.sh
|
||||
|
||||
# If it compiled succesfully let's deploy.
|
||||
# Azure and Cirrus publish PRs as artifacts only.
|
||||
{ [ "$CI_HAS_ARTIFACTS" = "true" ];
|
||||
} && SHOULD_DEPLOY="true" || SHOULD_DEPLOY="false"
|
||||
|
||||
if [ "$build_status" -eq 0 ] && [ "$SHOULD_DEPLOY" = "true" ]; then
|
||||
|
||||
+7
-15
@@ -12,7 +12,6 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then
|
||||
./squashfs-root/AppRun ./appdir/usr/share/applications/*.desktop -bundle-non-qt-libs
|
||||
ls ./appdir/usr/lib/
|
||||
rm -r ./appdir/usr/share/doc
|
||||
rm ./appdir/usr/lib/libxcb*
|
||||
cp "$(readlink -f /lib/x86_64-linux-gnu/libnsl.so.1)" ./appdir/usr/lib/libnsl.so.1
|
||||
export PATH=/rpcs3/build/squashfs-root/usr/bin/:${PATH}
|
||||
|
||||
@@ -33,7 +32,8 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then
|
||||
printf "#include <bits/stdc++.h>\nint main(){std::make_exception_ptr(0);std::pmr::get_default_resource();}" | $CXX -x c++ -std=c++2a -o ./appdir/usr/optional/checker -
|
||||
|
||||
# Package it up and send it off
|
||||
./squashfs-root/usr/bin/appimagetool /rpcs3/build/appdir
|
||||
./squashfs-root/usr/bin/appimagetool "$APPDIR"
|
||||
|
||||
ls
|
||||
|
||||
COMM_TAG="$(grep 'version{.*}' ../rpcs3/rpcs3_version.cpp | awk -F[\{,] '{printf "%d.%d.%d", $2, $3, $4}')"
|
||||
@@ -41,25 +41,17 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then
|
||||
COMM_HASH="$(git rev-parse --short=8 HEAD)"
|
||||
RPCS3_APPIMAGE="rpcs3-v${COMM_TAG}-${COMM_COUNT}-${COMM_HASH}_linux64.AppImage"
|
||||
|
||||
curl -sLO https://github.com/hcorion/uploadtool/raw/master/upload.sh
|
||||
mv ./RPCS3*.AppImage "$RPCS3_APPIMAGE"
|
||||
|
||||
# If we're building using Azure Pipelines, let's copy over the AppImage artifact
|
||||
# If we're building using a CI, let's copy over the AppImage artifact
|
||||
if [ -n "$BUILD_ARTIFACTSTAGINGDIRECTORY" ]; then
|
||||
cp "$RPCS3_APPIMAGE" ~/artifacts
|
||||
cp "$RPCS3_APPIMAGE" "$ARTDIR"
|
||||
fi
|
||||
|
||||
FILESIZE=$(stat -c %s ./rpcs3*.AppImage)
|
||||
SHA256SUM=$(sha256sum ./rpcs3*.AppImage)
|
||||
if [ -n "$GITHUB_TOKEN" ]; then
|
||||
unset TRAVIS_REPO_SLUG
|
||||
REPO_SLUG=RPCS3/rpcs3-binaries-linux \
|
||||
UPLOADTOOL_BODY="$SHA256SUM;${FILESIZE}B"\
|
||||
RELEASE_NAME=build-${TRAVIS_COMMIT}\
|
||||
RELEASE_TITLE=${COMM_TAG}-${COMM_COUNT}\
|
||||
REPO_COMMIT=d812f1254a1157c80fd402f94446310560f54e5f\
|
||||
bash upload.sh rpcs3*.AppImage
|
||||
fi
|
||||
SHA256SUM=$(sha256sum ./rpcs3*.AppImage | awk '{ print $1 }')
|
||||
echo "${SHA256SUM};${FILESIZE}B" > "$RELEASE_MESSAGE"
|
||||
|
||||
fi
|
||||
|
||||
if [ "$DEPLOY_PPA" = "true" ]; then
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
ARTIFACT_DIR="$BUILD_ARTIFACTSTAGINGDIRECTORY"
|
||||
|
||||
# Remove unecessary files
|
||||
rm -f ./bin/rpcs3.exp ./bin/rpcs3.lib ./bin/rpcs3.pdb
|
||||
rm -f ./bin/rpcs3.exp ./bin/rpcs3.lib ./bin/rpcs3.pdb ./bin/vc_redist.x64.exe
|
||||
|
||||
# Prepare compatibility database for packaging, as well as
|
||||
# certificate for ssl (auto-updater)
|
||||
@@ -20,5 +20,5 @@ sha256sum "$BUILD" | awk '{ print $1 }' | tee "$BUILD.sha256"
|
||||
echo "$(cat "$BUILD.sha256");$(stat -c %s "$BUILD")B" > GitHubReleaseMessage.txt
|
||||
|
||||
# Move files to publishing directory
|
||||
mv -- "$BUILD" "$ARTIFACT_DIR"
|
||||
mv -- "$BUILD.sha256" "$ARTIFACT_DIR"
|
||||
cp -- "$BUILD" "$ARTIFACT_DIR"
|
||||
cp -- "$BUILD.sha256" "$ARTIFACT_DIR"
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
# Variables set by Travis CI
|
||||
TRAVIS_PULL_REQUEST
|
||||
TRAVIS_BRANCH
|
||||
TRAVIS_COMMIT
|
||||
# Variables set by Azure Pipelines
|
||||
IS_AZURE
|
||||
CI_HAS_ARTIFACTS
|
||||
BUILD_REASON
|
||||
BUILD_SOURCEVERSION
|
||||
BUILD_ARTIFACTSTAGINGDIRECTORY
|
||||
BUILD_REPOSITORY_NAME
|
||||
BUILD_SOURCEBRANCHNAME
|
||||
# Variables for Travis build matrix
|
||||
APPDIR
|
||||
ARTDIR
|
||||
RELEASE_MESSAGE
|
||||
# Variables for build matrix
|
||||
COMPILER
|
||||
DEPLOY_APPIMAGE
|
||||
# Private Travis CI variables
|
||||
# Private variables
|
||||
GITHUB_TOKEN
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# Export variables for later stages of the Azure pipeline
|
||||
# Values done in this manner will appear as environment variables
|
||||
# in later stages.
|
||||
|
||||
# From pure-sh-bible
|
||||
# Setting 'IFS' tells 'read' where to split the string.
|
||||
while IFS='=' read -r key val; do
|
||||
# Skip over lines containing comments.
|
||||
[ "${key##\#*}" ] || continue
|
||||
export "$key"="$val"
|
||||
done < ".ci/azure-vars.env"
|
||||
Regular → Executable
+4
-6
@@ -7,7 +7,7 @@ generate_post_data()
|
||||
cat <<EOF
|
||||
{
|
||||
"tag_name": "build-${BUILD_SOURCEVERSION}",
|
||||
"target_commitish": "7d09e3be30805911226241afbb14f8cdc2eb054e",
|
||||
"target_commitish": "${UPLOAD_COMMIT_HASH}",
|
||||
"name": "${AVVER}",
|
||||
"body": "$body",
|
||||
"draft": false,
|
||||
@@ -16,17 +16,15 @@ generate_post_data()
|
||||
EOF
|
||||
}
|
||||
|
||||
repo_full_name="RPCS3/rpcs3-binaries-win"
|
||||
|
||||
curl -s \
|
||||
-H "Authorization: token ${RPCS3_TOKEN}" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
--data "$(generate_post_data)" "https://api.github.com/repos/$repo_full_name/releases" >> release.json
|
||||
--data "$(generate_post_data)" "https://api.github.com/repos/$UPLOAD_REPO_FULL_NAME/releases" >> release.json
|
||||
|
||||
cat release.json
|
||||
id=$(grep '"id"' release.json | cut -d ':' -f2 | head -n1 | awk '{$1=$1;print}')
|
||||
id=${id%?}
|
||||
echo ${id:?}
|
||||
echo "${id:?}"
|
||||
|
||||
upload_file()
|
||||
{
|
||||
@@ -35,7 +33,7 @@ upload_file()
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary @"$2"/"$3" \
|
||||
"https://uploads.github.com/repos/$repo_full_name/releases/$1/assets?name=$3"
|
||||
"https://uploads.github.com/repos/$UPLOAD_REPO_FULL_NAME/releases/$1/assets?name=$3"
|
||||
}
|
||||
|
||||
for file in "$ARTIFACT_DIR"/*; do
|
||||
@@ -8,12 +8,8 @@ sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
|
||||
export ASSUME_ALWAYS_YES=true
|
||||
pkg info # debug
|
||||
|
||||
# XXX Drop after Travis upgrades FreeBSD to 12.2 (see also .ci/build-freebsd.sh)
|
||||
case $(${CXX:-c++} --version) in
|
||||
*version\ 8.0.*)
|
||||
pkg install llvm10
|
||||
;;
|
||||
esac
|
||||
# Prefer newer Clang than in base system (see also .ci/build-freebsd.sh)
|
||||
pkg install llvm12
|
||||
|
||||
# Mandatory dependencies (qt5-dbus and qt5-gui are pulled via qt5-widgets)
|
||||
pkg install git ccache cmake ninja qt5-qmake qt5-buildtools qt5-widgets qt5-concurrent glew openal-soft ffmpeg
|
||||
|
||||
@@ -10,8 +10,9 @@ PR_NUMBER="$SYSTEM_PULLREQUEST_PULLREQUESTID"
|
||||
QT_HOST="http://mirrors.ocf.berkeley.edu/qt/"
|
||||
#QT_HOST="http://qt.mirror.constant.com/"
|
||||
QT_URL_VER=$(echo "$QT_VER" | sed "s/\.//g")
|
||||
QT_PREFIX="online/qtsdkrepository/windows_x86/desktop/qt5_${QT_URL_VER}/qt.qt5.${QT_URL_VER}.win64_msvc2017_64/${QT_VER}-0-${QT_DATE}"
|
||||
QT_SUFFIX="-Windows-Windows_10-MSVC2017-Windows-Windows_10-X86_64.7z"
|
||||
QT_VER_MSVC_UP=$(echo "${QT_VER_MSVC}" | tr '[:lower:]' '[:upper:]')
|
||||
QT_PREFIX="online/qtsdkrepository/windows_x86/desktop/qt${QT_VER_MAIN}_${QT_URL_VER}/qt.qt${QT_VER_MAIN}.${QT_URL_VER}.win64_${QT_VER_MSVC}_64/${QT_VER}-0-${QT_DATE}"
|
||||
QT_SUFFIX="-Windows-Windows_10-${QT_VER_MSVC_UP}-Windows-Windows_10-X86_64.7z"
|
||||
QT_BASE_URL="${QT_HOST}${QT_PREFIX}qtbase${QT_SUFFIX}"
|
||||
QT_WINE_URL="${QT_HOST}${QT_PREFIX}qtwinextras${QT_SUFFIX}"
|
||||
QT_DECL_URL="${QT_HOST}${QT_PREFIX}qtdeclarative${QT_SUFFIX}"
|
||||
@@ -35,7 +36,7 @@ DEP_URLS=" \
|
||||
# Pull all the submodules except llvm, since it is built separately and we just download that build
|
||||
# Note: Tried to use git submodule status, but it takes over 20 seconds
|
||||
# shellcheck disable=SC2046
|
||||
git submodule -q update --init --depth 1 $(awk '/path/ && !/llvm/ { print $3 }' .gitmodules)
|
||||
git submodule -q update --init --depth=1 --jobs=8 $(awk '/path/ && !/llvm/ { print $3 }' .gitmodules)
|
||||
|
||||
# Git bash doesn't have rev, so here it is
|
||||
rev()
|
||||
@@ -75,7 +76,7 @@ for url in $DEP_URLS; do
|
||||
case "$url" in
|
||||
*qt*) checksum=$(curl -L "${url}.sha1"); algo="sha1"; outDir='C:\Qt\' ;;
|
||||
*llvm*) checksum=$(curl -L "${url}.sha256"); algo="sha256"; outDir="." ;;
|
||||
*glslang*) checksum=$(curl -L "${url}.sha256"); algo="sha256"; outDir="./lib/Release - LLVM-x64" ;;
|
||||
*glslang*) checksum=$(curl -L "${url}.sha256"); algo="sha256"; outDir="./lib/Release-x64" ;;
|
||||
*Vulkan*)
|
||||
# Vulkan setup needs to be run in batch environment
|
||||
# Need to subshell this or else it doesn't wait
|
||||
|
||||
+98
-4
@@ -1,11 +1,107 @@
|
||||
env:
|
||||
CIRRUS_CLONE_DEPTH: 0 # Unshallow clone to obtain proper GIT_VERSION
|
||||
BUILD_REPOSITORY_NAME: $CIRRUS_REPO_FULL_NAME
|
||||
SYSTEM_PULLREQUEST_SOURCEBRANCH: $CIRRUS_BRANCH
|
||||
SYSTEM_PULLREQUEST_PULLREQUESTID: $CIRRUS_PR
|
||||
BUILD_SOURCEVERSION: $CIRRUS_CHANGE_IN_REPO
|
||||
# RPCS3_TOKEN: ENCRYPTED[13a0f18de9285e6c880e3aecbb54258245a74872af7d0fcb92447fa1200ceb6a4dc8acc880ddbf5e653d46336563ca72] # Replace this when we're using Cirrus for master releases!!
|
||||
|
||||
windows_task:
|
||||
matrix:
|
||||
- name: Cirrus Windows
|
||||
windows_container:
|
||||
image: cirrusci/windowsservercore:visualstudio2019
|
||||
cpu: 8
|
||||
memory: 16G
|
||||
env:
|
||||
CIRRUS_SHELL: "bash"
|
||||
COMPILER: msvc
|
||||
QT_VER_MAIN: '5'
|
||||
BUILD_ARTIFACTSTAGINGDIRECTORY: ${CIRRUS_WORKING_DIR}\artifacts\
|
||||
QT_VER: '5.15.2'
|
||||
QT_VER_MSVC: 'msvc2019'
|
||||
QT_DATE: '202011130602'
|
||||
QTDIR: C:\Qt\${QT_VER}\${QT_VER_MSVC}_64
|
||||
VULKAN_VER: '1.2.154.1'
|
||||
VULKAN_SDK_SHA: 'b64471f3a720e649c1fae6535ea83b8c642655ebed1485bfdf15bf4d88f746d9'
|
||||
VULKAN_SDK: C:\VulkanSDK\${VULKAN_VER}
|
||||
CACHE_DIR: "./cache"
|
||||
UPLOAD_COMMIT_HASH: 7d09e3be30805911226241afbb14f8cdc2eb054e
|
||||
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-win"
|
||||
deps_cache:
|
||||
folder: "./cache"
|
||||
#obj_cache:
|
||||
# folder: "./tmp"
|
||||
#obj2_cache:
|
||||
# folder: "./rpcs3/x64"
|
||||
setup_script:
|
||||
- './.ci/get_keys-windows.sh'
|
||||
- './.ci/setup-windows.sh'
|
||||
# - choco install -y python # Needed for SPIRV, use either this or make a new Docker image
|
||||
# spirv_script:
|
||||
# - export PATH=${PATH}:"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin"
|
||||
# - cd "${CIRRUS_WORKING_DIR}/Vulkan/spirv-tools-build"
|
||||
# - msbuild.exe spirv-tools-build.vcxproj //p:Configuration=Release //m
|
||||
rpcs3_script:
|
||||
- export PATH=${PATH}:"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin"
|
||||
- msbuild.exe rpcs3.sln //p:Configuration=Release //m
|
||||
deploy_script:
|
||||
- mkdir artifacts
|
||||
- source './.ci/export-cirrus-vars.sh'
|
||||
- './.ci/deploy-windows.sh'
|
||||
artifacts:
|
||||
name: Artifact
|
||||
path: "*.7z*"
|
||||
# push_script: |
|
||||
# if [ "$CIRRUS_REPO_OWNER" = "RPCS3" ] && [ -z "$CIRRUS_PR" ] && [ "$CIRRUS_BRANCH" = "master" ]; then
|
||||
# source './.ci/export-cirrus-vars.sh'
|
||||
# './.ci/github-upload.sh'
|
||||
# fi;
|
||||
|
||||
linux_task:
|
||||
container:
|
||||
image: rpcs3/rpcs3-ci-bionic:1.0
|
||||
cpu: 4
|
||||
memory: 16G
|
||||
env:
|
||||
BUILD_ARTIFACTSTAGINGDIRECTORY: ${CIRRUS_WORKING_DIR}/artifacts
|
||||
CCACHE_DIR: "/tmp/ccache_dir"
|
||||
CCACHE_MAXSIZE: 300M
|
||||
CI_HAS_ARTIFACTS: true
|
||||
UPLOAD_COMMIT_HASH: d812f1254a1157c80fd402f94446310560f54e5f
|
||||
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux"
|
||||
DEPLOY_APPIMAGE: true
|
||||
APPDIR: "./appdir"
|
||||
ARTDIR: ${CIRRUS_WORKING_DIR}/artifacts/
|
||||
RELEASE_MESSAGE: "../GitHubReleaseMessage.txt"
|
||||
ccache_cache:
|
||||
folder: "/tmp/ccache_dir"
|
||||
matrix:
|
||||
- name: Cirrus Linux GCC
|
||||
env:
|
||||
COMPILER: gcc
|
||||
gcc_script:
|
||||
- mkdir artifacts
|
||||
- ".ci/build-linux.sh"
|
||||
- name: Cirrus Linux Clang
|
||||
env:
|
||||
COMPILER: clang
|
||||
clang_script:
|
||||
- mkdir artifacts
|
||||
- ".ci/build-linux.sh"
|
||||
artifacts:
|
||||
name: Artifact
|
||||
path: "artifacts/*"
|
||||
# push_script: |
|
||||
# if [ "$CIRRUS_REPO_OWNER" = "RPCS3" ] && [ -z "$CIRRUS_PR" ] && [ "$CIRRUS_BRANCH" = "master" ] && [ "$COMPILER" = "gcc" ]; then
|
||||
# '.ci/github-upload.sh'
|
||||
# fi;
|
||||
|
||||
freebsd_task:
|
||||
matrix:
|
||||
- name: FreeBSD 12.2 (snapshot)
|
||||
- name: FreeBSD 12.2
|
||||
freebsd_instance:
|
||||
image_family: freebsd-12-1-snap
|
||||
image_family: freebsd-12-2
|
||||
cpu: 8
|
||||
memory: 8G
|
||||
env:
|
||||
@@ -13,7 +109,5 @@ freebsd_task:
|
||||
CCACHE_DIR: /tmp/ccache_dir
|
||||
ccache_cache:
|
||||
folder: /tmp/ccache_dir
|
||||
packages_cache:
|
||||
folder: /var/cache/pkg
|
||||
install_script: "sh -ex ./.ci/install-freebsd.sh"
|
||||
script: "./.ci/build-freebsd.sh"
|
||||
|
||||
+11
-11
@@ -1,20 +1,20 @@
|
||||
Standard: Cpp11
|
||||
Standard: c++20
|
||||
UseTab: ForIndentation
|
||||
TabWidth: 1
|
||||
IndentWidth: 1
|
||||
AccessModifierOffset: -1
|
||||
TabWidth: 4
|
||||
IndentWidth: 4
|
||||
AccessModifierOffset: -4
|
||||
PointerAlignment: Left
|
||||
NamespaceIndentation: All
|
||||
ColumnLimit: 200
|
||||
ColumnLimit: 0
|
||||
BreakBeforeBraces: Allman
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
BreakBeforeBinaryOperators: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
Cpp11BracedListStyle: true
|
||||
IndentCaseLabels: false
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
root = true
|
||||
|
||||
[*.{h,cpp,hpp}]
|
||||
charset = utf-8-bom
|
||||
charset = utf-8
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Getting Started
|
||||
|
||||
Before getting started using the emulator, read the [Quickstart Guide](https://rpcs3.net/quickstart) and the [FAQ](https://rpcs3.net/faq). After reading those, if you need support, visit our [Forums](https://forums.rpcs3.net).
|
||||
Before getting started using the emulator, read the [Quickstart Guide](https://rpcs3.net/quickstart). After reading it, if you need support, check out [How to ask for Support](https://github.com/RPCS3/rpcs3/wiki/How-to-ask-for-Support).
|
||||
|
||||
# Issue Reporting
|
||||
|
||||
@@ -8,13 +8,12 @@ Before getting started using the emulator, read the [Quickstart Guide](https://r
|
||||
|
||||
**Before reporting an issue:**
|
||||
- Check if your system matches all the minimum requirements listed in the [Quickstart Guide](https://rpcs3.net/quickstart);
|
||||
- Check if the issue is meaningful for the team (e.g. The Last of Us doesn't work is obvious and therefore useless);
|
||||
- Search older issues/forum threads to see if your issue was already submitted.
|
||||
- Use understandable English. It doesn't need to be perfect, but clear enough to understand your message.
|
||||
- While reporting issues, don't forget to include details about your system (OS, CPU, GPU, etc.), as well as the RPCS3.log file.
|
||||
- Search older issues/forum threads to see if your issue was already submitted;
|
||||
- Use understandable English. It doesn't need to be perfect, but clear enough to understand your message;
|
||||
- While reporting issues, please follow the template for the type of issue you've selected (Regression Report, Bug Report or Feature Request), which is prefilled on the issue's textbox.
|
||||
|
||||
Submitting your test results for Commercial Games must be done on our forums. Please read the [Game Compatibility](https://github.com/RPCS3/rpcs3/wiki/Game-Compatibility) wiki page before doing so.
|
||||
|
||||
# Contributing
|
||||
|
||||
Check the [Coding Style Guidelines](https://github.com/RPCS3/rpcs3/wiki/Coding-Style), [Roadmap](https://github.com/RPCS3/rpcs3/wiki/Roadmap) and [Developer Information](https://github.com/RPCS3/rpcs3/wiki/Developer-Information). If you have any questions, hit us up on our [Discord Server](https://discord.me/RPCS3) in the **#development** channel.
|
||||
Check the [Coding Style Guidelines](https://github.com/RPCS3/rpcs3/wiki/Coding-Style) and [Developer Information](https://github.com/RPCS3/rpcs3/wiki/Developer-Information). If you have any questions, hit us up on our [Discord Server](https://discord.me/RPCS3) in the **#development** channel.
|
||||
|
||||
@@ -15,6 +15,10 @@ Please briefly describe what has stopped working correctly.
|
||||
## Details
|
||||
Please describe the regression as accurately as possible.
|
||||
|
||||
#### 0. Make sure you're running with settings as close to default as possible
|
||||
* **Do NOT enable any emulator game patches when reporting issues**
|
||||
* Only change settings that are required for the game to work
|
||||
|
||||
#### 1. Please provide _exact_ build (or commit) information that introduced the regression you're reporting.
|
||||
* Please see [How to find the build that caused a regression](https://wiki.rpcs3.net/index.php?title=Help:Using_different_versions_of_RPCS3#How_to_find_the_build_that_caused_a_regression.3F) in our wiki.
|
||||
* You can find [History of RPCS3 builds](https://rpcs3.net/compatibility?b) here.
|
||||
@@ -35,12 +39,12 @@ Please describe the regression as accurately as possible.
|
||||
On Windows it will be near the executable.
|
||||
* Attach the log:
|
||||
+ Drag and drop your log file into the issue.
|
||||
+ Or upload it to the cloud, such as Dropbox, Mega etc.
|
||||
+ Or upload it to the cloud, such as Dropbox, Mega etc.
|
||||
|
||||
#### 3. If you describe graphical regression, please provide an RSX capture and a RenderDoc capture that demonstrate it.
|
||||
* To create an RSX capture, use _Create_ _RSX_ _Capture_ under _Utilities_.
|
||||
Captures will be stored in RPCS3 folder → captures.
|
||||
+ Compress your capture with 7z, Rar etc.
|
||||
+ Compress your capture with 7z, Rar etc.
|
||||
And drag and drop it into the issue.
|
||||
+ Or upload it to the cloud, such as Dropbox, Mega etc.
|
||||
* To create a RenderDoc capture, please refer to [RenderDoc's documentation](https://renderdoc.org/docs/how/how_capture_frame.html).
|
||||
@@ -59,4 +63,4 @@ You can find it in _Emulator_ tab in _Settings_.
|
||||
* etc.
|
||||
|
||||
#### Please include.
|
||||
* Anything else you deem to be important
|
||||
* Anything else you deem to be important
|
||||
|
||||
@@ -16,6 +16,10 @@ Please briefly describe what is not working correctly.
|
||||
|
||||
Please describe the problem as accurately as possible.
|
||||
|
||||
#### 0. Make sure you're running with settings as close to default as possible
|
||||
* **Do NOT enable any emulator game patches when reporting issues**
|
||||
* Only change settings that are required for the game to work
|
||||
|
||||
#### 1. Please attach RPCS3's log.
|
||||
* Run the game until you find the issue.
|
||||
* Completely close RPCS3, or move to the next step in case it has crashed.
|
||||
@@ -28,12 +32,12 @@ Please describe the problem as accurately as possible.
|
||||
On Windows it will be near the executable.
|
||||
* Attach the log:
|
||||
+ Drag and drop your log file into the issue.
|
||||
+ Or upload it to the cloud, such as Dropbox, Mega etc.
|
||||
+ Or upload it to the cloud, such as Dropbox, Mega etc.
|
||||
|
||||
#### 2. If you describe graphical issue, please provide an RSX capture and a RenderDoc capture that demonstrate it.
|
||||
* To create an RSX capture, use _Create_ _RSX_ _Capture_ under _Utilities_.
|
||||
Captures will be stored in RPCS3 folder → captures.
|
||||
+ Compress your capture with 7z, Rar etc.
|
||||
+ Compress your capture with 7z, Rar etc.
|
||||
And drag and drop it into the issue.
|
||||
+ Or upload it to the cloud, such as Dropbox, Mega etc.
|
||||
* To create a RenderDoc capture, please refer to [RenderDoc's documentation](https://renderdoc.org/docs/how/how_capture_frame.html).
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
## How to test a PR build
|
||||
|
||||
Please take into account, that RPCS3 build usually takes some time (about 15 mins), so you can't access a build if a PR was just submitted.
|
||||
|
||||
- Open a PR you want to test
|
||||
- Scroll to the very bottom and locate the **Checks** section
|
||||
- Click on **Show all checks**
|
||||
You are supposed to see something like this
|
||||

|
||||
- Click on __Details__ on either **Cirrus Linux GCC** or **Cirrus Windows**
|
||||
- Click **View more details on Cirrus CI** at the very bottom
|
||||

|
||||
- Click on the download button for **Artifact** on the **Artifacts** block
|
||||

|
||||
|
||||
- Congratulations! You are now downloading an RPCS3 build for that specific PR.
|
||||
|
||||
__Please note that PR builds are not supposed to be stable because they contain new changesets.__
|
||||
@@ -0,0 +1,3 @@
|
||||
<!-- Please include a summary of the change and which issue is fixed. -->
|
||||
|
||||
[How to test this PR](.github/PR-BUILD.md)
|
||||
+12
-1
@@ -9,7 +9,7 @@
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
# *.a # Commented out since OpenAL Soft's binaries use this extension.
|
||||
*.a
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.suo
|
||||
@@ -45,6 +45,10 @@
|
||||
!/bin
|
||||
/bin/*
|
||||
|
||||
# Audio DLLs
|
||||
!/bin/soft_oal.dll
|
||||
!/bin/xaudio2_9redist.dll
|
||||
|
||||
# Themes
|
||||
!/bin/GuiConfigs/
|
||||
/bin/GuiConfigs/*.ini
|
||||
@@ -52,6 +56,9 @@
|
||||
/bin/GuiConfigs/*.dat
|
||||
/bin/GuiConfigs/*.dat.*
|
||||
|
||||
# Some data from git
|
||||
!/bin/git/
|
||||
|
||||
# Visual Studio Files
|
||||
.vs/*
|
||||
.vscode/*
|
||||
@@ -62,6 +69,8 @@
|
||||
*.vcxproj.user
|
||||
enc_temp_folder/*
|
||||
CMakeSettings.json
|
||||
*PVS-Studio*
|
||||
PVS/*
|
||||
|
||||
# Ignore other system generated files
|
||||
x64/*
|
||||
@@ -116,3 +125,5 @@ yaml-cpp.pc
|
||||
|
||||
# ssl certificate
|
||||
cacert.pem
|
||||
|
||||
_ReSharper.*/
|
||||
|
||||
+3
-2
@@ -4,7 +4,8 @@
|
||||
ignore = dirty
|
||||
[submodule "asmjit"]
|
||||
path = asmjit
|
||||
url = https://github.com/kobalicek/asmjit
|
||||
url = https://github.com/asmjit/asmjit
|
||||
branch = oldstable
|
||||
ignore = dirty
|
||||
[submodule "llvm"]
|
||||
path = llvm
|
||||
@@ -52,7 +53,7 @@
|
||||
url = https://github.com/glennrp/libpng.git
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/libusb"]
|
||||
path = 3rdparty/libusb
|
||||
path = 3rdparty/libusb/src
|
||||
url = https://github.com/libusb/libusb.git
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/FAudio"]
|
||||
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
language: cpp
|
||||
jobs:
|
||||
include:
|
||||
- os: linux
|
||||
dist: xenial
|
||||
env:
|
||||
- NAME="Linux build"
|
||||
- COMPILER="gcc"
|
||||
- DEPLOY_APPIMAGE="true"
|
||||
services: docker
|
||||
cache: ccache
|
||||
compiler: gcc
|
||||
install: "docker pull rpcs3/rpcs3-travis-xenial:1.6"
|
||||
script: 'travis_wait docker run -v $(pwd):/rpcs3 -v "$HOME/.ccache":/root/.ccache --env-file .ci/travis.env rpcs3/rpcs3-travis-xenial:1.6 /rpcs3/.ci/build-linux.sh'
|
||||
- os: linux
|
||||
dist: xenial
|
||||
env:
|
||||
- NAME="Linux build"
|
||||
- COMPILER="clang"
|
||||
services: docker
|
||||
cache: ccache
|
||||
compiler: clang
|
||||
install: "docker pull rpcs3/rpcs3-travis-xenial:1.6"
|
||||
script: 'travis_wait docker run -v $(pwd):/rpcs3 -v "$HOME/.ccache":/root/.ccache --env-file .ci/travis.env rpcs3/rpcs3-travis-xenial:1.6 /rpcs3/.ci/build-linux.sh'
|
||||
# - os: freebsd
|
||||
# compiler: clang
|
||||
# cache: ccache
|
||||
# install: "./.ci/install-freebsd.sh"
|
||||
# script: "./.ci/build-freebsd.sh"
|
||||
# - os: osx
|
||||
# osx_image: xcode11.3
|
||||
# addons:
|
||||
# homebrew:
|
||||
# packages:
|
||||
# - ccache
|
||||
# - glew
|
||||
# - ninja
|
||||
# - qt
|
||||
# script: "/bin/bash -ex .ci/build-mac.sh"
|
||||
# cache: ccache
|
||||
allow_failures:
|
||||
- os: osx
|
||||
|
||||
git:
|
||||
depth: false # Unshallow clone to obtain proper GIT_VERSION
|
||||
submodules: false
|
||||
Vendored
+4
-3
@@ -123,7 +123,7 @@ if(CMAKE_SYSTEM MATCHES "DragonFly|FreeBSD")
|
||||
elseif(MSVC)
|
||||
# Windows time.h defines timespec but doesn't add any flag for it, which makes libusb attempt to define it again
|
||||
add_definitions(-DHAVE_STRUCT_TIMESPEC=1)
|
||||
add_subdirectory(libusb_cmake EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(libusb EXCLUDE_FROM_ALL)
|
||||
else()
|
||||
if(USE_SYS_LIBUSB)
|
||||
# we have the system libusb and have selected to use it
|
||||
@@ -131,7 +131,8 @@ else()
|
||||
target_link_libraries(usb-1.0-shared INTERFACE PkgConfig::LIBUSB)
|
||||
else()
|
||||
# we don't have the system libusb, so we compile from submodule
|
||||
add_subdirectory(libusb_cmake EXCLUDE_FROM_ALL)
|
||||
unset(LIBUSB_LIBRARIES CACHE)
|
||||
add_subdirectory(libusb EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -354,7 +355,7 @@ target_link_libraries(3rdparty_openal INTERFACE ${OPENAL_LIBRARY})
|
||||
set(FAUDIO_TARGET 3rdparty_dummy_lib)
|
||||
if(USE_FAUDIO)
|
||||
# FAudio depends on SDL2
|
||||
pkg_check_modules(SDL2 sdl2)
|
||||
find_package(SDL2)
|
||||
if (NOT SDL2_FOUND OR SDL2_VERSION VERSION_LESS 2.0.9)
|
||||
message("-- RPCS3: FAudio requires SDL 2.0.9 or newer.")
|
||||
else()
|
||||
|
||||
Vendored
+1
-1
Submodule 3rdparty/FAudio updated: 9c7d2d1430...398ca114c0
+4
-4
@@ -8848,7 +8848,7 @@ bool VmaBlockMetadata_Generic::CheckAllocation(
|
||||
|
||||
// Check previous suballocations for BufferImageGranularity conflicts.
|
||||
// Make bigger alignment if necessary.
|
||||
if(bufferImageGranularity > 1)
|
||||
if(bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment)
|
||||
{
|
||||
bool bufferImageGranularityConflict = false;
|
||||
VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;
|
||||
@@ -8932,7 +8932,7 @@ bool VmaBlockMetadata_Generic::CheckAllocation(
|
||||
|
||||
// Check next suballocations for BufferImageGranularity conflicts.
|
||||
// If conflict exists, we must mark more allocations lost or fail.
|
||||
if(bufferImageGranularity > 1)
|
||||
if(bufferImageGranularity > 1 && (allocSize % bufferImageGranularity || *pOffset % bufferImageGranularity))
|
||||
{
|
||||
VmaSuballocationList::const_iterator nextSuballocItem = lastSuballocItem;
|
||||
++nextSuballocItem;
|
||||
@@ -8991,7 +8991,7 @@ bool VmaBlockMetadata_Generic::CheckAllocation(
|
||||
|
||||
// Check previous suballocations for BufferImageGranularity conflicts.
|
||||
// Make bigger alignment if necessary.
|
||||
if(bufferImageGranularity > 1)
|
||||
if(bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment)
|
||||
{
|
||||
bool bufferImageGranularityConflict = false;
|
||||
VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;
|
||||
@@ -9031,7 +9031,7 @@ bool VmaBlockMetadata_Generic::CheckAllocation(
|
||||
|
||||
// Check next suballocations for BufferImageGranularity conflicts.
|
||||
// If conflict exists, allocation cannot be made here.
|
||||
if(bufferImageGranularity > 1)
|
||||
if(bufferImageGranularity > 1 && (allocSize % bufferImageGranularity || *pOffset % bufferImageGranularity))
|
||||
{
|
||||
VmaSuballocationList::const_iterator nextSuballocItem = suballocItem;
|
||||
++nextSuballocItem;
|
||||
|
||||
Vendored
+31
-32
@@ -22,7 +22,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** Deprecated macro. */
|
||||
/* Deprecated macros. */
|
||||
#define OPENAL
|
||||
#define ALAPI AL_API
|
||||
#define ALAPIENTRY AL_APIENTRY
|
||||
@@ -30,7 +30,7 @@ extern "C" {
|
||||
#define AL_ILLEGAL_ENUM AL_INVALID_ENUM
|
||||
#define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION
|
||||
|
||||
/** Supported AL version. */
|
||||
/* Supported AL versions. */
|
||||
#define AL_VERSION_1_0
|
||||
#define AL_VERSION_1_1
|
||||
|
||||
@@ -234,7 +234,7 @@ typedef void ALvoid;
|
||||
*/
|
||||
#define AL_SOURCE_STATE 0x1010
|
||||
|
||||
/** Source state value. */
|
||||
/* Source state values. */
|
||||
#define AL_INITIAL 0x1011
|
||||
#define AL_PLAYING 0x1012
|
||||
#define AL_PAUSED 0x1013
|
||||
@@ -300,7 +300,7 @@ typedef void ALvoid;
|
||||
* Source maximum distance.
|
||||
* Type: ALfloat
|
||||
* Range: [0.0 - ]
|
||||
* Default: +inf
|
||||
* Default: FLT_MAX
|
||||
*
|
||||
* The distance above which the source is not attenuated any further with a
|
||||
* clamped distance model, or where attenuation reaches 0.0 gain for linear
|
||||
@@ -330,15 +330,18 @@ typedef void ALvoid;
|
||||
*/
|
||||
#define AL_SOURCE_TYPE 0x1027
|
||||
|
||||
/** Source type value. */
|
||||
/* Source type values. */
|
||||
#define AL_STATIC 0x1028
|
||||
#define AL_STREAMING 0x1029
|
||||
#define AL_UNDETERMINED 0x1030
|
||||
|
||||
/** Buffer format specifier. */
|
||||
/** Unsigned 8-bit mono buffer format. */
|
||||
#define AL_FORMAT_MONO8 0x1100
|
||||
/** Signed 16-bit mono buffer format. */
|
||||
#define AL_FORMAT_MONO16 0x1101
|
||||
/** Unsigned 8-bit stereo buffer format. */
|
||||
#define AL_FORMAT_STEREO8 0x1102
|
||||
/** Signed 16-bit stereo buffer format. */
|
||||
#define AL_FORMAT_STEREO16 0x1103
|
||||
|
||||
/** Buffer frequency (query only). */
|
||||
@@ -350,11 +353,7 @@ typedef void ALvoid;
|
||||
/** Buffer data size (query only). */
|
||||
#define AL_SIZE 0x2004
|
||||
|
||||
/**
|
||||
* Buffer state.
|
||||
*
|
||||
* Not for public use.
|
||||
*/
|
||||
/* Buffer state. Not for public use. */
|
||||
#define AL_UNUSED 0x2010
|
||||
#define AL_PENDING 0x2011
|
||||
#define AL_PROCESSED 0x2012
|
||||
@@ -441,7 +440,7 @@ AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value);
|
||||
#define AL_DISTANCE_MODEL 0xD000
|
||||
AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel);
|
||||
|
||||
/** Distance model value. */
|
||||
/* Distance model values. */
|
||||
#define AL_INVERSE_DISTANCE 0xD001
|
||||
#define AL_INVERSE_DISTANCE_CLAMPED 0xD002
|
||||
#define AL_LINEAR_DISTANCE 0xD003
|
||||
@@ -449,12 +448,12 @@ AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel);
|
||||
#define AL_EXPONENT_DISTANCE 0xD005
|
||||
#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006
|
||||
|
||||
/** Renderer State management. */
|
||||
/* Renderer State management. */
|
||||
AL_API void AL_APIENTRY alEnable(ALenum capability);
|
||||
AL_API void AL_APIENTRY alDisable(ALenum capability);
|
||||
AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability);
|
||||
|
||||
/** State retrieval. */
|
||||
/* State retrieval. */
|
||||
AL_API const ALchar* AL_APIENTRY alGetString(ALenum param);
|
||||
AL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values);
|
||||
AL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values);
|
||||
@@ -465,25 +464,25 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum param);
|
||||
AL_API ALfloat AL_APIENTRY alGetFloat(ALenum param);
|
||||
AL_API ALdouble AL_APIENTRY alGetDouble(ALenum param);
|
||||
|
||||
/**
|
||||
* Error retrieval.
|
||||
*
|
||||
* Obtain the first error generated in the AL context since the last check.
|
||||
*/
|
||||
/* Error retrieval. */
|
||||
|
||||
/** Obtain the first error generated in the AL context since the last check. */
|
||||
AL_API ALenum AL_APIENTRY alGetError(void);
|
||||
|
||||
/**
|
||||
* Extension support.
|
||||
*
|
||||
* Query for the presence of an extension, and obtain any appropriate function
|
||||
* pointers and enum values.
|
||||
*/
|
||||
/** Query for the presence of an extension on the AL context. */
|
||||
AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname);
|
||||
/**
|
||||
* Retrieve the address of a function. The returned function may be context-
|
||||
* specific.
|
||||
*/
|
||||
AL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname);
|
||||
/**
|
||||
* Retrieve the value of an enum. The returned value may be context-specific.
|
||||
*/
|
||||
AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename);
|
||||
|
||||
|
||||
/** Set Listener parameters */
|
||||
/* Set Listener parameters */
|
||||
AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value);
|
||||
AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);
|
||||
AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values);
|
||||
@@ -491,7 +490,7 @@ AL_API void AL_APIENTRY alListeneri(ALenum param, ALint value);
|
||||
AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3);
|
||||
AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values);
|
||||
|
||||
/** Get Listener parameters */
|
||||
/* Get Listener parameters */
|
||||
AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value);
|
||||
AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);
|
||||
AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values);
|
||||
@@ -507,7 +506,7 @@ AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources);
|
||||
/** Verify a handle is a valid Source. */
|
||||
AL_API ALboolean AL_APIENTRY alIsSource(ALuint source);
|
||||
|
||||
/** Set Source parameters. */
|
||||
/* Set Source parameters. */
|
||||
AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value);
|
||||
AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);
|
||||
AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values);
|
||||
@@ -515,7 +514,7 @@ AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value);
|
||||
AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3);
|
||||
AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values);
|
||||
|
||||
/** Get Source parameters. */
|
||||
/* Get Source parameters. */
|
||||
AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value);
|
||||
AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);
|
||||
AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values);
|
||||
@@ -558,7 +557,7 @@ AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer);
|
||||
/** Specifies the data to be copied into a buffer */
|
||||
AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq);
|
||||
|
||||
/** Set Buffer parameters, */
|
||||
/* Set Buffer parameters, */
|
||||
AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value);
|
||||
AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);
|
||||
AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values);
|
||||
@@ -566,7 +565,7 @@ AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value);
|
||||
AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3);
|
||||
AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values);
|
||||
|
||||
/** Get Buffer parameters. */
|
||||
/* Get Buffer parameters. */
|
||||
AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value);
|
||||
AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);
|
||||
AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values);
|
||||
@@ -574,7 +573,7 @@ AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value);
|
||||
AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3);
|
||||
AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values);
|
||||
|
||||
/** Pointer-to-function type, useful for dynamically getting AL entry points. */
|
||||
/* Pointer-to-function type, useful for dynamically getting AL entry points. */
|
||||
typedef void (AL_APIENTRY *LPALENABLE)(ALenum capability);
|
||||
typedef void (AL_APIENTRY *LPALDISABLE)(ALenum capability);
|
||||
typedef ALboolean (AL_APIENTRY *LPALISENABLED)(ALenum capability);
|
||||
|
||||
Vendored
+54
-21
@@ -22,7 +22,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** Deprecated macro. */
|
||||
/* Deprecated macros. */
|
||||
#define ALCAPI ALC_API
|
||||
#define ALCAPIENTRY ALC_APIENTRY
|
||||
#define ALC_INVALID 0
|
||||
@@ -89,7 +89,7 @@ typedef void ALCvoid;
|
||||
/** Context attribute: <int> Hz. */
|
||||
#define ALC_REFRESH 0x1008
|
||||
|
||||
/** Context attribute: AL_TRUE or AL_FALSE. */
|
||||
/** Context attribute: AL_TRUE or AL_FALSE synchronous context? */
|
||||
#define ALC_SYNC 0x1009
|
||||
|
||||
/** Context attribute: <int> requested Mono (3D) Sources. */
|
||||
@@ -117,12 +117,14 @@ typedef void ALCvoid;
|
||||
#define ALC_OUT_OF_MEMORY 0xA005
|
||||
|
||||
|
||||
/** Runtime ALC version. */
|
||||
/** Runtime ALC major version. */
|
||||
#define ALC_MAJOR_VERSION 0x1000
|
||||
/** Runtime ALC minor version. */
|
||||
#define ALC_MINOR_VERSION 0x1001
|
||||
|
||||
/** Context attribute list properties. */
|
||||
/** Context attribute list size. */
|
||||
#define ALC_ATTRIBUTES_SIZE 0x1002
|
||||
/** Context attribute list properties. */
|
||||
#define ALC_ALL_ATTRIBUTES 0x1003
|
||||
|
||||
/** String for the default device specifier. */
|
||||
@@ -166,49 +168,80 @@ typedef void ALCvoid;
|
||||
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
||||
|
||||
|
||||
/** Context management. */
|
||||
ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint* attrlist);
|
||||
/* Context management. */
|
||||
|
||||
/** Create and attach a context to the given device. */
|
||||
ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrlist);
|
||||
/**
|
||||
* Makes the given context the active process-wide context. Passing NULL clears
|
||||
* the active context.
|
||||
*/
|
||||
ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context);
|
||||
/** Resumes processing updates for the given context. */
|
||||
ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context);
|
||||
/** Suspends updates for the given context. */
|
||||
ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context);
|
||||
/** Remove a context from its device and destroys it. */
|
||||
ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context);
|
||||
/** Returns the currently active context. */
|
||||
ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void);
|
||||
/** Returns the device that a particular context is attached to. */
|
||||
ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context);
|
||||
|
||||
/** Device management. */
|
||||
/* Device management. */
|
||||
|
||||
/** Opens the named playback device. */
|
||||
ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename);
|
||||
/** Closes the given playback device. */
|
||||
ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device);
|
||||
|
||||
/* Error support. */
|
||||
|
||||
/**
|
||||
* Error support.
|
||||
*
|
||||
* Obtain the most recent Device error.
|
||||
*/
|
||||
/** Obtain the most recent Device error. */
|
||||
ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device);
|
||||
|
||||
/* Extension support. */
|
||||
|
||||
/**
|
||||
* Extension support.
|
||||
*
|
||||
* Query for the presence of an extension, and obtain any appropriate
|
||||
* function pointers and enum values.
|
||||
* Query for the presence of an extension on the device. Pass a NULL device to
|
||||
* query a device-inspecific extension.
|
||||
*/
|
||||
ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname);
|
||||
ALC_API void* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname);
|
||||
/**
|
||||
* Retrieve the address of a function. Given a non-NULL device, the returned
|
||||
* function may be device-specific.
|
||||
*/
|
||||
ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname);
|
||||
/**
|
||||
* Retrieve the value of an enum. Given a non-NULL device, the returned value
|
||||
* may be device-specific.
|
||||
*/
|
||||
ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname);
|
||||
|
||||
/** Query function. */
|
||||
/* Query functions. */
|
||||
|
||||
/** Returns information about the device, and error strings. */
|
||||
ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param);
|
||||
/** Returns information about the device and the version of OpenAL. */
|
||||
ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values);
|
||||
|
||||
/** Capture function. */
|
||||
/* Capture functions. */
|
||||
|
||||
/**
|
||||
* Opens the named capture device with the given frequency, format, and buffer
|
||||
* size.
|
||||
*/
|
||||
ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize);
|
||||
/** Closes the given capture device. */
|
||||
ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device);
|
||||
/** Starts capturing samples into the device buffer. */
|
||||
ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device);
|
||||
/** Stops capturing samples. Samples in the device buffer remain available. */
|
||||
ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device);
|
||||
/** Reads samples from the device buffer. */
|
||||
ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
|
||||
|
||||
/** Pointer-to-function type, useful for dynamically getting ALC entry points. */
|
||||
/* Pointer-to-function type, useful for dynamically getting ALC entry points. */
|
||||
typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist);
|
||||
typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context);
|
||||
typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context);
|
||||
@@ -220,7 +253,7 @@ typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename
|
||||
typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device);
|
||||
typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device);
|
||||
typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname);
|
||||
typedef void* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname);
|
||||
typedef ALCvoid* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname);
|
||||
typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname);
|
||||
typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param);
|
||||
typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values);
|
||||
|
||||
Vendored
+68
-19
@@ -22,17 +22,20 @@
|
||||
#define AL_ALEXT_H
|
||||
|
||||
#include <stddef.h>
|
||||
/* Define int64_t and uint64_t types */
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
#include <inttypes.h>
|
||||
#elif defined(_WIN32) && defined(__GNUC__)
|
||||
/* Define int64 and uint64 types */
|
||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
|
||||
(defined(__cplusplus) && __cplusplus >= 201103L)
|
||||
#include <stdint.h>
|
||||
typedef int64_t _alsoft_int64_t;
|
||||
typedef uint64_t _alsoft_uint64_t;
|
||||
#elif defined(_WIN32)
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef __int64 _alsoft_int64_t;
|
||||
typedef unsigned __int64 _alsoft_uint64_t;
|
||||
#else
|
||||
/* Fallback if nothing above works */
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
typedef int64_t _alsoft_int64_t;
|
||||
typedef uint64_t _alsoft_uint64_t;
|
||||
#endif
|
||||
|
||||
#include "alc.h"
|
||||
@@ -158,9 +161,9 @@ extern "C" {
|
||||
|
||||
#ifndef AL_EXT_STATIC_BUFFER
|
||||
#define AL_EXT_STATIC_BUFFER 1
|
||||
typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei);
|
||||
typedef void (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API ALvoid AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq);
|
||||
AL_API void AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -193,9 +196,9 @@ ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void);
|
||||
#define AL_SOFT_buffer_sub_data 1
|
||||
#define AL_BYTE_RW_OFFSETS_SOFT 0x1031
|
||||
#define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032
|
||||
typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei);
|
||||
typedef void (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length);
|
||||
AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -343,8 +346,8 @@ ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffe
|
||||
#define AL_SOFT_source_latency 1
|
||||
#define AL_SAMPLE_OFFSET_LATENCY_SOFT 0x1200
|
||||
#define AL_SEC_OFFSET_LATENCY_SOFT 0x1201
|
||||
typedef int64_t ALint64SOFT;
|
||||
typedef uint64_t ALuint64SOFT;
|
||||
typedef _alsoft_int64_t ALint64SOFT;
|
||||
typedef _alsoft_uint64_t ALuint64SOFT;
|
||||
typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble);
|
||||
typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble);
|
||||
typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*);
|
||||
@@ -381,11 +384,11 @@ AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64
|
||||
#ifndef AL_SOFT_deferred_updates
|
||||
#define AL_SOFT_deferred_updates 1
|
||||
#define AL_DEFERRED_UPDATES_SOFT 0xC002
|
||||
typedef ALvoid (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void);
|
||||
typedef ALvoid (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void);
|
||||
typedef void (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void);
|
||||
typedef void (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void);
|
||||
AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void);
|
||||
AL_API void AL_APIENTRY alDeferUpdatesSOFT(void);
|
||||
AL_API void AL_APIENTRY alProcessUpdatesSOFT(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -496,8 +499,8 @@ AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index);
|
||||
|
||||
#ifndef ALC_SOFT_device_clock
|
||||
#define ALC_SOFT_device_clock 1
|
||||
typedef int64_t ALCint64SOFT;
|
||||
typedef uint64_t ALCuint64SOFT;
|
||||
typedef _alsoft_int64_t ALCint64SOFT;
|
||||
typedef _alsoft_uint64_t ALCuint64SOFT;
|
||||
#define ALC_DEVICE_CLOCK_SOFT 0x1600
|
||||
#define ALC_DEVICE_LATENCY_SOFT 0x1601
|
||||
#define ALC_DEVICE_CLOCK_LATENCY_SOFT 0x1602
|
||||
@@ -530,6 +533,52 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname,
|
||||
#define AL_N3D_SOFT 0x0002
|
||||
#endif
|
||||
|
||||
#ifndef ALC_SOFT_loopback_bformat
|
||||
#define ALC_SOFT_loopback_bformat 1
|
||||
#define ALC_AMBISONIC_LAYOUT_SOFT 0x1997
|
||||
#define ALC_AMBISONIC_SCALING_SOFT 0x1998
|
||||
#define ALC_AMBISONIC_ORDER_SOFT 0x1999
|
||||
#define ALC_MAX_AMBISONIC_ORDER_SOFT 0x199B
|
||||
|
||||
#define ALC_BFORMAT3D_SOFT 0x1507
|
||||
|
||||
/* Ambisonic layouts */
|
||||
#define ALC_FUMA_SOFT 0x0000
|
||||
#define ALC_ACN_SOFT 0x0001
|
||||
|
||||
/* Ambisonic scalings (normalization) */
|
||||
/*#define ALC_FUMA_SOFT*/
|
||||
#define ALC_SN3D_SOFT 0x0001
|
||||
#define ALC_N3D_SOFT 0x0002
|
||||
#endif
|
||||
|
||||
#ifndef AL_SOFT_effect_target
|
||||
#define AL_SOFT_effect_target
|
||||
#define AL_EFFECTSLOT_TARGET_SOFT 0x199C
|
||||
#endif
|
||||
|
||||
#ifndef AL_SOFT_events
|
||||
#define AL_SOFT_events 1
|
||||
#define AL_EVENT_CALLBACK_FUNCTION_SOFT 0x19A2
|
||||
#define AL_EVENT_CALLBACK_USER_PARAM_SOFT 0x19A3
|
||||
#define AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT 0x19A4
|
||||
#define AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT 0x19A5
|
||||
#define AL_EVENT_TYPE_DISCONNECTED_SOFT 0x19A6
|
||||
typedef void (AL_APIENTRY*ALEVENTPROCSOFT)(ALenum eventType, ALuint object, ALuint param,
|
||||
ALsizei length, const ALchar *message,
|
||||
void *userParam);
|
||||
typedef void (AL_APIENTRY*LPALEVENTCONTROLSOFT)(ALsizei count, const ALenum *types, ALboolean enable);
|
||||
typedef void (AL_APIENTRY*LPALEVENTCALLBACKSOFT)(ALEVENTPROCSOFT callback, void *userParam);
|
||||
typedef void* (AL_APIENTRY*LPALGETPOINTERSOFT)(ALenum pname);
|
||||
typedef void (AL_APIENTRY*LPALGETPOINTERVSOFT)(ALenum pname, void **values);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable);
|
||||
AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam);
|
||||
AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname);
|
||||
AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Vendored
+30
-30
@@ -243,41 +243,41 @@ typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*
|
||||
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*);
|
||||
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects);
|
||||
AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects);
|
||||
AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects);
|
||||
AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect);
|
||||
AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue);
|
||||
AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue);
|
||||
AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
|
||||
AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue);
|
||||
AL_API void AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues);
|
||||
AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue);
|
||||
AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues);
|
||||
AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue);
|
||||
AL_API void AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues);
|
||||
AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue);
|
||||
AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters);
|
||||
AL_API void AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters);
|
||||
AL_API void AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters);
|
||||
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter);
|
||||
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue);
|
||||
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue);
|
||||
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
|
||||
AL_API void AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue);
|
||||
AL_API void AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues);
|
||||
AL_API void AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue);
|
||||
AL_API void AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues);
|
||||
AL_API void AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue);
|
||||
AL_API void AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues);
|
||||
AL_API void AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue);
|
||||
AL_API void AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots);
|
||||
AL_API void AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
|
||||
AL_API void AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots);
|
||||
AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
|
||||
AL_API void AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue);
|
||||
AL_API void AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues);
|
||||
AL_API void AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue);
|
||||
AL_API void AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues);
|
||||
AL_API void AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue);
|
||||
AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
|
||||
AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue);
|
||||
AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
|
||||
#endif
|
||||
|
||||
/* Filter ranges and defaults. */
|
||||
|
||||
+80
@@ -1,35 +1,84 @@
|
||||
EXPORTS
|
||||
alAuxiliaryEffectSlotPlaySOFT
|
||||
alAuxiliaryEffectSlotPlayvSOFT
|
||||
alAuxiliaryEffectSlotStopSOFT
|
||||
alAuxiliaryEffectSlotStopvSOFT
|
||||
alAuxiliaryEffectSlotf
|
||||
alAuxiliaryEffectSlotfv
|
||||
alAuxiliaryEffectSloti
|
||||
alAuxiliaryEffectSlotiv
|
||||
alBuffer3f
|
||||
alBuffer3i
|
||||
alBufferCallbackSOFT
|
||||
alBufferData
|
||||
alBufferSamplesSOFT
|
||||
alBufferStorageSOFT
|
||||
alBufferSubDataSOFT
|
||||
alBufferSubSamplesSOFT
|
||||
alBufferf
|
||||
alBufferfv
|
||||
alBufferi
|
||||
alBufferiv
|
||||
alDeferUpdatesSOFT
|
||||
alDeleteAuxiliaryEffectSlots
|
||||
alDeleteBuffers
|
||||
alDeleteEffects
|
||||
alDeleteFilters
|
||||
alDeleteSources
|
||||
alDisable
|
||||
alDistanceModel
|
||||
alDopplerFactor
|
||||
alDopplerVelocity
|
||||
alEffectf
|
||||
alEffectfv
|
||||
alEffecti
|
||||
alEffectiv
|
||||
alEnable
|
||||
alEventCallbackSOFT
|
||||
alEventControlSOFT
|
||||
alFilterf
|
||||
alFilterfv
|
||||
alFilteri
|
||||
alFilteriv
|
||||
alFlushMappedBufferSOFT
|
||||
alGenAuxiliaryEffectSlots
|
||||
alGenBuffers
|
||||
alGenEffects
|
||||
alGenFilters
|
||||
alGenSources
|
||||
alGetAuxiliaryEffectSlotf
|
||||
alGetAuxiliaryEffectSlotfv
|
||||
alGetAuxiliaryEffectSloti
|
||||
alGetAuxiliaryEffectSlotiv
|
||||
alGetBoolean
|
||||
alGetBooleanv
|
||||
alGetBuffer3PtrSOFT
|
||||
alGetBuffer3f
|
||||
alGetBuffer3i
|
||||
alGetBufferPtrSOFT
|
||||
alGetBufferPtrvSOFT
|
||||
alGetBufferSamplesSOFT
|
||||
alGetBufferf
|
||||
alGetBufferfv
|
||||
alGetBufferi
|
||||
alGetBufferiv
|
||||
alGetDouble
|
||||
alGetDoublev
|
||||
alGetEffectf
|
||||
alGetEffectfv
|
||||
alGetEffecti
|
||||
alGetEffectiv
|
||||
alGetEnumValue
|
||||
alGetError
|
||||
alGetFilterf
|
||||
alGetFilterfv
|
||||
alGetFilteri
|
||||
alGetFilteriv
|
||||
alGetFloat
|
||||
alGetFloatv
|
||||
alGetInteger
|
||||
alGetInteger64SOFT
|
||||
alGetInteger64vSOFT
|
||||
alGetIntegerv
|
||||
alGetListener3f
|
||||
alGetListener3i
|
||||
@@ -37,17 +86,30 @@ EXPORTS
|
||||
alGetListenerfv
|
||||
alGetListeneri
|
||||
alGetListeneriv
|
||||
alGetPointerSOFT
|
||||
alGetPointervSOFT
|
||||
alGetProcAddress
|
||||
alGetSource3dSOFT
|
||||
alGetSource3f
|
||||
alGetSource3i
|
||||
alGetSource3i64SOFT
|
||||
alGetSourcedSOFT
|
||||
alGetSourcedvSOFT
|
||||
alGetSourcef
|
||||
alGetSourcefv
|
||||
alGetSourcei
|
||||
alGetSourcei64SOFT
|
||||
alGetSourcei64vSOFT
|
||||
alGetSourceiv
|
||||
alGetString
|
||||
alGetStringiSOFT
|
||||
alIsAuxiliaryEffectSlot
|
||||
alIsBuffer
|
||||
alIsBufferFormatSupportedSOFT
|
||||
alIsEffect
|
||||
alIsEnabled
|
||||
alIsExtensionPresent
|
||||
alIsFilter
|
||||
alIsSource
|
||||
alListener3f
|
||||
alListener3i
|
||||
@@ -55,8 +117,12 @@ EXPORTS
|
||||
alListenerfv
|
||||
alListeneri
|
||||
alListeneriv
|
||||
alMapBufferSOFT
|
||||
alProcessUpdatesSOFT
|
||||
alSource3dSOFT
|
||||
alSource3f
|
||||
alSource3i
|
||||
alSource3i64SOFT
|
||||
alSourcePause
|
||||
alSourcePausev
|
||||
alSourcePlay
|
||||
@@ -67,11 +133,16 @@ EXPORTS
|
||||
alSourceStop
|
||||
alSourceStopv
|
||||
alSourceUnqueueBuffers
|
||||
alSourcedSOFT
|
||||
alSourcedvSOFT
|
||||
alSourcef
|
||||
alSourcefv
|
||||
alSourcei
|
||||
alSourcei64SOFT
|
||||
alSourcei64vSOFT
|
||||
alSourceiv
|
||||
alSpeedOfSound
|
||||
alUnmapBufferSOFT
|
||||
alcCaptureCloseDevice
|
||||
alcCaptureOpenDevice
|
||||
alcCaptureSamples
|
||||
@@ -80,17 +151,26 @@ EXPORTS
|
||||
alcCloseDevice
|
||||
alcCreateContext
|
||||
alcDestroyContext
|
||||
alcDevicePauseSOFT
|
||||
alcDeviceResumeSOFT
|
||||
alcGetContextsDevice
|
||||
alcGetCurrentContext
|
||||
alcGetEnumValue
|
||||
alcGetError
|
||||
alcGetInteger64vSOFT
|
||||
alcGetIntegerv
|
||||
alcGetProcAddress
|
||||
alcGetString
|
||||
alcGetStringiSOFT
|
||||
alcGetThreadContext
|
||||
alcIsExtensionPresent
|
||||
alcIsRenderFormatSupportedSOFT
|
||||
alcLoopbackOpenDeviceSOFT
|
||||
alcMakeContextCurrent
|
||||
alcOpenDevice
|
||||
alcProcessContext
|
||||
alcRenderSamplesSOFT
|
||||
alcResetDeviceSOFT
|
||||
alcSetThreadContext
|
||||
alcSuspendContext
|
||||
alsoft_get_version
|
||||
|
||||
BIN
Binary file not shown.
+10
-9
@@ -18,10 +18,10 @@
|
||||
|
||||
// Current name of the DLL shipped in the same SDK as this header.
|
||||
// The name reflects the current version
|
||||
#define XAUDIO2_DLL_A "xaudio2redist.dll"
|
||||
#define XAUDIO2_DLL_W L"xaudio2redist.dll"
|
||||
#define XAUDIO2D_DLL_A "xaudio2redist.dll"
|
||||
#define XAUDIO2D_DLL_W L"xaudio2redist.dll"
|
||||
#define XAUDIO2_DLL_A "xaudio2_9redist.dll"
|
||||
#define XAUDIO2_DLL_W L"xaudio2_9redist.dll"
|
||||
#define XAUDIO2D_DLL_A "xaudio2_9redist.dll"
|
||||
#define XAUDIO2D_DLL_W L"xaudio2_9redist.dll"
|
||||
|
||||
#ifdef UNICODE
|
||||
#define XAUDIO2_DLL XAUDIO2_DLL_W
|
||||
@@ -446,7 +446,7 @@ DECLARE_INTERFACE_(IXAudio2, IUnknown)
|
||||
// ARGUMENTS:
|
||||
// pCallback - Callback interface to be called during each processing pass.
|
||||
//
|
||||
STDMETHOD(RegisterForCallbacks) (_In_ IXAudio2EngineCallback* pCallback) PURE;
|
||||
STDMETHOD(RegisterForCallbacks) (THIS_ _In_ IXAudio2EngineCallback* pCallback) PURE;
|
||||
|
||||
// NAME: IXAudio2::UnregisterForCallbacks
|
||||
// DESCRIPTION: Removes an existing receiver of XAudio2 engine callbacks.
|
||||
@@ -454,7 +454,7 @@ DECLARE_INTERFACE_(IXAudio2, IUnknown)
|
||||
// ARGUMENTS:
|
||||
// pCallback - Previously registered callback interface to be removed.
|
||||
//
|
||||
STDMETHOD_(void, UnregisterForCallbacks) (_In_ IXAudio2EngineCallback* pCallback) PURE;
|
||||
STDMETHOD_(void, UnregisterForCallbacks) (THIS_ _In_ IXAudio2EngineCallback* pCallback) PURE;
|
||||
|
||||
// NAME: IXAudio2::CreateSourceVoice
|
||||
// DESCRIPTION: Creates and configures a source voice.
|
||||
@@ -1047,6 +1047,8 @@ DECLARE_INTERFACE(IXAudio2VoiceCallback)
|
||||
#define IXAudio2_QueryInterface(This,riid,ppvInterface) ((This)->lpVtbl->QueryInterface(This,riid,ppvInterface))
|
||||
#define IXAudio2_AddRef(This) ((This)->lpVtbl->AddRef(This))
|
||||
#define IXAudio2_Release(This) ((This)->lpVtbl->Release(This))
|
||||
#define IXAudio2_RegisterForCallbacks(This,pCallback) ((This)->lpVtbl->RegisterForCallbacks(This,pCallback))
|
||||
#define IXAudio2_UnregisterForCallbacks(This,pCallback) ((This)->lpVtbl->UnregisterForCallbacks(This,pCallback))
|
||||
#define IXAudio2_CreateSourceVoice(This,ppSourceVoice,pSourceFormat,Flags,MaxFrequencyRatio,pCallback,pSendList,pEffectChain) ((This)->lpVtbl->CreateSourceVoice(This,ppSourceVoice,pSourceFormat,Flags,MaxFrequencyRatio,pCallback,pSendList,pEffectChain))
|
||||
#define IXAudio2_CreateSubmixVoice(This,ppSubmixVoice,InputChannels,InputSampleRate,Flags,ProcessingStage,pSendList,pEffectChain) ((This)->lpVtbl->CreateSubmixVoice(This,ppSubmixVoice,InputChannels,InputSampleRate,Flags,ProcessingStage,pSendList,pEffectChain))
|
||||
#define IXAudio2_CreateMasteringVoice(This,ppMasteringVoice,InputChannels,InputSampleRate,Flags,DeviceId,pEffectChain,StreamCategory) ((This)->lpVtbl->CreateMasteringVoice(This,ppMasteringVoice,InputChannels,InputSampleRate,Flags,DeviceId,pEffectChain,StreamCategory))
|
||||
@@ -1215,7 +1217,7 @@ __inline float XAudio2CutoffFrequencyToRadians(float CutoffFrequency, UINT32 Sam
|
||||
{
|
||||
return XAUDIO2_MAX_FILTER_FREQUENCY;
|
||||
}
|
||||
return 2.0f * sinf((float)M_PI * CutoffFrequency / SampleRate);
|
||||
return 2.0f * sinf((float)M_PI * CutoffFrequency / (float)SampleRate);
|
||||
}
|
||||
|
||||
// Convert from radian frequencies back to absolute frequencies in Hertz
|
||||
@@ -1234,7 +1236,7 @@ __inline float XAudio2CutoffFrequencyToOnePoleCoefficient(float CutoffFrequency,
|
||||
{
|
||||
return XAUDIO2_MAX_FILTER_FREQUENCY;
|
||||
}
|
||||
return ( 1.0f - powf(1.0f - 2.0f * CutoffFrequency / SampleRate, 2.0f) );
|
||||
return ( 1.0f - powf(1.0f - 2.0f * CutoffFrequency / (float)SampleRate, 2.0f) );
|
||||
}
|
||||
|
||||
|
||||
@@ -1271,4 +1273,3 @@ XAUDIO2_STDAPI XAudio2Create(_Outptr_ IXAudio2** ppXAudio2, UINT32 Flags X2DEFAU
|
||||
#endif // #ifndef GUID_DEFS_ONLY
|
||||
|
||||
#endif // #ifndef __XAUDIO2_INCLUDED__
|
||||
|
||||
|
||||
BIN
Binary file not shown.
Vendored
+1
-1
Submodule 3rdparty/curl updated: 9d954e49bc...566b74a0e1
Vendored
+1
-1
Submodule 3rdparty/hidapi updated: 9220f5e77c...8961cf86eb
Vendored
+13
-9
@@ -1,14 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug - LLVM|x64">
|
||||
<Configuration>Debug - LLVM</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release - LLVM|x64">
|
||||
<Configuration>Release - LLVM</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
@@ -72,6 +64,7 @@
|
||||
<ClCompile Include="curl\lib\asyn-ares.c" />
|
||||
<ClCompile Include="curl\lib\asyn-thread.c" />
|
||||
<ClCompile Include="curl\lib\base64.c" />
|
||||
<ClCompile Include="curl\lib\c-hyper.c" />
|
||||
<ClCompile Include="curl\lib\conncache.c" />
|
||||
<ClCompile Include="curl\lib\connect.c" />
|
||||
<ClCompile Include="curl\lib\content_encoding.c" />
|
||||
@@ -99,6 +92,8 @@
|
||||
<ClCompile Include="curl\lib\dotdot.c" />
|
||||
<ClCompile Include="curl\lib\dynbuf.c" />
|
||||
<ClCompile Include="curl\lib\easy.c" />
|
||||
<ClCompile Include="curl\lib\easygetopt.c" />
|
||||
<ClCompile Include="curl\lib\easyoptions.c" />
|
||||
<ClCompile Include="curl\lib\escape.c" />
|
||||
<ClCompile Include="curl\lib\file.c" />
|
||||
<ClCompile Include="curl\lib\fileinfo.c" />
|
||||
@@ -116,8 +111,10 @@
|
||||
<ClCompile Include="curl\lib\hostip4.c" />
|
||||
<ClCompile Include="curl\lib\hostip6.c" />
|
||||
<ClCompile Include="curl\lib\hostsyn.c" />
|
||||
<ClCompile Include="curl\lib\hsts.c" />
|
||||
<ClCompile Include="curl\lib\http.c" />
|
||||
<ClCompile Include="curl\lib\http2.c" />
|
||||
<ClCompile Include="curl\lib\http_aws_sigv4.c" />
|
||||
<ClCompile Include="curl\lib\http_chunks.c" />
|
||||
<ClCompile Include="curl\lib\http_digest.c" />
|
||||
<ClCompile Include="curl\lib\http_negotiate.c" />
|
||||
@@ -152,7 +149,6 @@
|
||||
<ClCompile Include="curl\lib\rand.c" />
|
||||
<ClCompile Include="curl\lib\rename.c" />
|
||||
<ClCompile Include="curl\lib\rtsp.c" />
|
||||
<ClCompile Include="curl\lib\security.c" />
|
||||
<ClCompile Include="curl\lib\select.c" />
|
||||
<ClCompile Include="curl\lib\sendf.c" />
|
||||
<ClCompile Include="curl\lib\setopt.c" />
|
||||
@@ -179,8 +175,10 @@
|
||||
<ClCompile Include="curl\lib\transfer.c" />
|
||||
<ClCompile Include="curl\lib\url.c" />
|
||||
<ClCompile Include="curl\lib\urlapi.c" />
|
||||
<ClCompile Include="curl\lib\vauth\gsasl.c" />
|
||||
<ClCompile Include="curl\lib\version.c" />
|
||||
<ClCompile Include="curl\lib\version_win32.c" />
|
||||
<ClCompile Include="curl\lib\vtls\rustls.c" />
|
||||
<ClCompile Include="curl\lib\warnless.c" />
|
||||
<ClCompile Include="curl\lib\wildcard.c" />
|
||||
<ClCompile Include="curl\lib\x509asn1.c" />
|
||||
@@ -231,6 +229,7 @@
|
||||
<ClInclude Include="curl\lib\amigaos.h" />
|
||||
<ClInclude Include="curl\lib\arpa_telnet.h" />
|
||||
<ClInclude Include="curl\lib\asyn.h" />
|
||||
<ClInclude Include="curl\lib\c-hyper.h" />
|
||||
<ClInclude Include="curl\lib\config-amigaos.h" />
|
||||
<ClInclude Include="curl\lib\config-dos.h" />
|
||||
<ClInclude Include="curl\lib\config-mac.h" />
|
||||
@@ -257,6 +256,7 @@
|
||||
<ClInclude Include="curl\lib\curl_get_line.h" />
|
||||
<ClInclude Include="curl\lib\curl_gssapi.h" />
|
||||
<ClInclude Include="curl\lib\curl_hmac.h" />
|
||||
<ClInclude Include="curl\lib\curl_krb5.h" />
|
||||
<ClInclude Include="curl\lib\curl_ldap.h" />
|
||||
<ClInclude Include="curl\lib\curl_md4.h" />
|
||||
<ClInclude Include="curl\lib\curl_md5.h" />
|
||||
@@ -281,6 +281,7 @@
|
||||
<ClInclude Include="curl\lib\dotdot.h" />
|
||||
<ClInclude Include="curl\lib\dynbuf.h" />
|
||||
<ClInclude Include="curl\lib\easyif.h" />
|
||||
<ClInclude Include="curl\lib\easyoptions.h" />
|
||||
<ClInclude Include="curl\lib\escape.h" />
|
||||
<ClInclude Include="curl\lib\file.h" />
|
||||
<ClInclude Include="curl\lib\fileinfo.h" />
|
||||
@@ -292,8 +293,10 @@
|
||||
<ClInclude Include="curl\lib\hash.h" />
|
||||
<ClInclude Include="curl\lib\hostcheck.h" />
|
||||
<ClInclude Include="curl\lib\hostip.h" />
|
||||
<ClInclude Include="curl\lib\hsts.h" />
|
||||
<ClInclude Include="curl\lib\http.h" />
|
||||
<ClInclude Include="curl\lib\http2.h" />
|
||||
<ClInclude Include="curl\lib\http_aws_sigv4.h" />
|
||||
<ClInclude Include="curl\lib\http_chunks.h" />
|
||||
<ClInclude Include="curl\lib\http_digest.h" />
|
||||
<ClInclude Include="curl\lib\http_negotiate.h" />
|
||||
@@ -351,6 +354,7 @@
|
||||
<ClInclude Include="curl\lib\urlapi-int.h" />
|
||||
<ClInclude Include="curl\lib\urldata.h" />
|
||||
<ClInclude Include="curl\lib\version_win32.h" />
|
||||
<ClInclude Include="curl\lib\vtls\rustls.h" />
|
||||
<ClInclude Include="curl\lib\warnless.h" />
|
||||
<ClInclude Include="curl\lib\wildcard.h" />
|
||||
<ClInclude Include="curl\lib\x509asn1.h" />
|
||||
|
||||
Vendored
+72
-3
@@ -264,9 +264,6 @@
|
||||
<ClCompile Include="curl\lib\rtsp.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\security.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\select.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -447,6 +444,42 @@
|
||||
<ClCompile Include="curl\lib\vtls\wolfssl.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\dynbuf.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\mqtt.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\version_win32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\vquic\vquic.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\vtls\keylog.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\c-hyper.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\easygetopt.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\easyoptions.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\hsts.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\http_aws_sigv4.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\vtls\rustls.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="curl\lib\vauth\gsasl.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="curl\include\curl\curl.h">
|
||||
@@ -902,6 +935,42 @@
|
||||
<ClInclude Include="curl\lib\vtls\wolfssl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\dynbuf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\mqtt.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\setup-win32.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\version_win32.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\vquic\vquic.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\vtls\keylog.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\c-hyper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\curl_krb5.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\easyoptions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\hsts.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\http_aws_sigv4.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="curl\lib\vtls\rustls.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="curl\lib\libcurl.rc">
|
||||
|
||||
Vendored
+1
-1
Submodule 3rdparty/libpng updated: eddf902320...a40189cf88
@@ -1,11 +1,11 @@
|
||||
cmake_minimum_required(VERSION 2.8.4)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
|
||||
|
||||
set(LIBUSB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../libusb/)
|
||||
|
||||
project(libusb)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
|
||||
set(LIBUSB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
|
||||
|
||||
option(WITH_DEBUG_LOG "enable debug logging" OFF)
|
||||
# if debug logging is enabled, by default enable logging
|
||||
option(WITH_LOGGING "if false, disable all logging" ON)
|
||||
Vendored
@@ -2,7 +2,7 @@ include(CheckCXXCompilerFlag)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckTypeSize)
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
if (${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
|
||||
if (NOT OS_WINDOWS)
|
||||
# mingw appears to print a bunch of warnings about this
|
||||
check_cxx_compiler_flag("-fvisibility=hidden" HAVE_VISIBILITY)
|
||||
@@ -15,9 +15,9 @@
|
||||
<ProjectGuid>{349EE8F9-7D25-4909-AAF5-FF3FADE72187}</ProjectGuid>
|
||||
<RootNamespace>libusb</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\common_default.props" />
|
||||
<Import Project="..\..\common_default.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="..\common_default_macros.props" />
|
||||
<Import Project="..\..\common_default_macros.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
@@ -42,7 +42,7 @@
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>libusb\msvc;libusb\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>src\msvc;src\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WINVER=0x0600;_WIN32_WINNT=0x0600;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
@@ -61,30 +61,30 @@
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="libusb\libusb\core.c" />
|
||||
<ClCompile Include="libusb\libusb\descriptor.c" />
|
||||
<ClCompile Include="libusb\libusb\hotplug.c" />
|
||||
<ClCompile Include="libusb\libusb\io.c" />
|
||||
<ClCompile Include="libusb\libusb\os\events_windows.c" />
|
||||
<ClCompile Include="libusb\libusb\strerror.c" />
|
||||
<ClCompile Include="libusb\libusb\sync.c" />
|
||||
<ClCompile Include="libusb\libusb\os\threads_windows.c" />
|
||||
<ClCompile Include="libusb\libusb\os\windows_common.c" />
|
||||
<ClCompile Include="libusb\libusb\os\windows_usbdk.c" />
|
||||
<ClCompile Include="libusb\libusb\os\windows_winusb.c" />
|
||||
<ClCompile Include="src\libusb\core.c" />
|
||||
<ClCompile Include="src\libusb\descriptor.c" />
|
||||
<ClCompile Include="src\libusb\hotplug.c" />
|
||||
<ClCompile Include="src\libusb\io.c" />
|
||||
<ClCompile Include="src\libusb\os\events_windows.c" />
|
||||
<ClCompile Include="src\libusb\strerror.c" />
|
||||
<ClCompile Include="src\libusb\sync.c" />
|
||||
<ClCompile Include="src\libusb\os\threads_windows.c" />
|
||||
<ClCompile Include="src\libusb\os\windows_common.c" />
|
||||
<ClCompile Include="src\libusb\os\windows_usbdk.c" />
|
||||
<ClCompile Include="src\libusb\os\windows_winusb.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="libusb\msvc\config.h" />
|
||||
<ClInclude Include="libusb\libusb\hotplug.h" />
|
||||
<ClInclude Include="libusb\libusb\libusb.h" />
|
||||
<ClInclude Include="libusb\libusb\libusbi.h" />
|
||||
<ClInclude Include="libusb\libusb\os\events_windows.h" />
|
||||
<ClInclude Include="libusb\libusb\os\threads_windows.h" />
|
||||
<ClInclude Include="libusb\libusb\version.h" />
|
||||
<ClInclude Include="libusb\libusb\version_nano.h" />
|
||||
<ClInclude Include="libusb\libusb\os\windows_common.h" />
|
||||
<ClInclude Include="libusb\libusb\os\windows_usbdk.h" />
|
||||
<ClInclude Include="libusb\libusb\os\windows_winusb.h" />
|
||||
<ClInclude Include="src\msvc\config.h" />
|
||||
<ClInclude Include="src\libusb\hotplug.h" />
|
||||
<ClInclude Include="src\libusb\libusb.h" />
|
||||
<ClInclude Include="src\libusb\libusbi.h" />
|
||||
<ClInclude Include="src\libusb\os\events_windows.h" />
|
||||
<ClInclude Include="src\libusb\os\threads_windows.h" />
|
||||
<ClInclude Include="src\libusb\version.h" />
|
||||
<ClInclude Include="src\libusb\version_nano.h" />
|
||||
<ClInclude Include="src\libusb\os\windows_common.h" />
|
||||
<ClInclude Include="src\libusb\os\windows_usbdk.h" />
|
||||
<ClInclude Include="src\libusb\os\windows_winusb.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
Vendored
+1
-1
Submodule 3rdparty/pugixml updated: 8bf806c035...08b3433180
Vendored
+9
-11
@@ -1,11 +1,13 @@
|
||||
add_library(3rdparty_qt5 INTERFACE)
|
||||
|
||||
find_package(Qt5 5.14 CONFIG COMPONENTS Widgets Concurrent)
|
||||
set(QT_MIN_VER 5.15.2)
|
||||
|
||||
find_package(Qt5 ${QT_MIN_VER} CONFIG COMPONENTS Widgets Concurrent)
|
||||
if(WIN32)
|
||||
find_package(Qt5 5.14 COMPONENTS WinExtras REQUIRED)
|
||||
find_package(Qt5 ${QT_MIN_VER} COMPONENTS WinExtras REQUIRED)
|
||||
target_link_libraries(3rdparty_qt5 INTERFACE Qt5::Widgets Qt5::WinExtras Qt5::Concurrent)
|
||||
else()
|
||||
find_package(Qt5 5.14 COMPONENTS DBus Gui)
|
||||
find_package(Qt5 ${QT_MIN_VER} COMPONENTS DBus Gui)
|
||||
if(Qt5DBus_FOUND)
|
||||
target_link_libraries(3rdparty_qt5 INTERFACE Qt5::Widgets Qt5::DBus Qt5::Concurrent)
|
||||
target_compile_definitions(3rdparty_qt5 INTERFACE -DHAVE_QTDBUS)
|
||||
@@ -16,16 +18,12 @@ else()
|
||||
endif()
|
||||
|
||||
if(NOT Qt5Widgets_FOUND)
|
||||
if(Qt5Widgets_VERSION VERSION_LESS 5.14.0)
|
||||
message("Minimum supported Qt5 version is 5.14.0! You have version ${Qt5Widgets_VERSION} installed, please upgrade!")
|
||||
if(Qt5Widgets_VERSION VERSION_LESS ${QT_MIN_VER})
|
||||
message("Minimum supported Qt5 version is ${QT_MIN_VER}! You have version ${Qt5Widgets_VERSION} installed, please upgrade!")
|
||||
if(CMAKE_SYSTEM MATCHES "Linux")
|
||||
message(FATAL_ERROR "Most distros do not provide an up-to-date version of Qt.
|
||||
If you're on Ubuntu or Linux Mint, there are PPAs you can use to install one of the latest qt5 versions.
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt-5.14.1-bionic
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt-5.14.1-xenial
|
||||
just make sure to run
|
||||
source /opt/qt514/bin/qt514-env.sh
|
||||
before re-running cmake")
|
||||
Find the correct ppa at https://launchpad.net/~beineri and follow the instructions.")
|
||||
elseif(WIN32)
|
||||
message(FATAL_ERROR "You can download the latest version of Qt5 here: https://www.qt.io/download-open-source/")
|
||||
else()
|
||||
@@ -35,7 +33,7 @@ before re-running cmake")
|
||||
|
||||
message("CMake was unable to find Qt5!")
|
||||
if(WIN32)
|
||||
message(FATAL_ERROR "Make sure the QTDIR env variable has been set properly. (for example C:\\Qt\\5.14.1\\msvc2017_64\\)
|
||||
message(FATAL_ERROR "Make sure the QTDIR env variable has been set properly. (for example C:\\Qt\\${QT_MIN_VER}\\msvc2019_64\\)
|
||||
You can also try setting the Qt5_DIR preprocessor definiton.")
|
||||
elseif(CMAKE_SYSTEM MATCHES "Linux")
|
||||
message(FATAL_ERROR "Make sure to install your distro's qt5 package!")
|
||||
|
||||
Vendored
+345
-130
File diff suppressed because it is too large
Load Diff
Vendored
+206
-77
@@ -1,5 +1,14 @@
|
||||
// stb_truetype.h - v1.21 - public domain
|
||||
// authored from 2009-2016 by Sean Barrett / RAD Game Tools
|
||||
// stb_truetype.h - v1.24 - public domain
|
||||
// authored from 2009-2020 by Sean Barrett / RAD Game Tools
|
||||
//
|
||||
// =======================================================================
|
||||
//
|
||||
// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES
|
||||
//
|
||||
// This library does no range checking of the offsets found in the file,
|
||||
// meaning an attacker can use it to read arbitrary memory.
|
||||
//
|
||||
// =======================================================================
|
||||
//
|
||||
// This library processes TrueType files:
|
||||
// parse files
|
||||
@@ -32,11 +41,11 @@
|
||||
// Daniel Ribeiro Maciel
|
||||
//
|
||||
// Bug/warning reports/fixes:
|
||||
// "Zer" on mollyrocket Fabian "ryg" Giesen
|
||||
// Cass Everitt Martins Mozeiko
|
||||
// stoiko (Haemimont Games) Cap Petschulat
|
||||
// Brian Hook Omar Cornut
|
||||
// Walter van Niftrik github:aloucks
|
||||
// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe
|
||||
// Cass Everitt Martins Mozeiko github:aloucks
|
||||
// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam
|
||||
// Brian Hook Omar Cornut github:vassvik
|
||||
// Walter van Niftrik Ryan Griege
|
||||
// David Gow Peter LaValle
|
||||
// David Given Sergey Popov
|
||||
// Ivan-Assen Ivanov Giumo X. Clanjor
|
||||
@@ -44,11 +53,14 @@
|
||||
// Johan Duparc Thomas Fields
|
||||
// Hou Qiming Derek Vinyard
|
||||
// Rob Loach Cort Stratton
|
||||
// Kenney Phillis Jr. github:oyvindjam
|
||||
// Brian Costabile github:vassvik
|
||||
//
|
||||
// Kenney Phillis Jr. Brian Costabile
|
||||
// Ken Voskuil (kaesve)
|
||||
//
|
||||
// VERSION HISTORY
|
||||
//
|
||||
// 1.24 (2020-02-05) fix warning
|
||||
// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
|
||||
// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
|
||||
// 1.21 (2019-02-25) fix warning
|
||||
// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
|
||||
// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
|
||||
@@ -208,7 +220,7 @@
|
||||
//
|
||||
// Advancing for the next character:
|
||||
// Call GlyphHMetrics, and compute 'current_point += SF * advance'.
|
||||
//
|
||||
//
|
||||
//
|
||||
// ADVANCED USAGE
|
||||
//
|
||||
@@ -333,7 +345,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
//
|
||||
// Output:
|
||||
//
|
||||
@@ -347,9 +359,9 @@ int main(int argc, char **argv)
|
||||
// :@@. M@M
|
||||
// @@@o@@@@
|
||||
// :M@@V:@@.
|
||||
//
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// Complete program: print "Hello World!" banner, with bugs
|
||||
//
|
||||
#if 0
|
||||
@@ -650,7 +662,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, cons
|
||||
// Calling these functions in sequence is roughly equivalent to calling
|
||||
// stbtt_PackFontRanges(). If you more control over the packing of multiple
|
||||
// fonts, or if you want to pack custom data into a font texture, take a look
|
||||
// at the source to of stbtt_PackFontRanges() and create a custom version
|
||||
// at the source to of stbtt_PackFontRanges() and create a custom version
|
||||
// using these functions, e.g. call GatherRects multiple times,
|
||||
// building up a single array of rects, then call PackRects once,
|
||||
// then call RenderIntoRects repeatedly. This may result in a
|
||||
@@ -702,7 +714,7 @@ struct stbtt_fontinfo
|
||||
|
||||
int numGlyphs; // number of glyphs, needed for range checking
|
||||
|
||||
int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf
|
||||
int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf
|
||||
int index_map; // a cmap mapping for our chosen character encoding
|
||||
int indexToLocFormat; // format needed to map from glyph index to glyph
|
||||
|
||||
@@ -785,6 +797,18 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1,
|
||||
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
|
||||
// as above, but takes one or more glyph indices for greater efficiency
|
||||
|
||||
typedef struct stbtt_kerningentry
|
||||
{
|
||||
int glyph1; // use stbtt_FindGlyphIndex
|
||||
int glyph2;
|
||||
int advance;
|
||||
} stbtt_kerningentry;
|
||||
|
||||
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info);
|
||||
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length);
|
||||
// Retrieves a complete list of all of the kerning pairs provided by the font
|
||||
// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write.
|
||||
// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -829,6 +853,11 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
|
||||
STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
|
||||
// frees the data allocated above
|
||||
|
||||
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
|
||||
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
|
||||
// fills svg with the character's SVG data.
|
||||
// returns data size or 0 if SVG not found.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BITMAP RENDERING
|
||||
@@ -958,7 +987,7 @@ STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, floa
|
||||
// and computing from that can allow drop-out prevention).
|
||||
//
|
||||
// The algorithm has not been optimized at all, so expect it to be slow
|
||||
// if computing lots of characters or very large sizes.
|
||||
// if computing lots of characters or very large sizes.
|
||||
|
||||
|
||||
|
||||
@@ -1330,6 +1359,22 @@ static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
|
||||
return stbtt__cff_get_index(&cff);
|
||||
}
|
||||
|
||||
// since most people won't use this, find this table the first time it's needed
|
||||
static int stbtt__get_svg(stbtt_fontinfo *info)
|
||||
{
|
||||
stbtt_uint32 t;
|
||||
if (info->svg < 0) {
|
||||
t = stbtt__find_table(info->data, info->fontstart, "SVG ");
|
||||
if (t) {
|
||||
stbtt_uint32 offset = ttULONG(info->data + t + 2);
|
||||
info->svg = t + offset;
|
||||
} else {
|
||||
info->svg = 0;
|
||||
}
|
||||
}
|
||||
return info->svg;
|
||||
}
|
||||
|
||||
static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
|
||||
{
|
||||
stbtt_uint32 cmap, t;
|
||||
@@ -1409,6 +1454,8 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in
|
||||
else
|
||||
info->numGlyphs = 0xffff;
|
||||
|
||||
info->svg = -1;
|
||||
|
||||
// find a cmap encoding table we understand *now* to avoid searching
|
||||
// later. (todo: could make this installable)
|
||||
// the same regardless of glyph.
|
||||
@@ -1715,7 +1762,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
||||
if (i != 0)
|
||||
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
|
||||
|
||||
// now start the new one
|
||||
// now start the new one
|
||||
start_off = !(flags & 1);
|
||||
if (start_off) {
|
||||
// if we start off with an off-curve point, then when we need to find a point on the curve
|
||||
@@ -1757,7 +1804,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
||||
}
|
||||
}
|
||||
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
|
||||
} else if (numberOfContours == -1) {
|
||||
} else if (numberOfContours < 0) {
|
||||
// Compound shapes.
|
||||
int more = 1;
|
||||
stbtt_uint8 *comp = data + g + 10;
|
||||
@@ -1768,7 +1815,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
||||
int comp_num_verts = 0, i;
|
||||
stbtt_vertex *comp_verts = 0, *tmp = 0;
|
||||
float mtx[6] = {1,0,0,1,0,0}, m, n;
|
||||
|
||||
|
||||
flags = ttSHORT(comp); comp+=2;
|
||||
gidx = ttSHORT(comp); comp+=2;
|
||||
|
||||
@@ -1798,7 +1845,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
||||
mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
|
||||
mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
|
||||
}
|
||||
|
||||
|
||||
// Find transformation scales.
|
||||
m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
|
||||
n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
|
||||
@@ -1834,9 +1881,6 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
||||
// More components ?
|
||||
more = flags & (1<<5);
|
||||
}
|
||||
} else if (numberOfContours < 0) {
|
||||
// @TODO other compound variations?
|
||||
STBTT_assert(0);
|
||||
} else {
|
||||
// numberOfCounters == 0, do nothing
|
||||
}
|
||||
@@ -2265,6 +2309,48 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde
|
||||
}
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
|
||||
{
|
||||
stbtt_uint8 *data = info->data + info->kern;
|
||||
|
||||
// we only look at the first table. it must be 'horizontal' and format 0.
|
||||
if (!info->kern)
|
||||
return 0;
|
||||
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
|
||||
return 0;
|
||||
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
|
||||
return 0;
|
||||
|
||||
return ttUSHORT(data+10);
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)
|
||||
{
|
||||
stbtt_uint8 *data = info->data + info->kern;
|
||||
int k, length;
|
||||
|
||||
// we only look at the first table. it must be 'horizontal' and format 0.
|
||||
if (!info->kern)
|
||||
return 0;
|
||||
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
|
||||
return 0;
|
||||
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
|
||||
return 0;
|
||||
|
||||
length = ttUSHORT(data+10);
|
||||
if (table_length < length)
|
||||
length = table_length;
|
||||
|
||||
for (k = 0; k < length; k++)
|
||||
{
|
||||
table[k].glyph1 = ttUSHORT(data+18+(k*6));
|
||||
table[k].glyph2 = ttUSHORT(data+20+(k*6));
|
||||
table[k].advance = ttSHORT(data+22+(k*6));
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
|
||||
{
|
||||
stbtt_uint8 *data = info->data + info->kern;
|
||||
@@ -2540,8 +2626,7 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int
|
||||
|
||||
if (info->gpos)
|
||||
xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
|
||||
|
||||
if (info->kern)
|
||||
else if (info->kern)
|
||||
xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
|
||||
|
||||
return xAdvance;
|
||||
@@ -2602,6 +2687,45 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
|
||||
STBTT_free(v, info->userdata);
|
||||
}
|
||||
|
||||
STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
|
||||
{
|
||||
int i;
|
||||
stbtt_uint8 *data = info->data;
|
||||
stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
|
||||
|
||||
int numEntries = ttUSHORT(svg_doc_list);
|
||||
stbtt_uint8 *svg_docs = svg_doc_list + 2;
|
||||
|
||||
for(i=0; i<numEntries; i++) {
|
||||
stbtt_uint8 *svg_doc = svg_docs + (12 * i);
|
||||
if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
|
||||
return svg_doc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
|
||||
{
|
||||
stbtt_uint8 *data = info->data;
|
||||
stbtt_uint8 *svg_doc;
|
||||
|
||||
if (info->svg == 0)
|
||||
return 0;
|
||||
|
||||
svg_doc = stbtt_FindSVGDoc(info, gl);
|
||||
if (svg_doc != NULL) {
|
||||
*svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
|
||||
return ttULONG(svg_doc + 8);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
|
||||
{
|
||||
return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// antialiasing software rasterizer
|
||||
@@ -2727,7 +2851,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i
|
||||
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
|
||||
STBTT_assert(z != NULL);
|
||||
if (!z) return z;
|
||||
|
||||
|
||||
// round dx down to avoid overshooting
|
||||
if (dxdy < 0)
|
||||
z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
|
||||
@@ -2805,7 +2929,7 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
@@ -3533,7 +3657,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info
|
||||
{
|
||||
int ix0,iy0,ix1,iy1;
|
||||
stbtt__bitmap gbm;
|
||||
stbtt_vertex *vertices;
|
||||
stbtt_vertex *vertices;
|
||||
int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
|
||||
|
||||
if (scale_x == 0) scale_x = scale_y;
|
||||
@@ -3556,7 +3680,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info
|
||||
if (height) *height = gbm.h;
|
||||
if (xoff ) *xoff = ix0;
|
||||
if (yoff ) *yoff = iy0;
|
||||
|
||||
|
||||
if (gbm.w && gbm.h) {
|
||||
gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
|
||||
if (gbm.pixels) {
|
||||
@@ -3567,7 +3691,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info
|
||||
}
|
||||
STBTT_free(vertices, info->userdata);
|
||||
return gbm.pixels;
|
||||
}
|
||||
}
|
||||
|
||||
STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
|
||||
{
|
||||
@@ -3579,7 +3703,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigne
|
||||
int ix0,iy0;
|
||||
stbtt_vertex *vertices;
|
||||
int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
|
||||
stbtt__bitmap gbm;
|
||||
stbtt__bitmap gbm;
|
||||
|
||||
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
|
||||
gbm.pixels = output;
|
||||
@@ -3601,7 +3725,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *
|
||||
STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
|
||||
{
|
||||
return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
|
||||
}
|
||||
}
|
||||
|
||||
STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
|
||||
{
|
||||
@@ -3616,7 +3740,7 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns
|
||||
STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
|
||||
{
|
||||
return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
|
||||
}
|
||||
}
|
||||
|
||||
STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
|
||||
{
|
||||
@@ -3741,7 +3865,7 @@ static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *no
|
||||
con->y = 0;
|
||||
con->bottom_y = 0;
|
||||
STBTT__NOTUSED(nodes);
|
||||
STBTT__NOTUSED(num_nodes);
|
||||
STBTT__NOTUSED(num_nodes);
|
||||
}
|
||||
|
||||
static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
|
||||
@@ -3968,6 +4092,7 @@ static float stbtt__oversample_shift(int oversample)
|
||||
STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
|
||||
{
|
||||
int i,j,k;
|
||||
int missing_glyph_added = 0;
|
||||
|
||||
k=0;
|
||||
for (i=0; i < num_ranges; ++i) {
|
||||
@@ -3979,7 +4104,7 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
|
||||
int x0,y0,x1,y1;
|
||||
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
|
||||
int glyph = stbtt_FindGlyphIndex(info, codepoint);
|
||||
if (glyph == 0 && spc->skip_missing) {
|
||||
if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
|
||||
rects[k].w = rects[k].h = 0;
|
||||
} else {
|
||||
stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
|
||||
@@ -3989,6 +4114,8 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
|
||||
&x0,&y0,&x1,&y1);
|
||||
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
|
||||
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
|
||||
if (glyph == 0)
|
||||
missing_glyph_added = 1;
|
||||
}
|
||||
++k;
|
||||
}
|
||||
@@ -4023,7 +4150,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info
|
||||
// rects array must be big enough to accommodate all characters in the given ranges
|
||||
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
|
||||
{
|
||||
int i,j,k, return_value = 1;
|
||||
int i,j,k, missing_glyph = -1, return_value = 1;
|
||||
|
||||
// save current values
|
||||
int old_h_over = spc->h_oversample;
|
||||
@@ -4088,6 +4215,13 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
|
||||
bc->yoff = (float) y0 * recip_v + sub_y;
|
||||
bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
|
||||
bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
|
||||
|
||||
if (glyph == 0)
|
||||
missing_glyph = j;
|
||||
} else if (spc->skip_missing) {
|
||||
return_value = 0;
|
||||
} else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
|
||||
ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
|
||||
} else {
|
||||
return_value = 0; // if any fail, report failure
|
||||
}
|
||||
@@ -4126,7 +4260,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char
|
||||
n = 0;
|
||||
for (i=0; i < num_ranges; ++i)
|
||||
n += ranges[i].num_chars;
|
||||
|
||||
|
||||
rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
|
||||
if (rects == NULL)
|
||||
return 0;
|
||||
@@ -4137,7 +4271,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char
|
||||
n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
|
||||
|
||||
stbtt_PackFontRangesPackRects(spc, rects, n);
|
||||
|
||||
|
||||
return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
|
||||
|
||||
STBTT_free(rects, spc->user_allocator_context);
|
||||
@@ -4298,7 +4432,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
|
||||
int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y;
|
||||
if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
|
||||
float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
|
||||
if (x_inter < x)
|
||||
if (x_inter < x)
|
||||
winding += (y0 < y1) ? 1 : -1;
|
||||
}
|
||||
}
|
||||
@@ -4324,7 +4458,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
|
||||
y1 = (int)verts[i ].y;
|
||||
if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
|
||||
float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
|
||||
if (x_inter < x)
|
||||
if (x_inter < x)
|
||||
winding += (y0 < y1) ? 1 : -1;
|
||||
}
|
||||
} else {
|
||||
@@ -4336,7 +4470,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
|
||||
if (hits[1][0] < 0)
|
||||
winding += (hits[1][1] < 0 ? -1 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return winding;
|
||||
@@ -4389,12 +4523,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
||||
int w,h;
|
||||
unsigned char *data;
|
||||
|
||||
// if one scale is 0, use same scale for both
|
||||
if (scale_x == 0) scale_x = scale_y;
|
||||
if (scale_y == 0) {
|
||||
if (scale_x == 0) return NULL; // if both scales are 0, return NULL
|
||||
scale_y = scale_x;
|
||||
}
|
||||
if (scale == 0) return NULL;
|
||||
|
||||
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
|
||||
|
||||
@@ -4417,7 +4546,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
||||
|
||||
// invert for y-downwards bitmaps
|
||||
scale_y = -scale_y;
|
||||
|
||||
|
||||
{
|
||||
int x,y,i,j;
|
||||
float *precompute;
|
||||
@@ -4566,7 +4695,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
|
||||
STBTT_free(verts, info->userdata);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
|
||||
{
|
||||
@@ -4584,7 +4713,7 @@ STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
|
||||
//
|
||||
|
||||
// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
|
||||
static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
|
||||
static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
|
||||
{
|
||||
stbtt_int32 i=0;
|
||||
|
||||
@@ -4623,7 +4752,7 @@ static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, s
|
||||
return i;
|
||||
}
|
||||
|
||||
static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
|
||||
static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
|
||||
{
|
||||
return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
|
||||
}
|
||||
@@ -4752,7 +4881,7 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
|
||||
|
||||
STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
|
||||
{
|
||||
return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
|
||||
return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
|
||||
@@ -4845,38 +4974,38 @@ This software is available under 2 licenses -- choose whichever you prefer.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2017 Sean Barrett
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||
This is free and unencumbered software released into the public domain.
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
commercial or non-commercial, and by any means.
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
this software under copyright law.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
+28
-23
@@ -7,22 +7,22 @@ Other instructions may be found [here](https://wiki.rpcs3.net/index.php?title=Bu
|
||||
|
||||
### Windows 7 or later
|
||||
|
||||
* [CMake 3.14.1+](https://www.cmake.org/download/) (add to PATH)
|
||||
* [Python 3.3+](https://www.python.org/downloads/) (add to PATH)
|
||||
* [Qt 5.14.2](https://www.qt.io/download-qt-installer)
|
||||
* [CMake 3.16.9+](https://www.cmake.org/download/) (add to PATH)
|
||||
* [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
|
||||
* [Qt 5.15.2](https://www.qt.io/download-qt-installer)
|
||||
* [Visual Studio 2019](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
|
||||
* [Vulkan SDK 1.1.126+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html))
|
||||
* [Vulkan SDK 1.2.154+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html))
|
||||
|
||||
**Either add the** `QTDIR` **environment variable, e.g.** `<QtInstallFolder>\5.14.2\msvc2017_64\` **, or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2019)**
|
||||
**Either add the** `QTDIR` **environment variable, e.g.** `<QtInstallFolder>\5.15.2\msvc2019_64\` **, or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2019)**
|
||||
|
||||
### Linux
|
||||
|
||||
These are the essentials tools to build RPCS3 on Linux. Some of them can be installed through your favorite package manager.
|
||||
|
||||
* Clang 9+ or GCC 9+
|
||||
* [CMake 3.14.1+](https://www.cmake.org/download/)
|
||||
* [Qt 5.14.2](https://www.qt.io/download-qt-installer)
|
||||
* [Vulkan SDK 1.1.126+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html))
|
||||
* Clang 12+ or GCC 10+
|
||||
* [CMake 3.16.9+](https://www.cmake.org/download/)
|
||||
* [Qt 5.15.2](https://www.qt.io/download-qt-installer)
|
||||
* [Vulkan SDK 1.2.154+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html))
|
||||
* [SDL2](https://www.libsdl.org/download-2.0.php) (for the FAudio backend)
|
||||
|
||||
**If you have an NVIDIA GPU, you may need to install the libglvnd package.**
|
||||
@@ -41,22 +41,22 @@ Ubuntu is usually horrendously out of date, and some packages need to be downloa
|
||||
Ubuntu usually does not have a new enough Qt package to suit rpcs3's needs. There is a PPA available to work around this. Run the following:
|
||||
```
|
||||
. /etc/os-release
|
||||
sudo add-apt-repository ppa:beineri/opt-qt-5.14.2-$UBUNTU_CODENAME
|
||||
sudo add-apt-repository ppa:beineri/opt-qt-5.15.2-$UBUNTU_CODENAME
|
||||
sudo apt-get update
|
||||
sudo apt-get install qt514-meta-minimal qt514svg
|
||||
. /opt/qt514/bin/qt514-env.sh >/dev/null 2>&1
|
||||
sudo apt-get install qt515base qt515svg
|
||||
. /opt/qt515/bin/qt515-env.sh >/dev/null 2>&1
|
||||
```
|
||||
|
||||
##### GCC 9.x installation
|
||||
##### GCC 10.x installation
|
||||
|
||||
If the `gcc-9` package is not available on your system, use the following commands
|
||||
If the `gcc-10` package is not available on your system, use the following commands
|
||||
```
|
||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-9 g++-9
|
||||
sudo apt-get install gcc-10 g++-10
|
||||
```
|
||||
|
||||
You can either use `update-alternatives` to setup `gcc-9`/`g++-9` as your default compilers or prefix any `cmake` command by `CXX=g++-9 CC=gcc-9 ` to use it.
|
||||
You can either use `update-alternatives` to setup `gcc-10`/`g++-10` as your default compilers or prefix any `cmake` command by `CXX=g++-10 CC=gcc-10 ` to use it.
|
||||
|
||||
##### Vulkan SDK
|
||||
|
||||
@@ -64,7 +64,7 @@ For Ubuntu systems, it is strongly recommended to use the PPA from [LunarG](http
|
||||
```
|
||||
. /etc/os-release
|
||||
wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
|
||||
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.2.148-$UBUNTU_CODENAME.list https://packages.lunarg.com/vulkan/1.2.148/lunarg-vulkan-1.2.148-$UBUNTU_CODENAME.list
|
||||
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.2.154-$UBUNTU_CODENAME.list https://packages.lunarg.com/vulkan/1.2.154/lunarg-vulkan-1.2.154-$UBUNTU_CODENAME.list
|
||||
sudo apt update
|
||||
sudo apt install vulkan-sdk
|
||||
```
|
||||
@@ -82,11 +82,11 @@ sudo apt-get install cmake
|
||||
|
||||
#### Fedora
|
||||
|
||||
sudo dnf install alsa-lib-devel cmake glew glew-devel libatomic libevdev-devel libudev-devel openal-devel qt5-devel vulkan-devel
|
||||
sudo dnf install alsa-lib-devel cmake glew glew-devel libatomic libevdev-devel libudev-devel openal-devel qt5-qtbase-devel qt5-qtbase-private-devel vulkan-devel
|
||||
|
||||
#### OpenSUSE
|
||||
|
||||
sudo zypper install git cmake libasound2 libpulse-devel openal-soft-devel glew-devel zlib-devel libedit-devel vulkan-devel libudev-devel libqt5-qtbase-devel libevdev-devel
|
||||
sudo zypper install git cmake libasound2 libpulse-devel openal-soft-devel glew-devel zlib-devel libedit-devel vulkan-devel libudev-devel libqt5-qtbase-devel libqt5gui-private-headers-devel libevdev-devel
|
||||
|
||||
## Setup the project
|
||||
|
||||
@@ -103,16 +103,21 @@ git submodule update --init
|
||||
#### Configuring the Qt plugin (if used)
|
||||
|
||||
1) Go to the Qt5 menu and edit Qt5 options.
|
||||
2) Add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\5.14.2\msvc2017_64`.
|
||||
2) Add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\5.15.2\msvc2019_64`.
|
||||
3) While selecting the rpcs3qt project, go to Qt5->Project Setting and select the version you added.
|
||||
|
||||
#### Building the projects
|
||||
|
||||
Open `rpcs3.sln`. The recommended build configuration is `Release - LLVM` for all purposes.
|
||||
Open `rpcs3.sln`. The recommended build configuration is `Release`. (On older revisions: `Release - LLVM`)
|
||||
|
||||
You may want to download the precompiled [LLVM libs](https://github.com/RPCS3/llvm-mirror/releases/download/custom-build-win/llvmlibs_mt.7z) and extract them to the root rpcs3 folder (which contains `rpcs3.sln`), as well as download and extract the [additional libs](https://github.com/RPCS3/glslang/releases/download/custom-build-win/glslanglibs_mt.7z) to `lib\%CONFIGURATION%-x64\` to speed up compilation time (unoptimised/debug libs are currently not available precompiled).
|
||||
|
||||
If you're not using the precompiled libs, build the projects in *__BUILD_BEFORE* folder: right-click on every project > *Build*.
|
||||
If you're not using the precompiled libs, build the following projects in *__BUILD_BEFORE* folder by right-clicking on a project > *Build*.:
|
||||
* glslang-build
|
||||
* **Either** llvm_build **or** llvm_build_clang_cl
|
||||
* spirv-tools-build
|
||||
|
||||
Afterwards:
|
||||
|
||||
`Build > Build Solution`
|
||||
|
||||
@@ -121,7 +126,7 @@ If you're not using the precompiled libs, build the projects in *__BUILD_BEFORE*
|
||||
While still in the project root:
|
||||
|
||||
1) `cd .. && mkdir rpcs3_build && cd rpcs3_build`
|
||||
2) `cmake ../rpcs3/ && make` or `CXX=g++-9 CC=gcc-9 cmake ../rpcs3/ && make` to force these compilers
|
||||
2) `cmake ../rpcs3/ && make` or `CXX=g++-10 CC=gcc-10 cmake ../rpcs3/ && make` to force these compilers
|
||||
3) Run RPCS3 with `./bin/rpcs3`
|
||||
|
||||
When using GDB, configure it to ignore SIGSEGV signal (`handle SIGSEGV nostop noprint`).
|
||||
|
||||
+29
-36
@@ -1,61 +1,54 @@
|
||||
cmake_minimum_required(VERSION 3.14.1)
|
||||
cmake_minimum_required(VERSION 3.16.9)
|
||||
|
||||
project(rpcs3)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)
|
||||
message(FATAL_ERROR "RPCS3 requires at least gcc-9.")
|
||||
endif()
|
||||
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10)
|
||||
message(FATAL_ERROR "RPCS3 requires at least gcc-10.")
|
||||
endif()
|
||||
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
|
||||
message(FATAL_ERROR "RPCS3 requires at least clang-9.0.")
|
||||
endif()
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
|
||||
message(FATAL_ERROR "RPCS3 requires at least clang-12.0.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(USE_NATIVE_INSTRUCTIONS "USE_NATIVE_INSTRUCTIONS makes rpcs3 compile with -march=native, which is useful for local builds, but not good for packages." ON)
|
||||
option(WITH_LLVM "Enable usage of LLVM library" ON)
|
||||
option(BUILD_LLVM_SUBMODULE "Build LLVM from git submodule" ON)
|
||||
option(USE_ALSA "ALSA audio backend" ON)
|
||||
option(USE_PULSE "PulseAudio audio backend" ON)
|
||||
option(USE_FAUDIO "FAudio audio backend" ON)
|
||||
option(USE_LIBEVDEV "libevdev-based joystick support" ON)
|
||||
option(USE_DISCORD_RPC "Discord rich presence integration" ON)
|
||||
option(USE_SYSTEM_ZLIB "Prefer system ZLIB instead of the builtin one" ON)
|
||||
option(USE_VULKAN "Vulkan render backend" ON)
|
||||
option(USE_PRECOMPILED_HEADERS "Use precompiled headers" ON)
|
||||
# include build options
|
||||
include(options.cmake)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/rpcs3/cmake_modules")
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake_modules")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
message(STATUS "No build type selected, default to Release")
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
message(STATUS "No build type selected, default to Release")
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_definitions(-DNDEBUG)
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
add_definitions(-DNDEBUG)
|
||||
elseif(NOT MSVC)
|
||||
add_definitions(-D_DEBUG)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
message( FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms." )
|
||||
message( FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms." )
|
||||
endif()
|
||||
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if (CCACHE_FOUND)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
if(CCACHE_FOUND)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DUNICODE)
|
||||
add_definitions(-D_WIN32_WINNT=0x0602)
|
||||
add_definitions(-DUNICODE)
|
||||
add_definitions(-D_WIN32_WINNT=0x0602)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
include_directories(/opt/local/include)
|
||||
link_directories(/opt/local/lib)
|
||||
include_directories(/opt/local/include)
|
||||
link_directories(/opt/local/lib)
|
||||
endif()
|
||||
|
||||
# Warnings are silenced for 3rdparty code
|
||||
@@ -64,7 +57,7 @@ set(CMAKE_C_FLAGS -w)
|
||||
set(LLVM_ENABLE_WARNINGS OFF CACHE BOOL "")
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options(/wd4530) # C++ exception handler used, but unwind semantics are not enabled
|
||||
add_compile_options(/wd4530 /utf-8) # C++ exception handler used, but unwind semantics are not enabled
|
||||
endif()
|
||||
|
||||
add_subdirectory(Vulkan EXCLUDE_FROM_ALL)
|
||||
@@ -74,8 +67,8 @@ add_subdirectory(3rdparty)
|
||||
unset(CMAKE_CXX_FLAGS)
|
||||
unset(CMAKE_C_FLAGS)
|
||||
|
||||
if (NOT WIN32)
|
||||
add_compile_options(-pthread)
|
||||
if(NOT WIN32)
|
||||
add_compile_options(-pthread)
|
||||
endif()
|
||||
|
||||
# TODO: do real installation, including copying directory structure
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
RPCS3
|
||||
=====
|
||||
|
||||
[](https://travis-ci.org/RPCS3/rpcs3)
|
||||
[](https://dev.azure.com/nekotekina/nekotekina/_build?definitionId=4&branchName=master)
|
||||
[&logo=cirrus-ci)](https://cirrus-ci.com/github/RPCS3/rpcs3)
|
||||
[](https://discord.me/rpcs3)
|
||||
|
||||
@@ -1,511 +0,0 @@
|
||||
#ifndef BETYPE_H_GUARD
|
||||
#define BETYPE_H_GUARD
|
||||
|
||||
#include "types.h"
|
||||
#include "util/endian.hpp"
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
#if __has_include(<bit>)
|
||||
#include <bit>
|
||||
#else
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
// 128-bit vector type and also se_storage<> storage type
|
||||
union alignas(16) v128
|
||||
{
|
||||
uchar _bytes[16];
|
||||
char _chars[16];
|
||||
|
||||
template <typename T, std::size_t N, std::size_t M>
|
||||
struct masked_array_t // array type accessed as (index ^ M)
|
||||
{
|
||||
char m_data[16];
|
||||
|
||||
public:
|
||||
T& operator[](std::size_t index)
|
||||
{
|
||||
return reinterpret_cast<T*>(m_data)[index ^ M];
|
||||
}
|
||||
|
||||
const T& operator[](std::size_t index) const
|
||||
{
|
||||
return reinterpret_cast<const T*>(m_data)[index ^ M];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, std::size_t N = 16 / sizeof(T)>
|
||||
using normal_array_t = masked_array_t<T, N, std::endian::little == std::endian::native ? 0 : N - 1>;
|
||||
template <typename T, std::size_t N = 16 / sizeof(T)>
|
||||
using reversed_array_t = masked_array_t<T, N, std::endian::little == std::endian::native ? N - 1 : 0>;
|
||||
|
||||
normal_array_t<u64> _u64;
|
||||
normal_array_t<s64> _s64;
|
||||
reversed_array_t<u64> u64r;
|
||||
reversed_array_t<s64> s64r;
|
||||
|
||||
normal_array_t<u32> _u32;
|
||||
normal_array_t<s32> _s32;
|
||||
reversed_array_t<u32> u32r;
|
||||
reversed_array_t<s32> s32r;
|
||||
|
||||
normal_array_t<u16> _u16;
|
||||
normal_array_t<s16> _s16;
|
||||
reversed_array_t<u16> u16r;
|
||||
reversed_array_t<s16> s16r;
|
||||
|
||||
normal_array_t<u8> _u8;
|
||||
normal_array_t<s8> _s8;
|
||||
reversed_array_t<u8> u8r;
|
||||
reversed_array_t<s8> s8r;
|
||||
|
||||
normal_array_t<f32> _f;
|
||||
normal_array_t<f64> _d;
|
||||
reversed_array_t<f32> fr;
|
||||
reversed_array_t<f64> dr;
|
||||
|
||||
__m128 vf;
|
||||
__m128i vi;
|
||||
__m128d vd;
|
||||
|
||||
struct bit_array_128
|
||||
{
|
||||
char m_data[16];
|
||||
|
||||
public:
|
||||
class bit_element
|
||||
{
|
||||
u64& data;
|
||||
const u64 mask;
|
||||
|
||||
public:
|
||||
bit_element(u64& data, const u64 mask)
|
||||
: data(data)
|
||||
, mask(mask)
|
||||
{
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return (data & mask) != 0;
|
||||
}
|
||||
|
||||
bit_element& operator=(const bool right)
|
||||
{
|
||||
if (right)
|
||||
{
|
||||
data |= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
data &= ~mask;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bit_element& operator=(const bit_element& right)
|
||||
{
|
||||
if (right)
|
||||
{
|
||||
data |= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
data &= ~mask;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
// Index 0 returns the MSB and index 127 returns the LSB
|
||||
bit_element operator[](u32 index)
|
||||
{
|
||||
const auto data_ptr = reinterpret_cast<u64*>(m_data);
|
||||
|
||||
if constexpr (std::endian::little == std::endian::native)
|
||||
{
|
||||
return bit_element(data_ptr[1 - (index >> 6)], 0x8000000000000000ull >> (index & 0x3F));
|
||||
}
|
||||
else
|
||||
{
|
||||
return bit_element(data_ptr[index >> 6], 0x8000000000000000ull >> (index & 0x3F));
|
||||
}
|
||||
}
|
||||
|
||||
// Index 0 returns the MSB and index 127 returns the LSB
|
||||
bool operator[](u32 index) const
|
||||
{
|
||||
const auto data_ptr = reinterpret_cast<const u64*>(m_data);
|
||||
|
||||
if constexpr (std::endian::little == std::endian::native)
|
||||
{
|
||||
return (data_ptr[1 - (index >> 6)] & (0x8000000000000000ull >> (index & 0x3F))) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (data_ptr[index >> 6] & (0x8000000000000000ull >> (index & 0x3F))) != 0;
|
||||
}
|
||||
}
|
||||
} _bit;
|
||||
|
||||
static v128 from64(u64 _0, u64 _1 = 0)
|
||||
{
|
||||
v128 ret;
|
||||
ret._u64[0] = _0;
|
||||
ret._u64[1] = _1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static v128 from64r(u64 _1, u64 _0 = 0)
|
||||
{
|
||||
return from64(_0, _1);
|
||||
}
|
||||
|
||||
static v128 from32(u32 _0, u32 _1 = 0, u32 _2 = 0, u32 _3 = 0)
|
||||
{
|
||||
v128 ret;
|
||||
ret._u32[0] = _0;
|
||||
ret._u32[1] = _1;
|
||||
ret._u32[2] = _2;
|
||||
ret._u32[3] = _3;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static v128 from32r(u32 _3, u32 _2 = 0, u32 _1 = 0, u32 _0 = 0)
|
||||
{
|
||||
return from32(_0, _1, _2, _3);
|
||||
}
|
||||
|
||||
static v128 from32p(u32 value)
|
||||
{
|
||||
v128 ret;
|
||||
ret.vi = _mm_set1_epi32(static_cast<s32>(value));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static v128 from16p(u16 value)
|
||||
{
|
||||
v128 ret;
|
||||
ret.vi = _mm_set1_epi16(static_cast<s16>(value));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static v128 from8p(u8 value)
|
||||
{
|
||||
v128 ret;
|
||||
ret.vi = _mm_set1_epi8(static_cast<s8>(value));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static v128 fromBit(u32 bit)
|
||||
{
|
||||
v128 ret = {};
|
||||
ret._bit[bit] = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static v128 fromV(__m128i value)
|
||||
{
|
||||
v128 ret;
|
||||
ret.vi = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static v128 fromF(__m128 value)
|
||||
{
|
||||
v128 ret;
|
||||
ret.vf = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static v128 fromD(__m128d value)
|
||||
{
|
||||
v128 ret;
|
||||
ret.vd = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Unaligned load with optional index offset
|
||||
static v128 loadu(const void* ptr, std::size_t index = 0)
|
||||
{
|
||||
v128 ret;
|
||||
std::memcpy(&ret, static_cast<const u8*>(ptr) + index * sizeof(v128), sizeof(v128));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Unaligned store with optional index offset
|
||||
static void storeu(v128 value, void* ptr, std::size_t index = 0)
|
||||
{
|
||||
std::memcpy(static_cast<u8*>(ptr) + index * sizeof(v128), &value, sizeof(v128));
|
||||
}
|
||||
|
||||
static inline v128 add8(const v128& left, const v128& right)
|
||||
{
|
||||
return fromV(_mm_add_epi8(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static inline v128 add16(const v128& left, const v128& right)
|
||||
{
|
||||
return fromV(_mm_add_epi16(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static inline v128 add32(const v128& left, const v128& right)
|
||||
{
|
||||
return fromV(_mm_add_epi32(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static inline v128 addfs(const v128& left, const v128& right)
|
||||
{
|
||||
return fromF(_mm_add_ps(left.vf, right.vf));
|
||||
}
|
||||
|
||||
static inline v128 addfd(const v128& left, const v128& right)
|
||||
{
|
||||
return fromD(_mm_add_pd(left.vd, right.vd));
|
||||
}
|
||||
|
||||
static inline v128 sub8(const v128& left, const v128& right)
|
||||
{
|
||||
return fromV(_mm_sub_epi8(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static inline v128 sub16(const v128& left, const v128& right)
|
||||
{
|
||||
return fromV(_mm_sub_epi16(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static inline v128 sub32(const v128& left, const v128& right)
|
||||
{
|
||||
return fromV(_mm_sub_epi32(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static inline v128 subfs(const v128& left, const v128& right)
|
||||
{
|
||||
return fromF(_mm_sub_ps(left.vf, right.vf));
|
||||
}
|
||||
|
||||
static inline v128 subfd(const v128& left, const v128& right)
|
||||
{
|
||||
return fromD(_mm_sub_pd(left.vd, right.vd));
|
||||
}
|
||||
|
||||
static inline v128 maxu8(const v128& left, const v128& right)
|
||||
{
|
||||
return fromV(_mm_max_epu8(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static inline v128 minu8(const v128& left, const v128& right)
|
||||
{
|
||||
return fromV(_mm_min_epu8(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static inline v128 eq8(const v128& left, const v128& right)
|
||||
{
|
||||
return fromV(_mm_cmpeq_epi8(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static inline v128 eq16(const v128& left, const v128& right)
|
||||
{
|
||||
return fromV(_mm_cmpeq_epi16(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static inline v128 eq32(const v128& left, const v128& right)
|
||||
{
|
||||
return fromV(_mm_cmpeq_epi32(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static inline v128 eq32f(const v128& left, const v128& right)
|
||||
{
|
||||
return fromF(_mm_cmpeq_ps(left.vf, right.vf));
|
||||
}
|
||||
|
||||
static inline v128 eq64f(const v128& left, const v128& right)
|
||||
{
|
||||
return fromD(_mm_cmpeq_pd(left.vd, right.vd));
|
||||
}
|
||||
|
||||
static inline bool use_fma = false;
|
||||
|
||||
static inline v128 fma32f(v128 a, const v128& b, const v128& c)
|
||||
{
|
||||
#ifndef __FMA__
|
||||
if (use_fma) [[likely]]
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
a.vf = _mm_fmadd_ps(a.vf, b.vf, c.vf);
|
||||
return a;
|
||||
#else
|
||||
__asm__("vfmadd213ps %[c], %[b], %[a]"
|
||||
: [a] "+x" (a.vf)
|
||||
: [b] "x" (b.vf)
|
||||
, [c] "x" (c.vf));
|
||||
return a;
|
||||
#endif
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
a._f[i] = std::fmaf(a._f[i], b._f[i], c._f[i]);
|
||||
}
|
||||
return a;
|
||||
#else
|
||||
a.vf = _mm_fmadd_ps(a.vf, b.vf, c.vf);
|
||||
return a;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool operator==(const v128& right) const
|
||||
{
|
||||
return _mm_movemask_epi8(v128::eq32(*this, right).vi) == 0xffff;
|
||||
}
|
||||
|
||||
bool operator!=(const v128& right) const
|
||||
{
|
||||
return !operator==(right);
|
||||
}
|
||||
|
||||
// result = (~left) & (right)
|
||||
static inline v128 andnot(const v128& left, const v128& right)
|
||||
{
|
||||
return fromV(_mm_andnot_si128(left.vi, right.vi));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
*this = {};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, std::size_t N, std::size_t M>
|
||||
struct offset32_array<v128::masked_array_t<T, N, M>>
|
||||
{
|
||||
template <typename Arg>
|
||||
static inline u32 index32(const Arg& arg)
|
||||
{
|
||||
return u32{sizeof(T)} * (static_cast<u32>(arg) ^ static_cast<u32>(M));
|
||||
}
|
||||
};
|
||||
|
||||
inline v128 operator|(const v128& left, const v128& right)
|
||||
{
|
||||
return v128::fromV(_mm_or_si128(left.vi, right.vi));
|
||||
}
|
||||
|
||||
inline v128 operator&(const v128& left, const v128& right)
|
||||
{
|
||||
return v128::fromV(_mm_and_si128(left.vi, right.vi));
|
||||
}
|
||||
|
||||
inline v128 operator^(const v128& left, const v128& right)
|
||||
{
|
||||
return v128::fromV(_mm_xor_si128(left.vi, right.vi));
|
||||
}
|
||||
|
||||
inline v128 operator~(const v128& other)
|
||||
{
|
||||
return other ^ v128::from32p(UINT32_MAX); // XOR with ones
|
||||
}
|
||||
|
||||
using stx::se_t;
|
||||
using stx::se_storage;
|
||||
|
||||
// se_t<> with native endianness
|
||||
template <typename T, std::size_t Align = alignof(T)>
|
||||
using nse_t = se_t<T, false, Align>;
|
||||
|
||||
template <typename T, std::size_t Align = alignof(T)>
|
||||
using be_t = se_t<T, std::endian::little == std::endian::native, Align>;
|
||||
template <typename T, std::size_t Align = alignof(T)>
|
||||
using le_t = se_t<T, std::endian::big == std::endian::native, Align>;
|
||||
|
||||
// Type converter: converts native endianness arithmetic/enum types to appropriate se_t<> type
|
||||
template <typename T, bool Se, typename = void>
|
||||
struct to_se
|
||||
{
|
||||
template <typename T2, typename = void>
|
||||
struct to_se_
|
||||
{
|
||||
using type = T2;
|
||||
};
|
||||
|
||||
template <typename T2>
|
||||
struct to_se_<T2, std::enable_if_t<std::is_arithmetic<T2>::value || std::is_enum<T2>::value>>
|
||||
{
|
||||
using type = std::conditional_t<(sizeof(T2) > 1), se_t<T2, Se>, T2>;
|
||||
};
|
||||
|
||||
// Convert arithmetic and enum types
|
||||
using type = typename to_se_<T>::type;
|
||||
};
|
||||
|
||||
template <bool Se>
|
||||
struct to_se<v128, Se>
|
||||
{
|
||||
using type = se_t<v128, Se>;
|
||||
};
|
||||
|
||||
template <bool Se>
|
||||
struct to_se<u128, Se>
|
||||
{
|
||||
using type = se_t<u128, Se>;
|
||||
};
|
||||
|
||||
template <bool Se>
|
||||
struct to_se<s128, Se>
|
||||
{
|
||||
using type = se_t<s128, Se>;
|
||||
};
|
||||
|
||||
template <typename T, bool Se>
|
||||
struct to_se<const T, Se, std::enable_if_t<!std::is_array<T>::value>>
|
||||
{
|
||||
// Move const qualifier
|
||||
using type = const typename to_se<T, Se>::type;
|
||||
};
|
||||
|
||||
template <typename T, bool Se>
|
||||
struct to_se<volatile T, Se, std::enable_if_t<!std::is_array<T>::value && !std::is_const<T>::value>>
|
||||
{
|
||||
// Move volatile qualifier
|
||||
using type = volatile typename to_se<T, Se>::type;
|
||||
};
|
||||
|
||||
template <typename T, bool Se>
|
||||
struct to_se<T[], Se>
|
||||
{
|
||||
// Move array qualifier
|
||||
using type = typename to_se<T, Se>::type[];
|
||||
};
|
||||
|
||||
template <typename T, bool Se, std::size_t N>
|
||||
struct to_se<T[N], Se>
|
||||
{
|
||||
// Move array qualifier
|
||||
using type = typename to_se<T, Se>::type[N];
|
||||
};
|
||||
|
||||
// BE/LE aliases for to_se<>
|
||||
template <typename T>
|
||||
using to_be_t = typename to_se<T, std::endian::little == std::endian::native>::type;
|
||||
template <typename T>
|
||||
using to_le_t = typename to_se<T, std::endian::big == std::endian::native>::type;
|
||||
|
||||
// BE/LE aliases for atomic_t
|
||||
template <typename T, std::size_t Align = alignof(T)>
|
||||
using atomic_be_t = atomic_t<be_t<T>, Align>;
|
||||
template <typename T, std::size_t Align = alignof(T)>
|
||||
using atomic_le_t = atomic_t<le_t<T>, Align>;
|
||||
|
||||
template <typename T, bool Se, std::size_t Align>
|
||||
struct fmt_unveil<se_t<T, Se, Align>, void>
|
||||
{
|
||||
using type = typename fmt_unveil<T>::type;
|
||||
|
||||
static inline auto get(const se_t<T, Se, Align>& arg)
|
||||
{
|
||||
return fmt_unveil<T>::get(arg);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BETYPE_H_GUARD
|
||||
+18
-8
@@ -1,12 +1,18 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
#include "Utilities/StrFmt.h"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#endif
|
||||
|
||||
template<typename T, uint N>
|
||||
struct bf_base
|
||||
{
|
||||
using type = T;
|
||||
using vtype = simple_t<type>;
|
||||
using vtype = std::common_type_t<type>;
|
||||
using utype = typename std::make_unsigned<vtype>::type;
|
||||
|
||||
// Datatype bitsize
|
||||
@@ -216,7 +222,7 @@ struct cf_t<void>
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr auto extract(const T& data) -> decltype(+T())
|
||||
static constexpr auto extract(const T&) -> decltype(+T())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -236,7 +242,7 @@ struct ff_t : bf_base<T, N>
|
||||
using vtype = typename ff_t::vtype;
|
||||
|
||||
// Return constant value
|
||||
static constexpr vtype extract(const type& data)
|
||||
static constexpr vtype extract(const type&)
|
||||
{
|
||||
static_assert((V & ff_t::vmask) == V, "ff_t<> error: V out of bounds");
|
||||
return V;
|
||||
@@ -249,10 +255,14 @@ struct ff_t : bf_base<T, N>
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
template<typename T, uint I, uint N>
|
||||
struct fmt_unveil<bf_t<T, I, N>, void>
|
||||
{
|
||||
using type = typename fmt_unveil<simple_t<T>>::type;
|
||||
using type = typename fmt_unveil<std::common_type_t<T>>::type;
|
||||
|
||||
static inline auto get(const bf_t<T, I, N>& bf)
|
||||
{
|
||||
@@ -263,7 +273,7 @@ struct fmt_unveil<bf_t<T, I, N>, void>
|
||||
template<typename F, typename... Fields>
|
||||
struct fmt_unveil<cf_t<F, Fields...>, void>
|
||||
{
|
||||
using type = typename fmt_unveil<simple_t<typename F::type>>::type;
|
||||
using type = typename fmt_unveil<std::common_type_t<typename F::type>>::type;
|
||||
|
||||
static inline auto get(const cf_t<F, Fields...>& cf)
|
||||
{
|
||||
@@ -274,7 +284,7 @@ struct fmt_unveil<cf_t<F, Fields...>, void>
|
||||
template<typename T, T V, uint N>
|
||||
struct fmt_unveil<ff_t<T, V, N>, void>
|
||||
{
|
||||
using type = typename fmt_unveil<simple_t<T>>::type;
|
||||
using type = typename fmt_unveil<std::common_type_t<T>>::type;
|
||||
|
||||
static inline auto get(const ff_t<T, V, N>& ff)
|
||||
{
|
||||
|
||||
+1
-3
@@ -295,7 +295,7 @@ namespace CRCPP
|
||||
static CRCType Finalize(CRCType remainder, CRCType finalXOR, bool reflectOutput);
|
||||
|
||||
template <typename CRCType, crcpp_uint16 CRCWidth>
|
||||
static CRCType UndoFinalize(CRCType remainder, CRCType finalXOR, bool reflectOutput);
|
||||
static CRCType UndoFinalize(CRCType crc, CRCType finalXOR, bool reflectOutput);
|
||||
|
||||
template <typename CRCType, crcpp_uint16 CRCWidth>
|
||||
static CRCType CalculateRemainder(const void * data, crcpp_size size, const Parameters<CRCType, CRCWidth> & parameters, CRCType remainder);
|
||||
@@ -771,8 +771,6 @@ namespace CRCPP
|
||||
in a function even in a branch will never be executed. This also means we don't need pragmas
|
||||
to get rid of warnings, but it still can be computed at compile-time. Win-win!
|
||||
@param[in] x Compile-time expression to bound
|
||||
@tparam CRCType Integer type for storing the CRC result
|
||||
@tparam CRCWidth Number of bits in the CRC
|
||||
@return Non-negative compile-time expression
|
||||
*/
|
||||
template <typename IntegerType>
|
||||
|
||||
+25
-26
@@ -1,14 +1,11 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "Config.h"
|
||||
#include "Utilities/types.h"
|
||||
#include "util/types.hpp"
|
||||
|
||||
#include "util/yaml.hpp"
|
||||
|
||||
#include <typeinfo>
|
||||
#include <charconv>
|
||||
|
||||
[[noreturn]] void report_fatal_error(const std::string&);
|
||||
|
||||
LOG_CHANNEL(cfg_log, "CFG");
|
||||
|
||||
namespace cfg
|
||||
@@ -18,32 +15,34 @@ namespace cfg
|
||||
{
|
||||
if (_type != type::node)
|
||||
{
|
||||
cfg_log.fatal("Invalid root node" HERE);
|
||||
cfg_log.fatal("Invalid root node");
|
||||
}
|
||||
}
|
||||
|
||||
_base::_base(type _type, node* owner, const std::string& name, bool dynamic)
|
||||
: m_type(_type), m_dynamic(dynamic)
|
||||
: m_type(_type), m_dynamic(dynamic), m_name(name)
|
||||
{
|
||||
for (const auto& pair : owner->m_nodes)
|
||||
for (const auto& node : owner->m_nodes)
|
||||
{
|
||||
if (pair.first == name)
|
||||
if (node->get_name() == name)
|
||||
{
|
||||
cfg_log.fatal("Node already exists: %s" HERE, name);
|
||||
cfg_log.fatal("Node already exists: %s", name);
|
||||
}
|
||||
}
|
||||
|
||||
owner->m_nodes.emplace_back(name, this);
|
||||
owner->m_nodes.emplace_back(this);
|
||||
}
|
||||
|
||||
bool _base::from_string(const std::string&, bool)
|
||||
{
|
||||
report_fatal_error("from_string() purecall" HERE);
|
||||
cfg_log.fatal("cfg::_base::from_string() purecall");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool _base::from_list(std::vector<std::string>&&)
|
||||
{
|
||||
report_fatal_error("from_list() purecall" HERE);
|
||||
cfg_log.fatal("cfg::_base::from_list() purecall");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Emit YAML
|
||||
@@ -84,7 +83,7 @@ bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
|
||||
|
||||
if (ret.ec != std::errc() || ret.ptr != end || (start[0] == '-' && sign < 0))
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_int('%s'): invalid integer", value);
|
||||
if (out) cfg_log.error("cfg::try_to_int64('%s'): invalid integer", value);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -92,7 +91,7 @@ bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
|
||||
|
||||
if (result < min || result > max)
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_int('%s'): out of bounds (%d..%d)", value, min, max);
|
||||
if (out) cfg_log.error("cfg::try_to_int64('%s'): out of bounds (%d..%d)", value, min, max);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -123,13 +122,13 @@ bool cfg::try_to_uint64(u64* out, const std::string& value, u64 min, u64 max)
|
||||
|
||||
if (ret.ec != std::errc() || ret.ptr != end)
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_int('%s'): invalid integer", value);
|
||||
if (out) cfg_log.error("cfg::try_to_uint64('%s'): invalid integer", value);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result < min || result > max)
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_int('%s'): out of bounds (%u..%u)", value, min, max);
|
||||
if (out) cfg_log.error("cfg::try_to_uint64('%s'): out of bounds (%u..%u)", value, min, max);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -139,7 +138,7 @@ bool cfg::try_to_uint64(u64* out, const std::string& value, u64 min, u64 max)
|
||||
|
||||
bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, const std::string& value)
|
||||
{
|
||||
u64 max = -1;
|
||||
u64 max = umax;
|
||||
|
||||
for (u64 i = 0;; i++)
|
||||
{
|
||||
@@ -221,11 +220,11 @@ void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
|
||||
case type::node:
|
||||
{
|
||||
out << YAML::BeginMap;
|
||||
for (const auto& np : static_cast<const node&>(rhs).get_nodes())
|
||||
for (const auto& node : static_cast<const node&>(rhs).get_nodes())
|
||||
{
|
||||
out << YAML::Key << np.first;
|
||||
out << YAML::Key << node->get_name();
|
||||
out << YAML::Value;
|
||||
encode(out, *np.second);
|
||||
encode(out, *node);
|
||||
}
|
||||
|
||||
out << YAML::EndMap;
|
||||
@@ -284,11 +283,11 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
|
||||
if (!pair.first.IsScalar()) continue;
|
||||
|
||||
// Find the key among existing nodes
|
||||
for (const auto& _pair : static_cast<node&>(rhs).get_nodes())
|
||||
for (const auto& node : static_cast<node&>(rhs).get_nodes())
|
||||
{
|
||||
if (_pair.first == pair.first.Scalar())
|
||||
if (node->get_name() == pair.first.Scalar())
|
||||
{
|
||||
decode(pair.second, *_pair.second, dynamic);
|
||||
decode(pair.second, *node, dynamic);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -369,7 +368,7 @@ void cfg::node::from_default()
|
||||
{
|
||||
for (auto& node : m_nodes)
|
||||
{
|
||||
node.second->from_default();
|
||||
node->from_default();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,7 +379,7 @@ void cfg::_bool::from_default()
|
||||
|
||||
void cfg::string::from_default()
|
||||
{
|
||||
m_value = m_value.make(def);
|
||||
m_value = def;
|
||||
}
|
||||
|
||||
void cfg::set_entry::from_default()
|
||||
|
||||
+17
-20
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "Utilities/types.h"
|
||||
#include "util/types.hpp"
|
||||
#include "Utilities/StrFmt.h"
|
||||
#include "util/logs.hpp"
|
||||
#include "util/atomic.hpp"
|
||||
#include "util/shared_cptr.hpp"
|
||||
#include "util/shared_ptr.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
@@ -48,10 +48,11 @@ namespace cfg
|
||||
// Config tree entry abstract base class
|
||||
class _base
|
||||
{
|
||||
const type m_type;
|
||||
const type m_type{};
|
||||
|
||||
protected:
|
||||
bool m_dynamic = true;
|
||||
const std::string m_name{};
|
||||
|
||||
// Ownerless entry constructor
|
||||
_base(type _type);
|
||||
@@ -64,11 +65,15 @@ namespace cfg
|
||||
|
||||
_base& operator=(const _base&) = delete;
|
||||
|
||||
virtual ~_base() = default;
|
||||
|
||||
// Get type
|
||||
type get_type() const { return m_type; }
|
||||
|
||||
const std::string& get_name() const { return m_name; }
|
||||
|
||||
// Get dynamic property for reloading configs during games
|
||||
bool get_is_dynamic() const { return m_dynamic; };
|
||||
bool get_is_dynamic() const { return m_dynamic; }
|
||||
|
||||
// Reset defaults
|
||||
virtual void from_default() = 0;
|
||||
@@ -95,7 +100,7 @@ namespace cfg
|
||||
// Config tree node which contains another nodes
|
||||
class node : public _base
|
||||
{
|
||||
std::vector<std::pair<std::string, _base*>> m_nodes;
|
||||
std::vector<_base*> m_nodes{};
|
||||
|
||||
friend class _base;
|
||||
|
||||
@@ -391,17 +396,14 @@ namespace cfg
|
||||
// Simple string entry with mutex
|
||||
class string : public _base
|
||||
{
|
||||
const std::string m_name;
|
||||
|
||||
stx::atomic_cptr<std::string> m_value;
|
||||
atomic_ptr<std::string> m_value;
|
||||
|
||||
public:
|
||||
std::string def;
|
||||
|
||||
string(node* owner, std::string name, std::string def = {}, bool dynamic = false)
|
||||
: _base(type::string, owner, name, dynamic)
|
||||
, m_name(std::move(name))
|
||||
, m_value(m_value.make(def))
|
||||
, m_value(def)
|
||||
, def(std::move(def))
|
||||
{
|
||||
}
|
||||
@@ -411,7 +413,7 @@ namespace cfg
|
||||
return *m_value.load().get();
|
||||
}
|
||||
|
||||
std::pair<const std::string&, stx::shared_cptr<std::string>> get() const
|
||||
std::pair<const std::string&, shared_ptr<std::string>> get() const
|
||||
{
|
||||
auto v = m_value.load();
|
||||
|
||||
@@ -426,11 +428,6 @@ namespace cfg
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& get_name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void from_default() override;
|
||||
|
||||
std::string to_string() const override
|
||||
@@ -440,7 +437,7 @@ namespace cfg
|
||||
|
||||
bool from_string(const std::string& value, bool /*dynamic*/ = false) override
|
||||
{
|
||||
m_value = m_value.make(value);
|
||||
m_value = value;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -448,7 +445,7 @@ namespace cfg
|
||||
// Simple set entry (TODO: template for various types)
|
||||
class set_entry final : public _base
|
||||
{
|
||||
std::set<std::string> m_set;
|
||||
std::set<std::string> m_set{};
|
||||
|
||||
public:
|
||||
// Default value is empty list in current implementation
|
||||
@@ -484,7 +481,7 @@ namespace cfg
|
||||
|
||||
class log_entry final : public _base
|
||||
{
|
||||
std::map<std::string, logs::level> m_map;
|
||||
std::map<std::string, logs::level> m_map{};
|
||||
|
||||
public:
|
||||
log_entry(node* owner, const std::string& name)
|
||||
|
||||
+310
-198
@@ -1,16 +1,15 @@
|
||||
#include "File.h"
|
||||
#include "File.h"
|
||||
#include "mutex.h"
|
||||
#include "StrFmt.h"
|
||||
#include "BEType.h"
|
||||
#include "Crypto/sha1.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
#include <typeinfo>
|
||||
#include <map>
|
||||
|
||||
#include "util/asm.hpp"
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -21,10 +20,10 @@ using namespace std::literals::string_literals;
|
||||
static std::unique_ptr<wchar_t[]> to_wchar(const std::string& source)
|
||||
{
|
||||
// String size + null terminator
|
||||
const std::size_t buf_size = source.size() + 1;
|
||||
const usz buf_size = source.size() + 1;
|
||||
|
||||
// Safe size
|
||||
const int size = narrow<int>(buf_size, "to_wchar" HERE);
|
||||
const int size = narrow<int>(buf_size);
|
||||
|
||||
// Buffer for max possible output length
|
||||
std::unique_ptr<wchar_t[]> buffer(new wchar_t[buf_size + 8 + 32768]);
|
||||
@@ -41,10 +40,10 @@ static std::unique_ptr<wchar_t[]> to_wchar(const std::string& source)
|
||||
std::memcpy(buffer.get() + 32768 + 4, L"UNC\\", 4 * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
verify("to_wchar" HERE), MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get() + 32768 + (unc ? 8 : 4), size);
|
||||
ensure(MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get() + 32768 + (unc ? 8 : 4), size)); // "to_wchar"
|
||||
|
||||
// Canonicalize wide path (replace '/', ".", "..", \\ repetitions, etc)
|
||||
verify("to_wchar" HERE), GetFullPathNameW(buffer.get() + 32768, 32768, buffer.get(), nullptr) - 1 < 32768 - 1;
|
||||
ensure(GetFullPathNameW(buffer.get() + 32768, 32768, buffer.get(), nullptr) - 1 < 32768 - 1); // "to_wchar"
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@@ -52,18 +51,18 @@ static std::unique_ptr<wchar_t[]> to_wchar(const std::string& source)
|
||||
static void to_utf8(std::string& out, const wchar_t* source)
|
||||
{
|
||||
// String size
|
||||
const std::size_t length = std::wcslen(source);
|
||||
const usz length = std::wcslen(source);
|
||||
|
||||
// Safe buffer size for max possible output length (including null terminator)
|
||||
const int buf_size = narrow<int>(length * 3 + 1, "to_utf8" HERE);
|
||||
const int buf_size = narrow<int>(length * 3 + 1);
|
||||
|
||||
// Resize buffer
|
||||
out.resize(buf_size - 1);
|
||||
|
||||
const int result = WideCharToMultiByte(CP_UTF8, 0, source, static_cast<int>(length) + 1, &out.front(), buf_size, NULL, NULL);
|
||||
const int result = WideCharToMultiByte(CP_UTF8, 0, source, static_cast<int>(length) + 1, &out.front(), buf_size, nullptr, nullptr);
|
||||
|
||||
// Fix the size
|
||||
out.resize(verify("to_utf8" HERE, result) - 1);
|
||||
out.resize(ensure(result) - 1);
|
||||
}
|
||||
|
||||
static time_t to_time(const ULARGE_INTEGER& ft)
|
||||
@@ -182,7 +181,7 @@ static std::string path_append(std::string_view path, std::string_view more)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
if (const size_t src_slash_pos = path.find_last_not_of('/'); src_slash_pos != path.npos)
|
||||
if (const usz src_slash_pos = path.find_last_not_of('/'); src_slash_pos != path.npos)
|
||||
{
|
||||
path.remove_suffix(path.length() - src_slash_pos - 1);
|
||||
result = path;
|
||||
@@ -190,7 +189,7 @@ static std::string path_append(std::string_view path, std::string_view more)
|
||||
|
||||
result.push_back('/');
|
||||
|
||||
if (const size_t dst_slash_pos = more.find_first_not_of('/'); dst_slash_pos != more.npos)
|
||||
if (const usz dst_slash_pos = more.find_first_not_of('/'); dst_slash_pos != more.npos)
|
||||
{
|
||||
more.remove_prefix(dst_slash_pos);
|
||||
result.append(more);
|
||||
@@ -205,13 +204,13 @@ namespace fs
|
||||
|
||||
class device_manager final
|
||||
{
|
||||
mutable shared_mutex m_mutex;
|
||||
mutable shared_mutex m_mutex{};
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<device_base>> m_map;
|
||||
std::unordered_map<std::string, shared_ptr<device_base>> m_map{};
|
||||
|
||||
public:
|
||||
std::shared_ptr<device_base> get_device(const std::string& path);
|
||||
std::shared_ptr<device_base> set_device(const std::string& name, const std::shared_ptr<device_base>&);
|
||||
shared_ptr<device_base> get_device(const std::string& path);
|
||||
shared_ptr<device_base> set_device(const std::string& name, shared_ptr<device_base>);
|
||||
};
|
||||
|
||||
static device_manager& get_device_manager()
|
||||
@@ -225,9 +224,9 @@ namespace fs
|
||||
{
|
||||
}
|
||||
|
||||
stat_t file_base::stat()
|
||||
[[noreturn]] stat_t file_base::stat()
|
||||
{
|
||||
fmt::throw_exception("fs::file::stat() not supported for %s", typeid(*this).name());
|
||||
fmt::throw_exception("fs::file::stat() not supported.");
|
||||
}
|
||||
|
||||
void file_base::sync()
|
||||
@@ -276,58 +275,163 @@ namespace fs
|
||||
{
|
||||
}
|
||||
|
||||
device_base::device_base()
|
||||
: fs_prefix(fmt::format("/vfsv0_%s%s_", fmt::base57(reinterpret_cast<u64>(this)), fmt::base57(utils::get_unique_tsc())))
|
||||
{
|
||||
}
|
||||
|
||||
device_base::~device_base()
|
||||
{
|
||||
}
|
||||
|
||||
bool device_base::remove_dir(const std::string&)
|
||||
{
|
||||
g_tls_error = error::readonly;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool device_base::create_dir(const std::string&)
|
||||
{
|
||||
g_tls_error = error::readonly;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool device_base::rename(const std::string&, const std::string&)
|
||||
{
|
||||
g_tls_error = error::readonly;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool device_base::remove(const std::string&)
|
||||
{
|
||||
g_tls_error = error::readonly;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool device_base::trunc(const std::string&, u64)
|
||||
{
|
||||
g_tls_error = error::readonly;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool device_base::utime(const std::string&, s64, s64)
|
||||
{
|
||||
g_tls_error = error::readonly;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<fs::device_base> fs::device_manager::get_device(const std::string& path)
|
||||
shared_ptr<fs::device_base> fs::device_manager::get_device(const std::string& path)
|
||||
{
|
||||
reader_lock lock(m_mutex);
|
||||
|
||||
const auto found = m_map.find(path.substr(0, path.find_first_of('/', 2)));
|
||||
const usz prefix = path.find_first_of('_', 7) + 1;
|
||||
|
||||
if (found == m_map.end())
|
||||
const auto found = m_map.find(path.substr(prefix, path.find_first_of('/', 1) - prefix));
|
||||
|
||||
if (found == m_map.end() || !path.starts_with(found->second->fs_prefix))
|
||||
{
|
||||
return nullptr;
|
||||
return null_ptr;
|
||||
}
|
||||
|
||||
return found->second;
|
||||
}
|
||||
|
||||
std::shared_ptr<fs::device_base> fs::device_manager::set_device(const std::string& name, const std::shared_ptr<device_base>& device)
|
||||
shared_ptr<fs::device_base> fs::device_manager::set_device(const std::string& name, shared_ptr<device_base> device)
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
return m_map[name] = device;
|
||||
if (device)
|
||||
{
|
||||
// Adding
|
||||
if (auto [it, ok] = m_map.try_emplace(name, std::move(device)); ok)
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
g_tls_error = error::exist;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Removing
|
||||
if (auto found = m_map.find(name); found != m_map.end())
|
||||
{
|
||||
device = std::move(found->second);
|
||||
m_map.erase(found);
|
||||
return device;
|
||||
}
|
||||
|
||||
g_tls_error = error::noent;
|
||||
}
|
||||
|
||||
return null_ptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<fs::device_base> fs::get_virtual_device(const std::string& path)
|
||||
shared_ptr<fs::device_base> fs::get_virtual_device(const std::string& path)
|
||||
{
|
||||
// Every virtual device path must have "//" at the beginning
|
||||
if (path.starts_with("//"))
|
||||
// Every virtual device path must have specific name at the beginning
|
||||
if (path.starts_with("/vfsv0_") && path.size() >= 8 + 22 && path[29] == '_' && path.find_first_of('/', 1) > 29)
|
||||
{
|
||||
return get_device_manager().get_device(path);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return null_ptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<fs::device_base> fs::set_virtual_device(const std::string& name, const std::shared_ptr<device_base>& device)
|
||||
shared_ptr<fs::device_base> fs::set_virtual_device(const std::string& name, shared_ptr<device_base> device)
|
||||
{
|
||||
verify(HERE), name.starts_with("//"), name[2] != '/';
|
||||
|
||||
return get_device_manager().set_device(name, device);
|
||||
return get_device_manager().set_device(name, std::move(device));
|
||||
}
|
||||
|
||||
std::string fs::get_parent_dir(const std::string& path)
|
||||
{
|
||||
// Get (basically) processed path
|
||||
const auto real_path = fs::escape_path(path);
|
||||
std::string_view result = path;
|
||||
|
||||
const auto pos = real_path.find_last_of(delim);
|
||||
// Number of path components to remove
|
||||
usz to_remove = 1;
|
||||
|
||||
return real_path.substr(0, pos == umax ? 0 : pos);
|
||||
while (to_remove--)
|
||||
{
|
||||
// Trim contiguous delimiters at the end
|
||||
if (usz sz = result.find_last_not_of(delim) + 1)
|
||||
{
|
||||
result = result.substr(0, sz);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "/";
|
||||
}
|
||||
|
||||
const auto elem = result.substr(result.find_last_of(delim) + 1);
|
||||
|
||||
if (elem.empty() || elem.size() == result.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (elem == ".")
|
||||
{
|
||||
to_remove += 1;
|
||||
}
|
||||
|
||||
if (elem == "..")
|
||||
{
|
||||
to_remove += 2;
|
||||
}
|
||||
|
||||
result.remove_suffix(elem.size());
|
||||
}
|
||||
|
||||
if (usz sz = result.find_last_not_of(delim) + 1)
|
||||
{
|
||||
result = result.substr(0, sz);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "/";
|
||||
}
|
||||
|
||||
return std::string{result};
|
||||
}
|
||||
|
||||
bool fs::stat(const std::string& path, stat_t& info)
|
||||
@@ -355,7 +459,7 @@ bool fs::stat(const std::string& path, stat_t& info)
|
||||
if (!GetFileAttributesExW(to_wchar(std::string(epath) + '/').get(), GetFileExInfoStandard, &attrs))
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
info.is_directory = true; // Handle drives as directories
|
||||
@@ -404,7 +508,7 @@ bool fs::stat(const std::string& path, stat_t& info)
|
||||
if (const DWORD err = GetLastError(); err != ERROR_NO_MORE_FILES)
|
||||
{
|
||||
g_tls_error = to_error(err);
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
g_tls_error = fs::error::noent;
|
||||
@@ -506,7 +610,7 @@ bool fs::statfs(const std::string& path, fs::device_stat& info)
|
||||
// Keep cutting path from right until it's short enough
|
||||
while (str.size() > 256)
|
||||
{
|
||||
if (std::size_t x = str.find_last_of('\\') + 1)
|
||||
if (usz x = str.find_last_of('\\') + 1)
|
||||
str.resize(x - 1);
|
||||
else
|
||||
break;
|
||||
@@ -547,9 +651,17 @@ bool fs::create_dir(const std::string& path)
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!CreateDirectoryW(to_wchar(path).get(), NULL))
|
||||
if (!CreateDirectoryW(to_wchar(path).get(), nullptr))
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
int res = GetLastError();
|
||||
|
||||
if (res == ERROR_ACCESS_DENIED && is_dir(path))
|
||||
{
|
||||
// May happen on drives
|
||||
res = ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
g_tls_error = to_error(res);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -659,7 +771,7 @@ bool fs::rename(const std::string& from, const std::string& to, bool overwrite)
|
||||
}
|
||||
|
||||
error1 = GetLastError();
|
||||
CreateDirectoryW(ws2.get(), NULL); // TODO
|
||||
CreateDirectoryW(ws2.get(), nullptr); // TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -828,7 +940,7 @@ bool fs::truncate_file(const std::string& path, u64 length)
|
||||
|
||||
#ifdef _WIN32
|
||||
// Open the file
|
||||
const auto handle = CreateFileW(to_wchar(path).get(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
const auto handle = CreateFileW(to_wchar(path).get(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
@@ -867,7 +979,7 @@ bool fs::utime(const std::string& path, s64 atime, s64 mtime)
|
||||
|
||||
#ifdef _WIN32
|
||||
// Open the file
|
||||
const auto handle = CreateFileW(to_wchar(path).get(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
const auto handle = CreateFileW(to_wchar(path).get(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
g_tls_error = to_error(GetLastError());
|
||||
@@ -900,14 +1012,29 @@ bool fs::utime(const std::string& path, s64 atime, s64 mtime)
|
||||
#endif
|
||||
}
|
||||
|
||||
void fs::file::xnull() const
|
||||
void fs::sync()
|
||||
{
|
||||
fmt::throw_exception("fs::file is null");
|
||||
#ifdef _WIN32
|
||||
fs::g_tls_error = fs::error::unknown;
|
||||
#else
|
||||
::sync();
|
||||
fs::g_tls_error = fs::error::ok;
|
||||
#endif
|
||||
}
|
||||
|
||||
void fs::file::xfail() const
|
||||
[[noreturn]] void fs::xnull(const src_loc& loc)
|
||||
{
|
||||
fmt::throw_exception("Unexpected fs::error %s", g_tls_error);
|
||||
fmt::throw_exception("Null object.%s", loc);
|
||||
}
|
||||
|
||||
[[noreturn]] void fs::xfail(const src_loc& loc)
|
||||
{
|
||||
fmt::throw_exception("Unexpected fs::error %s%s", g_tls_error, loc);
|
||||
}
|
||||
|
||||
[[noreturn]] void fs::xovfl()
|
||||
{
|
||||
fmt::throw_exception("Stream overflow.");
|
||||
}
|
||||
|
||||
fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
@@ -964,7 +1091,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
share |= FILE_SHARE_WRITE;
|
||||
}
|
||||
|
||||
const HANDLE handle = CreateFileW(to_wchar(path).get(), access, share, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
const HANDLE handle = CreateFileW(to_wchar(path).get(), access, share, nullptr, disp, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
@@ -990,7 +1117,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
stat_t stat() override
|
||||
{
|
||||
FILE_BASIC_INFO basic_info;
|
||||
verify("file::stat" HERE), GetFileInformationByHandleEx(m_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO));
|
||||
ensure(GetFileInformationByHandleEx(m_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO))); // "file::stat"
|
||||
|
||||
stat_t info;
|
||||
info.is_directory = (basic_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
@@ -1008,7 +1135,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
|
||||
void sync() override
|
||||
{
|
||||
verify("file::sync" HERE), FlushFileBuffers(m_handle);
|
||||
ensure(FlushFileBuffers(m_handle)); // "file::sync"
|
||||
}
|
||||
|
||||
bool trunc(u64 length) override
|
||||
@@ -1028,10 +1155,10 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
u64 read(void* buffer, u64 count) override
|
||||
{
|
||||
// TODO (call ReadFile multiple times if count is too big)
|
||||
const int size = narrow<int>(count, "file::read" HERE);
|
||||
const int size = narrow<int>(count);
|
||||
|
||||
DWORD nread;
|
||||
verify("file::read" HERE), ReadFile(m_handle, buffer, size, &nread, NULL);
|
||||
ensure(ReadFile(m_handle, buffer, size, &nread, nullptr)); // "file::read"
|
||||
|
||||
return nread;
|
||||
}
|
||||
@@ -1039,24 +1166,27 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
u64 write(const void* buffer, u64 count) override
|
||||
{
|
||||
// TODO (call WriteFile multiple times if count is too big)
|
||||
const int size = narrow<int>(count, "file::write" HERE);
|
||||
const int size = narrow<int>(count);
|
||||
|
||||
DWORD nwritten;
|
||||
verify("file::write" HERE), WriteFile(m_handle, buffer, size, &nwritten, NULL);
|
||||
ensure(WriteFile(m_handle, buffer, size, &nwritten, nullptr)); // "file::write"
|
||||
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
u64 seek(s64 offset, seek_mode whence) override
|
||||
{
|
||||
if (whence > seek_end)
|
||||
{
|
||||
fmt::throw_exception("Invalid whence (0x%x)", whence);
|
||||
}
|
||||
|
||||
LARGE_INTEGER pos;
|
||||
pos.QuadPart = offset;
|
||||
|
||||
const DWORD mode =
|
||||
whence == seek_set ? FILE_BEGIN :
|
||||
whence == seek_cur ? FILE_CURRENT :
|
||||
whence == seek_end ? FILE_END :
|
||||
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
|
||||
whence == seek_cur ? FILE_CURRENT : FILE_END;
|
||||
|
||||
if (!SetFilePointerEx(m_handle, pos, &pos, mode))
|
||||
{
|
||||
@@ -1070,7 +1200,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
u64 size() override
|
||||
{
|
||||
LARGE_INTEGER size;
|
||||
verify("file::size" HERE), GetFileSizeEx(m_handle, &size);
|
||||
ensure(GetFileSizeEx(m_handle, &size)); // "file::size"
|
||||
|
||||
return size.QuadPart;
|
||||
}
|
||||
@@ -1091,13 +1221,22 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
|
||||
if (mode & fs::append) flags |= O_APPEND;
|
||||
if (mode & fs::create) flags |= O_CREAT;
|
||||
if (mode & fs::trunc && !(mode & (fs::lock + fs::unread))) flags |= O_TRUNC;
|
||||
if (mode & fs::trunc && !(mode & fs::lock)) flags |= O_TRUNC;
|
||||
if (mode & fs::excl) flags |= O_EXCL;
|
||||
|
||||
int perm = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
|
||||
if (mode & fs::write && mode & fs::unread)
|
||||
{
|
||||
if (!(mode & (fs::excl + fs::lock)) && mode & fs::trunc)
|
||||
{
|
||||
// Alternative to truncation for "unread" flag (TODO)
|
||||
if (mode & fs::create)
|
||||
{
|
||||
::unlink(path.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
perm = 0;
|
||||
}
|
||||
|
||||
@@ -1109,17 +1248,17 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode & fs::write && mode & (fs::lock + fs::unread) && ::flock(fd, LOCK_EX | LOCK_NB) != 0)
|
||||
if (mode & fs::write && mode & fs::lock && ::flock(fd, LOCK_EX | LOCK_NB) != 0)
|
||||
{
|
||||
g_tls_error = errno == EWOULDBLOCK ? fs::error::acces : to_error(errno);
|
||||
::close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode & fs::trunc && mode & (fs::lock + fs::unread) && mode & fs::write)
|
||||
if (mode & fs::trunc && mode & fs::lock && mode & fs::write)
|
||||
{
|
||||
// Postpone truncation in order to avoid using O_TRUNC on a locked file
|
||||
verify(HERE), ::ftruncate(fd, 0) == 0;
|
||||
ensure(::ftruncate(fd, 0) == 0);
|
||||
}
|
||||
|
||||
class unix_file final : public file_base
|
||||
@@ -1140,7 +1279,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
stat_t stat() override
|
||||
{
|
||||
struct ::stat file_info;
|
||||
verify("file::stat" HERE), ::fstat(m_fd, &file_info) == 0;
|
||||
ensure(::fstat(m_fd, &file_info) == 0); // "file::stat"
|
||||
|
||||
stat_t info;
|
||||
info.is_directory = S_ISDIR(file_info.st_mode);
|
||||
@@ -1158,7 +1297,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
|
||||
void sync() override
|
||||
{
|
||||
verify("file::sync" HERE), ::fsync(m_fd) == 0;
|
||||
ensure(::fsync(m_fd) == 0); // "file::sync"
|
||||
}
|
||||
|
||||
bool trunc(u64 length) override
|
||||
@@ -1175,7 +1314,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
u64 read(void* buffer, u64 count) override
|
||||
{
|
||||
const auto result = ::read(m_fd, buffer, count);
|
||||
verify("file::read" HERE), result != -1;
|
||||
ensure(result != -1); // "file::read"
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1183,18 +1322,21 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
u64 write(const void* buffer, u64 count) override
|
||||
{
|
||||
const auto result = ::write(m_fd, buffer, count);
|
||||
verify("file::write" HERE), result != -1;
|
||||
ensure(result != -1); // "file::write"
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
u64 seek(s64 offset, seek_mode whence) override
|
||||
{
|
||||
if (whence > seek_end)
|
||||
{
|
||||
fmt::throw_exception("Invalid whence (0x%x)", whence);
|
||||
}
|
||||
|
||||
const int mode =
|
||||
whence == seek_set ? SEEK_SET :
|
||||
whence == seek_cur ? SEEK_CUR :
|
||||
whence == seek_end ? SEEK_END :
|
||||
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
|
||||
whence == seek_cur ? SEEK_CUR : SEEK_END;
|
||||
|
||||
const auto result = ::lseek(m_fd, offset, mode);
|
||||
|
||||
@@ -1210,7 +1352,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
u64 size() override
|
||||
{
|
||||
struct ::stat file_info;
|
||||
verify("file::size" HERE), ::fstat(m_fd, &file_info) == 0;
|
||||
ensure(::fstat(m_fd, &file_info) == 0); // "file::size"
|
||||
|
||||
return file_info.st_size;
|
||||
}
|
||||
@@ -1225,8 +1367,19 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
static_assert(sizeof(iovec) == sizeof(iovec_clone), "Weird iovec size");
|
||||
static_assert(offsetof(iovec, iov_len) == offsetof(iovec_clone, iov_len), "Weird iovec::iov_len offset");
|
||||
|
||||
const auto result = ::writev(m_fd, reinterpret_cast<const iovec*>(buffers), buf_count);
|
||||
verify("file::write_gather" HERE), result != -1;
|
||||
u64 result = 0;
|
||||
|
||||
while (buf_count)
|
||||
{
|
||||
iovec arg[256];
|
||||
const auto count = std::min<u64>(buf_count, 256);
|
||||
std::memcpy(&arg, buffers, sizeof(iovec) * count);
|
||||
const auto added = ::writev(m_fd, arg, count);
|
||||
ensure(added != -1); // "file::write_gather"
|
||||
result += added;
|
||||
buf_count -= count;
|
||||
buffers += count;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1236,7 +1389,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
||||
#endif
|
||||
}
|
||||
|
||||
fs::file::file(const void* ptr, std::size_t size)
|
||||
fs::file::file(const void* ptr, usz size)
|
||||
{
|
||||
class memory_stream : public file_base
|
||||
{
|
||||
@@ -1252,7 +1405,11 @@ fs::file::file(const void* ptr, std::size_t size)
|
||||
{
|
||||
}
|
||||
|
||||
bool trunc(u64 length) override
|
||||
memory_stream(const memory_stream&) = delete;
|
||||
|
||||
memory_stream& operator=(const memory_stream&) = delete;
|
||||
|
||||
bool trunc(u64) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1273,7 +1430,7 @@ fs::file::file(const void* ptr, std::size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 write(const void* buffer, u64 count) override
|
||||
u64 write(const void*, u64) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -1318,11 +1475,6 @@ fs::native_handle fs::file::get_handle() const
|
||||
#endif
|
||||
}
|
||||
|
||||
void fs::dir::xnull() const
|
||||
{
|
||||
fmt::throw_exception("fs::dir is null");
|
||||
}
|
||||
|
||||
bool fs::dir::open(const std::string& path)
|
||||
{
|
||||
if (path.empty())
|
||||
@@ -1345,7 +1497,7 @@ bool fs::dir::open(const std::string& path)
|
||||
|
||||
#ifdef _WIN32
|
||||
WIN32_FIND_DATAW found;
|
||||
const auto handle = FindFirstFileExW(to_wchar(path + "/*").get(), FindExInfoBasic, &found, FindExSearchNameMatch, NULL, FIND_FIRST_EX_CASE_SENSITIVE | FIND_FIRST_EX_LARGE_FETCH);
|
||||
const auto handle = FindFirstFileExW(to_wchar(path + "/*").get(), FindExInfoBasic, &found, FindExSearchNameMatch, nullptr, FIND_FIRST_EX_CASE_SENSITIVE | FIND_FIRST_EX_LARGE_FETCH);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
@@ -1356,7 +1508,7 @@ bool fs::dir::open(const std::string& path)
|
||||
class windows_dir final : public dir_base
|
||||
{
|
||||
std::vector<dir_entry> m_entries;
|
||||
std::size_t m_pos = 0;
|
||||
usz m_pos = 0;
|
||||
|
||||
void add_entry(const WIN32_FIND_DATAW& found)
|
||||
{
|
||||
@@ -1386,7 +1538,7 @@ bool fs::dir::open(const std::string& path)
|
||||
add_entry(found);
|
||||
}
|
||||
|
||||
verify("dir::read" HERE), ERROR_NO_MORE_FILES == GetLastError();
|
||||
ensure(ERROR_NO_MORE_FILES == GetLastError()); // "dir::read"
|
||||
FindClose(handle);
|
||||
}
|
||||
|
||||
@@ -1427,6 +1579,10 @@ bool fs::dir::open(const std::string& path)
|
||||
{
|
||||
}
|
||||
|
||||
unix_dir(const unix_dir&) = delete;
|
||||
|
||||
unix_dir& operator=(const unix_dir&) = delete;
|
||||
|
||||
~unix_dir() override
|
||||
{
|
||||
::closedir(m_dd);
|
||||
@@ -1474,6 +1630,17 @@ bool fs::dir::open(const std::string& path)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fs::file::strict_read_check(u64 _size, u64 type_size) const
|
||||
{
|
||||
if (usz pos0 = pos(), size0 = size(); pos0 >= size0 || (size0 - pos0) / type_size < _size)
|
||||
{
|
||||
fs::g_tls_error = fs::error::inval;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string& fs::get_config_dir()
|
||||
{
|
||||
// Use magic static
|
||||
@@ -1485,9 +1652,9 @@ const std::string& fs::get_config_dir()
|
||||
wchar_t buf[32768];
|
||||
constexpr DWORD size = static_cast<DWORD>(std::size(buf));
|
||||
if (GetEnvironmentVariable(L"RPCS3_CONFIG_DIR", buf, size) - 1 >= size - 1 &&
|
||||
GetModuleFileName(NULL, buf, size) - 1 >= size - 1)
|
||||
GetModuleFileName(nullptr, buf, size) - 1 >= size - 1)
|
||||
{
|
||||
MessageBoxA(0, fmt::format("GetModuleFileName() failed: error %u.", GetLastError()).c_str(), "fs::get_config_dir()", MB_ICONERROR);
|
||||
MessageBoxA(nullptr, fmt::format("GetModuleFileName() failed: error %u.", GetLastError()).c_str(), "fs::get_config_dir()", MB_ICONERROR);
|
||||
return dir; // empty
|
||||
}
|
||||
|
||||
@@ -1602,110 +1769,6 @@ bool fs::remove_all(const std::string& path, bool remove_root)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string fs::escape_path(std::string_view path)
|
||||
{
|
||||
std::string real; real.resize(path.size());
|
||||
|
||||
auto get_char = [&](std::size_t& from, std::size_t& to, std::size_t count)
|
||||
{
|
||||
std::memcpy(&real[to], &path[from], count);
|
||||
from += count, to += count;
|
||||
};
|
||||
|
||||
std::size_t i = 0, j = -1, pos_nondelim = 0, after_delim = 0;
|
||||
|
||||
if (i < path.size())
|
||||
{
|
||||
j = 0;
|
||||
}
|
||||
|
||||
for (; i < path.size();)
|
||||
{
|
||||
real[j] = path[i];
|
||||
#ifdef _Win32
|
||||
if (real[j] == '\\')
|
||||
{
|
||||
real[j] = '/';
|
||||
}
|
||||
#endif
|
||||
// If the current character was preceeded by a delimiter special treatment is required:
|
||||
// If another deleimiter is encountered, remove it (do not write it to output string)
|
||||
// Otherwise test if it is a "." or ".." sequence.
|
||||
if (std::exchange(after_delim, path[i] == delim[0] || path[i] == delim[1]))
|
||||
{
|
||||
if (!after_delim)
|
||||
{
|
||||
if (real[j] == '.')
|
||||
{
|
||||
if (i + 1 == path.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
get_char(i, j, 1);
|
||||
|
||||
switch (real[j])
|
||||
{
|
||||
case '.':
|
||||
{
|
||||
bool remove_element = true;
|
||||
std::size_t k = 1;
|
||||
|
||||
for (; k + i != path.size(); k++)
|
||||
{
|
||||
switch (path[i + k])
|
||||
{
|
||||
case '.': continue;
|
||||
case delim[0]: case delim[1]: break;
|
||||
default: remove_element = false; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (remove_element)
|
||||
{
|
||||
if (i == 1u)
|
||||
{
|
||||
j = pos_nondelim;
|
||||
real[j] = '\0';// Ensure termination at this posistion
|
||||
after_delim = true;
|
||||
i += k;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
get_char(i, j, k);
|
||||
continue;
|
||||
}
|
||||
case '/':
|
||||
{
|
||||
i++;
|
||||
after_delim = true;
|
||||
continue;
|
||||
}
|
||||
default: get_char(i, j, 1); continue;
|
||||
}
|
||||
}
|
||||
|
||||
pos_nondelim = j;
|
||||
get_char(i, j, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
get_char(i, j, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (j != umax && (real[j] == delim[0] || real[j] == delim[1])) j--; // Do not include a delmiter at the end
|
||||
|
||||
real.resize(j + 1);
|
||||
return real;
|
||||
}
|
||||
|
||||
u64 fs::get_dir_size(const std::string& path, u64 rounding_alignment)
|
||||
{
|
||||
u64 result = 0;
|
||||
@@ -1714,7 +1777,7 @@ u64 fs::get_dir_size(const std::string& path, u64 rounding_alignment)
|
||||
|
||||
if (!root_dir)
|
||||
{
|
||||
return static_cast<u64>(umax);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (const auto& entry : root_dir)
|
||||
@@ -1726,7 +1789,7 @@ u64 fs::get_dir_size(const std::string& path, u64 rounding_alignment)
|
||||
|
||||
if (!entry.is_directory)
|
||||
{
|
||||
result += ::align(entry.size, rounding_alignment);
|
||||
result += utils::align(entry.size, rounding_alignment);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1750,8 +1813,8 @@ fs::file fs::make_gather(std::vector<fs::file> files)
|
||||
{
|
||||
u64 pos = 0;
|
||||
u64 end = 0;
|
||||
std::vector<file> files;
|
||||
std::map<u64, u64> ends; // Fragment End Offset -> Index
|
||||
std::vector<file> files{};
|
||||
std::map<u64, u64> ends{}; // Fragment End Offset -> Index
|
||||
|
||||
gather_stream(std::vector<fs::file> arg)
|
||||
: files(std::move(arg))
|
||||
@@ -1783,7 +1846,7 @@ fs::file fs::make_gather(std::vector<fs::file> files)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool trunc(u64 length) override
|
||||
bool trunc(u64) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1826,7 +1889,7 @@ fs::file fs::make_gather(std::vector<fs::file> files)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 write(const void* buffer, u64 size) override
|
||||
u64 write(const void*, u64) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -1859,6 +1922,55 @@ fs::file fs::make_gather(std::vector<fs::file> files)
|
||||
return result;
|
||||
}
|
||||
|
||||
fs::pending_file::pending_file(const std::string& path)
|
||||
{
|
||||
do
|
||||
{
|
||||
m_path = fmt::format(u8"%s/$%s.%s.tmp", get_parent_dir(path), std::string_view(path).substr(path.find_last_of(fs::delim) + 1), fmt::base57(utils::get_unique_tsc()));
|
||||
|
||||
if (file.open(m_path, fs::create + fs::write + fs::read + fs::excl))
|
||||
{
|
||||
m_dest = path;
|
||||
break;
|
||||
}
|
||||
|
||||
m_path.clear();
|
||||
}
|
||||
while (fs::g_tls_error == fs::error::exist); // Only retry if failed due to existing file
|
||||
}
|
||||
|
||||
fs::pending_file::~pending_file()
|
||||
{
|
||||
file.close();
|
||||
|
||||
if (!m_path.empty())
|
||||
{
|
||||
fs::remove_file(m_path);
|
||||
}
|
||||
}
|
||||
|
||||
bool fs::pending_file::commit(bool overwrite)
|
||||
{
|
||||
if (!file || m_path.empty())
|
||||
{
|
||||
fs::g_tls_error = fs::error::noent;
|
||||
return false;
|
||||
}
|
||||
|
||||
// The temporary file's contents must be on disk before rename
|
||||
file.sync();
|
||||
file.close();
|
||||
|
||||
if (fs::rename(m_path, m_dest, overwrite))
|
||||
{
|
||||
// Disable the destructor
|
||||
m_path.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
void fmt_class_string<fs::seek_mode>::format(std::string& out, u64 arg)
|
||||
{
|
||||
|
||||
+246
-81
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#pragma once // No BOM and only basic ASCII in this header, or a neko will die
|
||||
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
#include "util/shared_ptr.hpp"
|
||||
#include "bit_set.h"
|
||||
|
||||
#include <memory>
|
||||
@@ -73,7 +74,7 @@ namespace fs
|
||||
struct iovec_clone
|
||||
{
|
||||
const void* iov_base;
|
||||
std::size_t iov_len;
|
||||
usz iov_len;
|
||||
};
|
||||
|
||||
// File handle base
|
||||
@@ -81,7 +82,7 @@ namespace fs
|
||||
{
|
||||
virtual ~file_base();
|
||||
|
||||
virtual stat_t stat();
|
||||
[[noreturn]] virtual stat_t stat();
|
||||
virtual void sync();
|
||||
virtual bool trunc(u64 length) = 0;
|
||||
virtual u64 read(void* buffer, u64 size) = 0;
|
||||
@@ -95,7 +96,12 @@ namespace fs
|
||||
// Directory entry (TODO)
|
||||
struct dir_entry : stat_t
|
||||
{
|
||||
std::string name;
|
||||
std::string name{};
|
||||
|
||||
dir_entry()
|
||||
: stat_t{}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Directory handle base
|
||||
@@ -119,26 +125,35 @@ namespace fs
|
||||
// Virtual device
|
||||
struct device_base
|
||||
{
|
||||
const std::string fs_prefix;
|
||||
|
||||
device_base();
|
||||
virtual ~device_base();
|
||||
|
||||
virtual bool stat(const std::string& path, stat_t& info) = 0;
|
||||
virtual bool statfs(const std::string& path, device_stat& info) = 0;
|
||||
virtual bool remove_dir(const std::string& path) = 0;
|
||||
virtual bool create_dir(const std::string& path) = 0;
|
||||
virtual bool rename(const std::string& from, const std::string& to) = 0;
|
||||
virtual bool remove(const std::string& path) = 0;
|
||||
virtual bool trunc(const std::string& path, u64 length) = 0;
|
||||
virtual bool utime(const std::string& path, s64 atime, s64 mtime) = 0;
|
||||
virtual bool remove_dir(const std::string& path);
|
||||
virtual bool create_dir(const std::string& path);
|
||||
virtual bool rename(const std::string& from, const std::string& to);
|
||||
virtual bool remove(const std::string& path);
|
||||
virtual bool trunc(const std::string& path, u64 length);
|
||||
virtual bool utime(const std::string& path, s64 atime, s64 mtime);
|
||||
|
||||
virtual std::unique_ptr<file_base> open(const std::string& path, bs_t<open_mode> mode) = 0;
|
||||
virtual std::unique_ptr<dir_base> open_dir(const std::string& path) = 0;
|
||||
};
|
||||
|
||||
[[noreturn]] void xnull(const src_loc&);
|
||||
[[noreturn]] void xfail(const src_loc&);
|
||||
[[noreturn]] void xovfl();
|
||||
|
||||
constexpr struct pod_tag_t{} pod_tag;
|
||||
|
||||
// Get virtual device for specified path (nullptr for real path)
|
||||
std::shared_ptr<device_base> get_virtual_device(const std::string& path);
|
||||
shared_ptr<device_base> get_virtual_device(const std::string& path);
|
||||
|
||||
// Set virtual device with specified name (nullptr for deletion)
|
||||
std::shared_ptr<device_base> set_virtual_device(const std::string& root_name, const std::shared_ptr<device_base>&);
|
||||
shared_ptr<device_base> set_virtual_device(const std::string& name, shared_ptr<device_base> device);
|
||||
|
||||
// Try to get parent directory (returns empty string on failure)
|
||||
std::string get_parent_dir(const std::string& path);
|
||||
@@ -182,12 +197,14 @@ namespace fs
|
||||
// Set file access/modification time
|
||||
bool utime(const std::string& path, s64 atime, s64 mtime);
|
||||
|
||||
// Synchronize filesystems (TODO)
|
||||
void sync();
|
||||
|
||||
class file final
|
||||
{
|
||||
std::unique_ptr<file_base> m_file;
|
||||
std::unique_ptr<file_base> m_file{};
|
||||
|
||||
[[noreturn]] void xnull() const;
|
||||
[[noreturn]] void xfail() const;
|
||||
bool strict_read_check(u64 size, u64 type_size) const;
|
||||
|
||||
public:
|
||||
// Default constructor
|
||||
@@ -197,7 +214,7 @@ namespace fs
|
||||
explicit file(const std::string& path, bs_t<open_mode> mode = ::fs::read);
|
||||
|
||||
// Open memory for read
|
||||
explicit file(const void* ptr, std::size_t size);
|
||||
explicit file(const void* ptr, usz size);
|
||||
|
||||
// Open file with specified args (forward to constructor)
|
||||
template <typename... Args>
|
||||
@@ -230,144 +247,244 @@ namespace fs
|
||||
}
|
||||
|
||||
// Change file size (possibly appending zero bytes)
|
||||
bool trunc(u64 length) const
|
||||
bool trunc(u64 length,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (!m_file) xnull();
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
return m_file->trunc(length);
|
||||
}
|
||||
|
||||
// Get file information
|
||||
stat_t stat() const
|
||||
stat_t stat(
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (!m_file) xnull();
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
return m_file->stat();
|
||||
}
|
||||
|
||||
// Sync file buffers
|
||||
void sync() const
|
||||
void sync(
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (!m_file) xnull();
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
return m_file->sync();
|
||||
}
|
||||
|
||||
// Read the data from the file and return the amount of data written in buffer
|
||||
u64 read(void* buffer, u64 count) const
|
||||
u64 read(void* buffer, u64 count,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (!m_file) xnull();
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
return m_file->read(buffer, count);
|
||||
}
|
||||
|
||||
// Write the data to the file and return the amount of data actually written
|
||||
u64 write(const void* buffer, u64 count) const
|
||||
u64 write(const void* buffer, u64 count,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (!m_file) xnull();
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
return m_file->write(buffer, count);
|
||||
}
|
||||
|
||||
// Change current position, returns resulting position
|
||||
u64 seek(s64 offset, seek_mode whence = seek_set) const
|
||||
u64 seek(s64 offset, seek_mode whence = seek_set,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (!m_file) xnull();
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
return m_file->seek(offset, whence);
|
||||
}
|
||||
|
||||
// Get file size
|
||||
u64 size() const
|
||||
u64 size(
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (!m_file) xnull();
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
return m_file->size();
|
||||
}
|
||||
|
||||
// Get current position
|
||||
u64 pos() const
|
||||
u64 pos(
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (!m_file) xnull();
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
return m_file->seek(0, seek_cur);
|
||||
}
|
||||
|
||||
// Write std::string unconditionally
|
||||
const file& write(const std::string& str) const
|
||||
// Write std::basic_string unconditionally
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, const file&> write(const std::basic_string<T>& str,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (write(str.data(), str.size()) != str.size()) xfail();
|
||||
if (write(str.data(), str.size() * sizeof(T), line, col, file, func) != str.size() * sizeof(T)) xfail({line, col, file, func});
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Write POD unconditionally
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, const file&> write(const T& data) const
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, const file&> write(const T& data,
|
||||
pod_tag_t = pod_tag,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (write(std::addressof(data), sizeof(T)) != sizeof(T)) xfail();
|
||||
if (write(std::addressof(data), sizeof(T), line, col, file, func) != sizeof(T)) xfail({line, col, file, func});
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Write POD std::vector unconditionally
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, const file&> write(const std::vector<T>& vec) const
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, const file&> write(const std::vector<T>& vec,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (write(vec.data(), vec.size() * sizeof(T)) != vec.size() * sizeof(T)) xfail();
|
||||
if (write(vec.data(), vec.size() * sizeof(T), line, col, file, func) != vec.size() * sizeof(T)) xfail({line, col, file, func});
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Read std::string, size must be set by resize() method
|
||||
bool read(std::string& str) const
|
||||
// Read std::basic_string, size must be set by resize() method
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::basic_string<T>& str,
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION(),
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN()) const
|
||||
{
|
||||
return read(&str[0], str.size()) == str.size();
|
||||
return read(&str[0], str.size() * sizeof(T), line, col, file, func) == str.size() * sizeof(T);
|
||||
}
|
||||
|
||||
// Read std::string
|
||||
bool read(std::string& str, std::size_t size) const
|
||||
// Read std::basic_string
|
||||
template <bool IsStrict = false, typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::basic_string<T>& str, usz _size,
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION(),
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN()) const
|
||||
{
|
||||
str.resize(size);
|
||||
return read(&str[0], size) == size;
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
if (!_size) return true;
|
||||
|
||||
if constexpr (IsStrict)
|
||||
{
|
||||
// If _size arg is too high std::bad_alloc may happen in resize and then we cannot error check
|
||||
if (!strict_read_check(_size, sizeof(T))) return false;
|
||||
}
|
||||
|
||||
str.resize(_size);
|
||||
return read(str.data(), sizeof(T) * _size, line, col, file, func) == sizeof(T) * _size;
|
||||
}
|
||||
|
||||
// Read POD, sizeof(T) is used
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(T& data) const
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(T& data,
|
||||
pod_tag_t = pod_tag,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
return read(&data, sizeof(T)) == sizeof(T);
|
||||
return read(&data, sizeof(T), line, col, file, func) == sizeof(T);
|
||||
}
|
||||
|
||||
// Read POD std::vector, size must be set by resize() method
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::vector<T>& vec) const
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::vector<T>& vec,
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION(),
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN()) const
|
||||
{
|
||||
return read(vec.data(), sizeof(T) * vec.size()) == sizeof(T) * vec.size();
|
||||
return read(vec.data(), sizeof(T) * vec.size(), line, col, file, func) == sizeof(T) * vec.size();
|
||||
}
|
||||
|
||||
// Read POD std::vector
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::vector<T>& vec, std::size_t size) const
|
||||
template <bool IsStrict = false, typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, bool> read(std::vector<T>& vec, usz _size,
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION(),
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN()) const
|
||||
{
|
||||
vec.resize(size);
|
||||
return read(vec.data(), sizeof(T) * size) == sizeof(T) * size;
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
if (!_size) return true;
|
||||
|
||||
if constexpr (IsStrict)
|
||||
{
|
||||
if (!strict_read_check(_size, sizeof(T))) return false;
|
||||
}
|
||||
|
||||
vec.resize(_size);
|
||||
return read(vec.data(), sizeof(T) * _size, line, col, file, func) == sizeof(T) * _size;
|
||||
}
|
||||
|
||||
// Read POD (experimental)
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, T> read() const
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, T> read(
|
||||
pod_tag_t = pod_tag,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
T result;
|
||||
if (!read(result)) xfail();
|
||||
if (!read(result, pod_tag, line, col, file, func)) xfail({line, col, file, func});
|
||||
return result;
|
||||
}
|
||||
|
||||
// Read full file to std::string
|
||||
std::string to_string() const
|
||||
// Read full file to std::basic_string
|
||||
template <typename T = char>
|
||||
std::basic_string<T> to_string(
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
std::string result;
|
||||
result.resize(size());
|
||||
if (seek(0), !read(result)) xfail();
|
||||
std::basic_string<T> result;
|
||||
result.resize(size() / sizeof(T));
|
||||
if (seek(0), !read(result, file, func, line, col)) xfail({line, col, file, func});
|
||||
return result;
|
||||
}
|
||||
|
||||
// Read full file to std::vector
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, std::vector<T>> to_vector() const
|
||||
std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>, std::vector<T>> to_vector(
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
std::vector<T> result;
|
||||
result.resize(size() / sizeof(T));
|
||||
if (seek(0), !read(result)) xfail();
|
||||
if (seek(0), !read(result, file, func, line, col)) xfail({line, col, file, func});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -375,18 +492,20 @@ namespace fs
|
||||
native_handle get_handle() const;
|
||||
|
||||
// Gathered write
|
||||
u64 write_gather(const iovec_clone* buffers, u64 buf_count) const
|
||||
u64 write_gather(const iovec_clone* buffers, u64 buf_count,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (!m_file) xnull();
|
||||
if (!m_file) xnull({line, col, file, func});
|
||||
return m_file->write_gather(buffers, buf_count);
|
||||
}
|
||||
};
|
||||
|
||||
class dir final
|
||||
{
|
||||
std::unique_ptr<dir_base> m_dir;
|
||||
|
||||
[[noreturn]] void xnull() const;
|
||||
std::unique_ptr<dir_base> m_dir{};
|
||||
|
||||
public:
|
||||
dir() = default;
|
||||
@@ -423,23 +542,31 @@ namespace fs
|
||||
}
|
||||
|
||||
// Get next directory entry
|
||||
bool read(dir_entry& out) const
|
||||
bool read(dir_entry& out,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (!m_dir) xnull();
|
||||
if (!m_dir) xnull({line, col, file, func});
|
||||
return m_dir->read(out);
|
||||
}
|
||||
|
||||
// Reset to the beginning
|
||||
void rewind() const
|
||||
void rewind(
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION()) const
|
||||
{
|
||||
if (!m_dir) xnull();
|
||||
if (!m_dir) xnull({line, col, file, func});
|
||||
return m_dir->rewind();
|
||||
}
|
||||
|
||||
class iterator
|
||||
{
|
||||
const dir* m_parent;
|
||||
dir_entry m_entry;
|
||||
dir_entry m_entry{};
|
||||
|
||||
public:
|
||||
enum class mode
|
||||
@@ -467,6 +594,14 @@ namespace fs
|
||||
}
|
||||
}
|
||||
|
||||
iterator(const iterator&) = default;
|
||||
|
||||
iterator(iterator&&) = default;
|
||||
|
||||
iterator& operator=(const iterator&) = default;
|
||||
|
||||
iterator& operator=(iterator&&) = default;
|
||||
|
||||
dir_entry& operator *()
|
||||
{
|
||||
return m_entry;
|
||||
@@ -501,8 +636,21 @@ namespace fs
|
||||
// Get common cache directory
|
||||
const std::string& get_cache_dir();
|
||||
|
||||
// Get real path for comparisons (TODO: investigate std::filesystem::path::compare implementation)
|
||||
std::string escape_path(std::string_view path);
|
||||
// Unique pending file creation destined to be renamed to the destination file
|
||||
struct pending_file
|
||||
{
|
||||
fs::file file{};
|
||||
|
||||
// This is meant to modify files atomically, overwriting is likely
|
||||
bool commit(bool overwrite = true);
|
||||
|
||||
pending_file(const std::string& path);
|
||||
~pending_file();
|
||||
|
||||
private:
|
||||
std::string m_path{}; // Pending file path
|
||||
std::string m_dest{}; // Destination file path
|
||||
};
|
||||
|
||||
// Delete directory and all its contents recursively
|
||||
bool remove_all(const std::string& path, bool remove_root = true);
|
||||
@@ -576,13 +724,16 @@ namespace fs
|
||||
{
|
||||
const u64 old_size = obj.size();
|
||||
|
||||
if (old_size + size < old_size)
|
||||
if (old_size + size < old_size || pos + size < pos)
|
||||
{
|
||||
fmt::raw_error("fs::container_stream<>::write(): overflow");
|
||||
xovfl();
|
||||
}
|
||||
|
||||
if (pos > old_size)
|
||||
{
|
||||
// Reserve memory
|
||||
obj.reserve(pos + size);
|
||||
|
||||
// Fill gap if necessary (default-initialized)
|
||||
obj.resize(pos);
|
||||
}
|
||||
@@ -631,14 +782,28 @@ namespace fs
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
template <bool Flush = false, typename... Args>
|
||||
bool write_file(const std::string& path, bs_t<fs::open_mode> mode, const Args&... args)
|
||||
{
|
||||
// Always use write flag, remove read flag
|
||||
if (fs::file f{path, mode + fs::write - fs::read})
|
||||
{
|
||||
// Write args sequentially
|
||||
(f.write(args), ...);
|
||||
if constexpr (sizeof...(args) == 2u && (std::is_pointer_v<Args> || ...))
|
||||
{
|
||||
// Specialization for [const void*, usz] args
|
||||
f.write(args...);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write args sequentially
|
||||
(f.write(args), ...);
|
||||
}
|
||||
|
||||
if constexpr (Flush)
|
||||
{
|
||||
f.sync();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+140
-56
@@ -1,16 +1,16 @@
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
#include "util/sysinfo.hpp"
|
||||
#include "JIT.h"
|
||||
#include "StrFmt.h"
|
||||
#include "File.h"
|
||||
#include "util/logs.hpp"
|
||||
#include "mutex.h"
|
||||
#include "sysinfo.h"
|
||||
#include "VirtualMemory.h"
|
||||
#include <immintrin.h>
|
||||
#include "util/vm.hpp"
|
||||
#include "util/asm.hpp"
|
||||
#include <charconv>
|
||||
#include <zlib.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/mman.h>
|
||||
#define CAN_OVERCOMMIT
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,6 @@ static u8* get_jit_memory()
|
||||
static void* const s_memory2 = []() -> void*
|
||||
{
|
||||
void* ptr = utils::memory_reserve(0x80000000);
|
||||
|
||||
#ifdef CAN_OVERCOMMIT
|
||||
utils::memory_commit(ptr, 0x80000000);
|
||||
utils::memory_protect(ptr, 0x40000000, utils::protection::wx);
|
||||
@@ -40,7 +39,7 @@ static atomic_t<u64> s_code_pos{0}, s_data_pos{0};
|
||||
static std::vector<u8> s_code_init, s_data_init;
|
||||
|
||||
template <atomic_t<u64>& Ctr, uint Off, utils::protection Prot>
|
||||
static u8* add_jit_memory(std::size_t size, uint align)
|
||||
static u8* add_jit_memory(usz size, uint align)
|
||||
{
|
||||
// Select subrange
|
||||
u8* pointer = get_jit_memory() + Off;
|
||||
@@ -56,8 +55,8 @@ static u8* add_jit_memory(std::size_t size, uint align)
|
||||
// Simple allocation by incrementing pointer to the next free data
|
||||
const u64 pos = Ctr.atomic_op([&](u64& ctr) -> u64
|
||||
{
|
||||
const u64 _pos = ::align(ctr & 0xffff'ffff, align);
|
||||
const u64 _new = ::align(_pos + size, align);
|
||||
const u64 _pos = utils::align(ctr & 0xffff'ffff, align);
|
||||
const u64 _new = utils::align(_pos + size, align);
|
||||
|
||||
if (_new > 0x40000000) [[unlikely]]
|
||||
{
|
||||
@@ -73,7 +72,7 @@ static u8* add_jit_memory(std::size_t size, uint align)
|
||||
// Check the necessity to commit more memory
|
||||
if (_new > olda) [[unlikely]]
|
||||
{
|
||||
newa = ::align(_new, 0x100000);
|
||||
newa = utils::align(_new, 0x200000);
|
||||
}
|
||||
|
||||
ctr += _new - (ctr & 0xffff'ffff);
|
||||
@@ -82,15 +81,13 @@ static u8* add_jit_memory(std::size_t size, uint align)
|
||||
|
||||
if (pos == umax) [[unlikely]]
|
||||
{
|
||||
jit_log.error("JIT: Out of memory (size=0x%x, align=0x%x, off=0x%x)", size, align, Off);
|
||||
jit_log.error("Out of memory (size=0x%x, align=0x%x, off=0x%x)", size, align, Off);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (olda != newa) [[unlikely]]
|
||||
{
|
||||
#ifdef CAN_OVERCOMMIT
|
||||
madvise(pointer + olda, newa - olda, MADV_WILLNEED);
|
||||
#else
|
||||
#ifndef CAN_OVERCOMMIT
|
||||
// Commit more memory
|
||||
utils::memory_commit(pointer + olda, newa - olda, Prot);
|
||||
#endif
|
||||
@@ -118,7 +115,7 @@ jit_runtime::~jit_runtime()
|
||||
|
||||
asmjit::Error jit_runtime::_add(void** dst, asmjit::CodeHolder* code) noexcept
|
||||
{
|
||||
std::size_t codeSize = code->getCodeSize();
|
||||
usz codeSize = code->getCodeSize();
|
||||
if (!codeSize) [[unlikely]]
|
||||
{
|
||||
*dst = nullptr;
|
||||
@@ -132,7 +129,7 @@ asmjit::Error jit_runtime::_add(void** dst, asmjit::CodeHolder* code) noexcept
|
||||
return asmjit::kErrorNoVirtualMemory;
|
||||
}
|
||||
|
||||
std::size_t relocSize = code->relocate(p);
|
||||
usz relocSize = code->relocate(p);
|
||||
if (!relocSize) [[unlikely]]
|
||||
{
|
||||
*dst = nullptr;
|
||||
@@ -145,12 +142,12 @@ asmjit::Error jit_runtime::_add(void** dst, asmjit::CodeHolder* code) noexcept
|
||||
return asmjit::kErrorOk;
|
||||
}
|
||||
|
||||
asmjit::Error jit_runtime::_release(void* ptr) noexcept
|
||||
asmjit::Error jit_runtime::_release(void*) noexcept
|
||||
{
|
||||
return asmjit::kErrorOk;
|
||||
}
|
||||
|
||||
u8* jit_runtime::alloc(std::size_t size, uint align, bool exec) noexcept
|
||||
u8* jit_runtime::alloc(usz size, uint align, bool exec) noexcept
|
||||
{
|
||||
if (exec)
|
||||
{
|
||||
@@ -220,37 +217,42 @@ asmjit::Runtime& asmjit::get_global_runtime()
|
||||
utils::memory_commit(m_pos, size, utils::protection::wx);
|
||||
}
|
||||
|
||||
custom_runtime(const custom_runtime&) = delete;
|
||||
|
||||
custom_runtime& operator=(const custom_runtime&) = delete;
|
||||
|
||||
asmjit::Error _add(void** dst, asmjit::CodeHolder* code) noexcept override
|
||||
{
|
||||
std::size_t codeSize = code->getCodeSize();
|
||||
usz codeSize = code->getCodeSize();
|
||||
if (!codeSize) [[unlikely]]
|
||||
{
|
||||
*dst = nullptr;
|
||||
return asmjit::kErrorNoCodeGenerated;
|
||||
}
|
||||
|
||||
void* p = m_pos.fetch_add(::align(codeSize, 4096));
|
||||
void* p = m_pos.fetch_add(utils::align(codeSize, 4096));
|
||||
if (!p || m_pos > m_max) [[unlikely]]
|
||||
{
|
||||
*dst = nullptr;
|
||||
jit_log.fatal("Out of memory (static asmjit)");
|
||||
return asmjit::kErrorNoVirtualMemory;
|
||||
}
|
||||
|
||||
std::size_t relocSize = code->relocate(p);
|
||||
usz relocSize = code->relocate(p);
|
||||
if (!relocSize) [[unlikely]]
|
||||
{
|
||||
*dst = nullptr;
|
||||
return asmjit::kErrorInvalidState;
|
||||
}
|
||||
|
||||
utils::memory_protect(p, ::align(codeSize, 4096), utils::protection::rx);
|
||||
utils::memory_protect(p, utils::align(codeSize, 4096), utils::protection::rx);
|
||||
flush(p, relocSize);
|
||||
*dst = p;
|
||||
|
||||
return asmjit::kErrorOk;
|
||||
}
|
||||
|
||||
asmjit::Error _release(void* ptr) noexcept override
|
||||
asmjit::Error _release(void*) noexcept override
|
||||
{
|
||||
return asmjit::kErrorOk;
|
||||
}
|
||||
@@ -269,10 +271,7 @@ asmjit::Runtime& asmjit::get_global_runtime()
|
||||
#ifdef LLVM_AVAILABLE
|
||||
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <set>
|
||||
#include <array>
|
||||
#include <deque>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -282,6 +281,11 @@ asmjit::Runtime& asmjit::get_global_runtime()
|
||||
#pragma GCC diagnostic ignored "-Wall"
|
||||
#pragma GCC diagnostic ignored "-Wextra"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#pragma GCC diagnostic ignored "-Wmissing-noreturn"
|
||||
#endif
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
@@ -295,12 +299,6 @@ asmjit::Runtime& asmjit::get_global_runtime()
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
const bool jit_initialize = []() -> bool
|
||||
{
|
||||
llvm::InitializeNativeTarget();
|
||||
@@ -310,14 +308,74 @@ const bool jit_initialize = []() -> bool
|
||||
return true;
|
||||
}();
|
||||
|
||||
[[noreturn]] static void null(const char* name)
|
||||
{
|
||||
fmt::throw_exception("Null function: %s", name);
|
||||
}
|
||||
|
||||
namespace vm
|
||||
{
|
||||
extern u8* const g_sudo_addr;
|
||||
}
|
||||
|
||||
static shared_mutex null_mtx;
|
||||
|
||||
static std::unordered_map<std::string, u64> null_funcs;
|
||||
|
||||
static u64 make_null_function(const std::string& name)
|
||||
{
|
||||
if (name.starts_with("__0x"))
|
||||
{
|
||||
u32 addr = -1;
|
||||
auto res = std::from_chars(name.c_str() + 4, name.c_str() + name.size(), addr, 16);
|
||||
|
||||
if (res.ec == std::errc() && res.ptr == name.c_str() + name.size() && addr < 0x8000'0000)
|
||||
{
|
||||
// Point the garbage to reserved, non-executable memory
|
||||
return reinterpret_cast<u64>(vm::g_sudo_addr + addr);
|
||||
}
|
||||
}
|
||||
|
||||
std::lock_guard lock(null_mtx);
|
||||
|
||||
if (u64& func_ptr = null_funcs[name]) [[likely]]
|
||||
{
|
||||
// Already exists
|
||||
return func_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
using namespace asmjit;
|
||||
|
||||
// Build a "null" function that contains its name
|
||||
const auto func = build_function_asm<void (*)()>([&](X86Assembler& c, auto& args)
|
||||
{
|
||||
Label data = c.newLabel();
|
||||
c.lea(args[0], x86::qword_ptr(data, 0));
|
||||
c.jmp(imm_ptr(&null));
|
||||
c.align(kAlignCode, 16);
|
||||
c.bind(data);
|
||||
|
||||
// Copy function name bytes
|
||||
for (char ch : name)
|
||||
c.db(ch);
|
||||
c.db(0);
|
||||
c.align(kAlignData, 16);
|
||||
});
|
||||
|
||||
func_ptr = reinterpret_cast<u64>(func);
|
||||
return func_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Simple memory manager
|
||||
struct MemoryManager1 : llvm::RTDyldMemoryManager
|
||||
{
|
||||
// 256 MiB for code or data
|
||||
static constexpr u64 c_max_size = 0x20000000 / 2;
|
||||
|
||||
// Allocation unit
|
||||
static constexpr u64 c_page_size = 4096;
|
||||
// Allocation unit (2M)
|
||||
static constexpr u64 c_page_size = 2 * 1024 * 1024;
|
||||
|
||||
// Reserve 512 MiB
|
||||
u8* const ptr = static_cast<u8*>(utils::memory_reserve(c_max_size * 2));
|
||||
@@ -327,50 +385,54 @@ struct MemoryManager1 : llvm::RTDyldMemoryManager
|
||||
|
||||
MemoryManager1() = default;
|
||||
|
||||
MemoryManager1(const MemoryManager1&) = delete;
|
||||
|
||||
MemoryManager1& operator=(const MemoryManager1&) = delete;
|
||||
|
||||
~MemoryManager1() override
|
||||
{
|
||||
utils::memory_release(ptr, c_max_size * 2);
|
||||
}
|
||||
|
||||
[[noreturn]] static void null()
|
||||
{
|
||||
fmt::throw_exception("Null function" HERE);
|
||||
}
|
||||
|
||||
llvm::JITSymbol findSymbol(const std::string& name) override
|
||||
{
|
||||
u64 addr = RTDyldMemoryManager::getSymbolAddress(name);
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
addr = reinterpret_cast<uptr>(&null);
|
||||
addr = make_null_function(name);
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
fmt::throw_exception("Failed to link '%s'", name);
|
||||
}
|
||||
}
|
||||
|
||||
return {addr, llvm::JITSymbolFlags::Exported};
|
||||
}
|
||||
|
||||
u8* allocate(u64& oldp, std::uintptr_t size, uint align, utils::protection prot)
|
||||
u8* allocate(u64& oldp, uptr size, uint align, utils::protection prot)
|
||||
{
|
||||
if (align > c_page_size)
|
||||
{
|
||||
jit_log.fatal("JIT: Unsupported alignment (size=0x%x, align=0x%x)", size, align);
|
||||
jit_log.fatal("Unsupported alignment (size=0x%x, align=0x%x)", size, align);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const u64 olda = ::align(oldp, align);
|
||||
const u64 newp = ::align(olda + size, align);
|
||||
const u64 olda = utils::align(oldp, align);
|
||||
const u64 newp = utils::align(olda + size, align);
|
||||
|
||||
if ((newp - 1) / c_max_size != oldp / c_max_size)
|
||||
{
|
||||
jit_log.fatal("JIT: Out of memory (size=0x%x, align=0x%x)", size, align);
|
||||
jit_log.fatal("Out of memory (size=0x%x, align=0x%x)", size, align);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ((oldp - 1) / c_page_size != (newp - 1) / c_page_size)
|
||||
{
|
||||
// Allocate pages on demand
|
||||
const u64 pagea = ::align(oldp, c_page_size);
|
||||
const u64 psize = ::align(newp - pagea, c_page_size);
|
||||
const u64 pagea = utils::align(oldp, c_page_size);
|
||||
const u64 psize = utils::align(newp - pagea, c_page_size);
|
||||
utils::memory_commit(this->ptr + pagea, psize, prot);
|
||||
}
|
||||
|
||||
@@ -380,12 +442,12 @@ struct MemoryManager1 : llvm::RTDyldMemoryManager
|
||||
return this->ptr + olda;
|
||||
}
|
||||
|
||||
u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
|
||||
u8* allocateCodeSection(uptr size, uint align, uint /*sec_id*/, llvm::StringRef /*sec_name*/) override
|
||||
{
|
||||
return allocate(code_ptr, size, align, utils::protection::wx);
|
||||
}
|
||||
|
||||
u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
|
||||
u8* allocateDataSection(uptr size, uint align, uint /*sec_id*/, llvm::StringRef /*sec_name*/, bool /*is_ro*/) override
|
||||
{
|
||||
return allocate(data_ptr, size, align, utils::protection::rw);
|
||||
}
|
||||
@@ -395,7 +457,7 @@ struct MemoryManager1 : llvm::RTDyldMemoryManager
|
||||
return false;
|
||||
}
|
||||
|
||||
void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
void registerEHFrames(u8*, u64, usz) override
|
||||
{
|
||||
}
|
||||
|
||||
@@ -413,12 +475,29 @@ struct MemoryManager2 : llvm::RTDyldMemoryManager
|
||||
{
|
||||
}
|
||||
|
||||
u8* allocateCodeSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name) override
|
||||
llvm::JITSymbol findSymbol(const std::string& name) override
|
||||
{
|
||||
u64 addr = RTDyldMemoryManager::getSymbolAddress(name);
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
addr = make_null_function(name);
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
fmt::throw_exception("Failed to link '%s' (MM2)", name);
|
||||
}
|
||||
}
|
||||
|
||||
return {addr, llvm::JITSymbolFlags::Exported};
|
||||
}
|
||||
|
||||
u8* allocateCodeSection(uptr size, uint align, uint /*sec_id*/, llvm::StringRef /*sec_name*/) override
|
||||
{
|
||||
return jit_runtime::alloc(size, align, true);
|
||||
}
|
||||
|
||||
u8* allocateDataSection(std::uintptr_t size, uint align, uint sec_id, llvm::StringRef sec_name, bool is_ro) override
|
||||
u8* allocateDataSection(uptr size, uint align, uint /*sec_id*/, llvm::StringRef /*sec_name*/, bool /*is_ro*/) override
|
||||
{
|
||||
return jit_runtime::alloc(size, align, false);
|
||||
}
|
||||
@@ -428,7 +507,7 @@ struct MemoryManager2 : llvm::RTDyldMemoryManager
|
||||
return false;
|
||||
}
|
||||
|
||||
void registerEHFrames(u8* addr, u64 load_addr, std::size_t size) override
|
||||
void registerEHFrames(u8*, u64, usz) override
|
||||
{
|
||||
}
|
||||
|
||||
@@ -458,7 +537,7 @@ public:
|
||||
name.append(".gz");
|
||||
|
||||
z_stream zs{};
|
||||
uLong zsz = compressBound(::narrow<u32>(obj.getBufferSize(), HERE)) + 256;
|
||||
uLong zsz = compressBound(::narrow<u32>(obj.getBufferSize())) + 256;
|
||||
auto zbuf = std::make_unique<uchar[]>(zsz);
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic push
|
||||
@@ -489,7 +568,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
fs::file(name, fs::rewrite).write(zbuf.get(), zsz - zs.avail_out);
|
||||
if (!fs::write_file(name, fs::rewrite, zbuf.get(), zsz - zs.avail_out))
|
||||
{
|
||||
jit_log.error("LLVM: Failed to create module file: %s (%s)", name, fs::g_tls_error);
|
||||
return;
|
||||
}
|
||||
|
||||
jit_log.notice("LLVM: Created module: %s", _module->getName().data());
|
||||
}
|
||||
|
||||
@@ -683,7 +767,7 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, co
|
||||
|
||||
for (auto&& [name, addr] : _link)
|
||||
{
|
||||
m_engine->addGlobalMapping(name, addr);
|
||||
m_engine->updateGlobalMapping(name, addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-9
@@ -13,6 +13,14 @@
|
||||
#pragma GCC diagnostic ignored "-Wall"
|
||||
#pragma GCC diagnostic ignored "-Wextra"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic ignored "-Wduplicated-branches"
|
||||
#endif
|
||||
#include <asmjit/asmjit.h>
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
@@ -41,7 +49,7 @@ struct jit_runtime final : asmjit::HostRuntime
|
||||
asmjit::Error _release(void* p) noexcept override;
|
||||
|
||||
// Allocate memory
|
||||
static u8* alloc(std::size_t size, uint align, bool exec = true) noexcept;
|
||||
static u8* alloc(usz size, uint align, bool exec = true) noexcept;
|
||||
|
||||
// Should be called at least once after global initialization
|
||||
static void initialize();
|
||||
@@ -148,7 +156,7 @@ inline FT build_function_asm(F&& builder)
|
||||
|
||||
X86Assembler compiler(&code);
|
||||
builder(std::ref(compiler), args);
|
||||
ASSERT(compiler.getLastError() == 0);
|
||||
ensure(compiler.getLastError() == 0);
|
||||
|
||||
FT result;
|
||||
|
||||
@@ -167,10 +175,8 @@ inline FT build_function_asm(F&& builder)
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "types.h"
|
||||
#include "mutex.h"
|
||||
#include "util/types.hpp"
|
||||
|
||||
#include "restore_new.h"
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#else
|
||||
@@ -178,6 +184,14 @@ inline FT build_function_asm(F&& builder)
|
||||
#pragma GCC diagnostic ignored "-Wall"
|
||||
#pragma GCC diagnostic ignored "-Wextra"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Wsuggest-override"
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#pragma GCC diagnostic ignored "-Wmissing-noreturn"
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Winconsistent-missing-override"
|
||||
#endif
|
||||
#endif
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
@@ -187,19 +201,18 @@ inline FT build_function_asm(F&& builder)
|
||||
#else
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#include "define_new_memleakdetect.h"
|
||||
|
||||
// Temporary compiler interface
|
||||
class jit_compiler final
|
||||
{
|
||||
// Local LLVM context
|
||||
llvm::LLVMContext m_context;
|
||||
llvm::LLVMContext m_context{};
|
||||
|
||||
// Execution instance
|
||||
std::unique_ptr<llvm::ExecutionEngine> m_engine;
|
||||
std::unique_ptr<llvm::ExecutionEngine> m_engine{};
|
||||
|
||||
// Arch
|
||||
std::string m_cpu;
|
||||
std::string m_cpu{};
|
||||
|
||||
public:
|
||||
jit_compiler(const std::unordered_map<std::string, u64>& _link, const std::string& _cpu, u32 flags = 0);
|
||||
|
||||
@@ -29,24 +29,22 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
|
||||
// check if the scheme name is valid
|
||||
static bool IsSchemeValid( const std::string& SchemeName )
|
||||
{
|
||||
for ( auto c : SchemeName )
|
||||
return std::all_of(SchemeName.cbegin(), SchemeName.cend(), [](const auto& c)
|
||||
{
|
||||
if ( !isalpha( c ) && c != '+' && c != '-' && c != '.' ) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return isalpha(c) || c == '+' || c == '-' || c == '.';
|
||||
});
|
||||
}
|
||||
|
||||
bool LUrlParser::clParseURL::GetPort( int* OutPort ) const
|
||||
{
|
||||
if ( !IsValid() ) { return false; }
|
||||
|
||||
int Port = atoi( m_Port.c_str() );
|
||||
const int Port = atoi( m_Port.c_str() );
|
||||
|
||||
if ( Port <= 0 || Port > 65535 ) { return false; }
|
||||
|
||||
|
||||
+13
-13
@@ -1,21 +1,21 @@
|
||||
/*
|
||||
* Lightweight URL & URI parser (RFC 1738, RFC 3986)
|
||||
* https://github.com/corporateshark/LUrlParser
|
||||
*
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com)
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -47,14 +47,14 @@ namespace LUrlParser
|
||||
{
|
||||
public:
|
||||
LUrlParserError m_ErrorCode;
|
||||
std::string m_Scheme;
|
||||
std::string m_Host;
|
||||
std::string m_Port;
|
||||
std::string m_Path;
|
||||
std::string m_Query;
|
||||
std::string m_Fragment;
|
||||
std::string m_UserName;
|
||||
std::string m_Password;
|
||||
std::string m_Scheme{};
|
||||
std::string m_Host{};
|
||||
std::string m_Port{};
|
||||
std::string m_Path{};
|
||||
std::string m_Query{};
|
||||
std::string m_Fragment{};
|
||||
std::string m_UserName{};
|
||||
std::string m_Password{};
|
||||
|
||||
clParseURL()
|
||||
: m_ErrorCode( LUrlParserError_Uninitialized )
|
||||
|
||||
+146
-100
@@ -1,8 +1,9 @@
|
||||
#include "StrFmt.h"
|
||||
#include "BEType.h"
|
||||
#include "StrFmt.h"
|
||||
#include "StrUtil.h"
|
||||
#include "cfmt.h"
|
||||
#include "util/endian.hpp"
|
||||
#include "util/logs.hpp"
|
||||
#include "util/v128.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
@@ -78,14 +79,14 @@ void fmt_class_string<fmt::base57>::format(std::string& out, u64 arg)
|
||||
static constexpr u8 s_tail[8] = {0, 2, 3, 5, 6, 7, 9, 10};
|
||||
|
||||
// Get full output size
|
||||
const std::size_t out_size = _arg.size / 8 * 11 + s_tail[_arg.size % 8];
|
||||
const usz out_size = _arg.size / 8 * 11 + s_tail[_arg.size % 8];
|
||||
|
||||
out.resize(out.size() + out_size);
|
||||
|
||||
const auto ptr = &out.front() + (out.size() - out_size);
|
||||
|
||||
// Each 8 bytes of input data produce 11 bytes of base57 output
|
||||
for (std::size_t i = 0, p = 0; i < _arg.size; i += 8, p += 11)
|
||||
for (usz i = 0, p = 0; i < _arg.size; i += 8, p += 11)
|
||||
{
|
||||
// Load up to 8 bytes
|
||||
be_t<u64> be_value;
|
||||
@@ -235,6 +236,12 @@ void fmt_class_string<bool>::format(std::string& out, u64 arg)
|
||||
out += arg ? "true" : "false";
|
||||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<b8>::format(std::string& out, u64 arg)
|
||||
{
|
||||
out += get_object(arg) ? "true" : "false";
|
||||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<v128>::format(std::string& out, u64 arg)
|
||||
{
|
||||
@@ -242,70 +249,89 @@ void fmt_class_string<v128>::format(std::string& out, u64 arg)
|
||||
fmt::append(out, "0x%016llx%016llx", vec._u64[1], vec._u64[0]);
|
||||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<u128>::format(std::string& out, u64 arg)
|
||||
{
|
||||
// TODO: it should be supported as full-fledged integral type (with %u, %d, etc, fmt)
|
||||
const u128& num = get_object(arg);
|
||||
|
||||
if (!num)
|
||||
{
|
||||
out += '0';
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
fmt::append(out, "0x%016llx%016llx", num.hi, num.lo);
|
||||
#else
|
||||
fmt::append(out, "0x%016llx%016llx", static_cast<u64>(num >> 64), static_cast<u64>(num));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<s128>::format(std::string& out, u64 arg)
|
||||
{
|
||||
return fmt_class_string<u128>::format(out, arg);
|
||||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<src_loc>::format(std::string& out, u64 arg)
|
||||
{
|
||||
const src_loc& loc = get_object(arg);
|
||||
|
||||
if (loc.col != umax)
|
||||
{
|
||||
fmt::append(out, "\n(in file %s:%u[:%u]", loc.file, loc.line, loc.col);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::append(out, "\n(in file %s:%u", loc.file, loc.line);
|
||||
}
|
||||
|
||||
if (loc.func && *loc.func)
|
||||
{
|
||||
fmt::append(out, ", in function %s)", loc.func);
|
||||
}
|
||||
else
|
||||
{
|
||||
out += ')';
|
||||
}
|
||||
|
||||
// Print error code (may be irrelevant)
|
||||
#ifdef _WIN32
|
||||
if (DWORD error = GetLastError())
|
||||
{
|
||||
fmt::append(out, " (e=0x%08x[%u])", error, error);
|
||||
}
|
||||
#else
|
||||
if (int error = errno)
|
||||
{
|
||||
fmt::append(out, " (errno=%d)", error);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace fmt
|
||||
{
|
||||
void raw_error(const char* msg)
|
||||
{
|
||||
thread_ctrl::emergency_exit(msg);
|
||||
}
|
||||
|
||||
void raw_verify_error(const char* msg, const fmt_type_info* sup, u64 arg)
|
||||
[[noreturn]] void raw_verify_error(const src_loc& loc)
|
||||
{
|
||||
std::string out{"Verification failed"};
|
||||
|
||||
// Print error code (may be irrelevant)
|
||||
#ifdef _WIN32
|
||||
if (DWORD error = GetLastError())
|
||||
{
|
||||
fmt::append(out, " (e=%#x)", error);
|
||||
}
|
||||
#else
|
||||
if (int error = errno)
|
||||
{
|
||||
fmt::append(out, " (e=%d)", error);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sup)
|
||||
{
|
||||
out += " (";
|
||||
sup->fmt_string(out, arg); // Print value
|
||||
out += ")";
|
||||
}
|
||||
|
||||
if (msg)
|
||||
{
|
||||
out += ": ";
|
||||
out += msg;
|
||||
}
|
||||
|
||||
fmt::append(out, "%s", loc);
|
||||
thread_ctrl::emergency_exit(out);
|
||||
}
|
||||
|
||||
void raw_narrow_error(const char* msg, const fmt_type_info* sup, u64 arg)
|
||||
[[noreturn]] void raw_narrow_error(const src_loc& loc)
|
||||
{
|
||||
std::string out{"Narrow error"};
|
||||
|
||||
if (sup)
|
||||
{
|
||||
out += " (";
|
||||
sup->fmt_string(out, arg); // Print value
|
||||
out += ")";
|
||||
}
|
||||
|
||||
if (msg)
|
||||
{
|
||||
out += ": ";
|
||||
out += msg;
|
||||
}
|
||||
|
||||
std::string out{"Narrowing error"};
|
||||
fmt::append(out, "%s", loc);
|
||||
thread_ctrl::emergency_exit(out);
|
||||
}
|
||||
|
||||
void raw_throw_exception(const char* fmt, const fmt_type_info* sup, const u64* args)
|
||||
[[noreturn]] void raw_throw_exception(const src_loc& loc, const char* fmt, const fmt_type_info* sup, const u64* args)
|
||||
{
|
||||
std::string out;
|
||||
raw_append(out, fmt, sup, args);
|
||||
fmt::append(out, "%s", loc);
|
||||
thread_ctrl::emergency_exit(out);
|
||||
}
|
||||
|
||||
@@ -318,7 +344,7 @@ struct fmt::cfmt_src
|
||||
const fmt_type_info* sup;
|
||||
const u64* args;
|
||||
|
||||
bool test(std::size_t index) const
|
||||
bool test(usz index) const
|
||||
{
|
||||
if (!sup[index].fmt_string)
|
||||
{
|
||||
@@ -329,26 +355,28 @@ struct fmt::cfmt_src
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T get(std::size_t index) const
|
||||
T get(usz index) const
|
||||
{
|
||||
return *reinterpret_cast<const T*>(reinterpret_cast<const u8*>(args + index));
|
||||
T res{};
|
||||
std::memcpy(&res, reinterpret_cast<const u8*>(args + index), sizeof(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
void skip(std::size_t extra)
|
||||
void skip(usz extra)
|
||||
{
|
||||
sup += extra + 1;
|
||||
args += extra + 1;
|
||||
}
|
||||
|
||||
std::size_t fmt_string(std::string& out, std::size_t extra) const
|
||||
usz fmt_string(std::string& out, usz extra) const
|
||||
{
|
||||
const std::size_t start = out.size();
|
||||
const usz start = out.size();
|
||||
sup[extra].fmt_string(out, args[extra]);
|
||||
return out.size() - start;
|
||||
}
|
||||
|
||||
// Returns type size (0 if unknown, pointer, unsigned, assumed max)
|
||||
std::size_t type(std::size_t extra) const
|
||||
usz type(usz extra) const
|
||||
{
|
||||
// Hack: use known function pointers to determine type
|
||||
#define TYPE(type) \
|
||||
@@ -360,20 +388,22 @@ struct fmt::cfmt_src
|
||||
TYPE(short);
|
||||
if (std::is_signed<char>::value) TYPE(char);
|
||||
TYPE(long);
|
||||
TYPE(u128);
|
||||
TYPE(s128);
|
||||
|
||||
#undef TYPE
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static constexpr std::size_t size_char = 1;
|
||||
static constexpr std::size_t size_short = 2;
|
||||
static constexpr std::size_t size_int = 0;
|
||||
static constexpr std::size_t size_long = sizeof(ulong);
|
||||
static constexpr std::size_t size_llong = sizeof(ullong);
|
||||
static constexpr std::size_t size_size = sizeof(std::size_t);
|
||||
static constexpr std::size_t size_max = sizeof(std::uintmax_t);
|
||||
static constexpr std::size_t size_diff = sizeof(std::ptrdiff_t);
|
||||
static constexpr usz size_char = 1;
|
||||
static constexpr usz size_short = 2;
|
||||
static constexpr usz size_int = 0;
|
||||
static constexpr usz size_long = sizeof(ulong);
|
||||
static constexpr usz size_llong = sizeof(ullong);
|
||||
static constexpr usz size_size = sizeof(usz);
|
||||
static constexpr usz size_max = sizeof(std::uintmax_t);
|
||||
static constexpr usz size_diff = sizeof(std::ptrdiff_t);
|
||||
};
|
||||
|
||||
void fmt::raw_append(std::string& out, const char* fmt, const fmt_type_info* sup, const u64* args) noexcept
|
||||
@@ -381,56 +411,72 @@ void fmt::raw_append(std::string& out, const char* fmt, const fmt_type_info* sup
|
||||
cfmt_append(out, fmt, cfmt_src{sup, args});
|
||||
}
|
||||
|
||||
std::string fmt::replace_first(const std::string& src, const std::string& from, const std::string& to)
|
||||
std::string fmt::replace_all(std::string_view src, std::string_view from, std::string_view to, usz count)
|
||||
{
|
||||
auto pos = src.find(from);
|
||||
std::string target;
|
||||
target.reserve(src.size() + to.size());
|
||||
|
||||
if (pos == umax)
|
||||
for (usz i = 0, replaced = 0; i < src.size();)
|
||||
{
|
||||
return src;
|
||||
}
|
||||
const usz pos = src.find(from, i);
|
||||
|
||||
return (pos ? src.substr(0, pos) + to : to) + std::string(src.c_str() + pos + from.length());
|
||||
}
|
||||
if (pos == umax || replaced++ >= count)
|
||||
{
|
||||
// No match or too many encountered, append the rest of the string as is
|
||||
target.append(src.substr(i));
|
||||
break;
|
||||
}
|
||||
|
||||
std::string fmt::replace_all(const std::string& src, const std::string& from, const std::string& to)
|
||||
{
|
||||
std::string target = src;
|
||||
for (auto pos = target.find(from); pos != umax; pos = target.find(from, pos + 1))
|
||||
{
|
||||
target = (pos ? target.substr(0, pos) + to : to) + std::string(target.c_str() + pos + from.length());
|
||||
pos += to.length();
|
||||
// Append source until the matched string position
|
||||
target.append(src.substr(i, pos - i));
|
||||
|
||||
// Replace string
|
||||
target.append(to);
|
||||
i = pos + from.size();
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
std::vector<std::string> fmt::split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty)
|
||||
std::vector<std::string> fmt::split(std::string_view source, std::initializer_list<std::string_view> separators, bool is_skip_empty)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
size_t cursor_begin = 0;
|
||||
|
||||
for (size_t cursor_end = 0; cursor_end < source.length(); ++cursor_end)
|
||||
for (usz index = 0; index < source.size();)
|
||||
{
|
||||
usz pos = -1;
|
||||
usz sep_size = 0;
|
||||
|
||||
for (auto& separator : separators)
|
||||
{
|
||||
if (strncmp(source.c_str() + cursor_end, separator.c_str(), separator.length()) == 0)
|
||||
if (usz pos0 = source.find(separator, index); pos0 < pos)
|
||||
{
|
||||
std::string candidate = source.substr(cursor_begin, cursor_end - cursor_begin);
|
||||
if (!is_skip_empty || !candidate.empty())
|
||||
result.push_back(candidate);
|
||||
|
||||
cursor_begin = cursor_end + separator.length();
|
||||
cursor_end = cursor_begin - 1;
|
||||
break;
|
||||
pos = pos0;
|
||||
sep_size = separator.size();
|
||||
}
|
||||
}
|
||||
|
||||
if (!sep_size)
|
||||
{
|
||||
result.emplace_back(&source[index], source.size() - index);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string_view piece = {&source[index], pos - index};
|
||||
|
||||
index = pos + sep_size;
|
||||
|
||||
if (piece.empty() && is_skip_empty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.emplace_back(std::string(piece));
|
||||
}
|
||||
|
||||
if (cursor_begin != source.length())
|
||||
if (result.empty() && !is_skip_empty)
|
||||
{
|
||||
result.push_back(source.substr(cursor_begin));
|
||||
result.emplace_back();
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -438,7 +484,7 @@ std::vector<std::string> fmt::split(const std::string& source, std::initializer_
|
||||
|
||||
std::string fmt::trim(const std::string& source, const std::string& values)
|
||||
{
|
||||
std::size_t begin = source.find_first_not_of(values);
|
||||
usz begin = source.find_first_not_of(values);
|
||||
|
||||
if (begin == source.npos)
|
||||
return {};
|
||||
@@ -464,7 +510,7 @@ std::string fmt::to_lower(const std::string& string)
|
||||
|
||||
bool fmt::match(const std::string& source, const std::string& mask)
|
||||
{
|
||||
std::size_t source_position = 0, mask_position = 0;
|
||||
usz source_position = 0, mask_position = 0;
|
||||
|
||||
for (; source_position < source.size() && mask_position < mask.size(); ++mask_position, ++source_position)
|
||||
{
|
||||
@@ -473,7 +519,7 @@ bool fmt::match(const std::string& source, const std::string& mask)
|
||||
case '?': break;
|
||||
|
||||
case '*':
|
||||
for (std::size_t test_source_position = source_position; test_source_position < source.size(); ++test_source_position)
|
||||
for (usz test_source_position = source_position; test_source_position < source.size(); ++test_source_position)
|
||||
{
|
||||
if (match(source.substr(test_source_position), mask.substr(mask_position + 1)))
|
||||
{
|
||||
|
||||
+48
-42
@@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
#pragma once // No BOM and only basic ASCII in this header, or a neko will die
|
||||
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace fmt
|
||||
{
|
||||
template <typename CharT, std::size_t N, typename... Args>
|
||||
template <typename CharT, usz N, typename... Args>
|
||||
static std::string format(const CharT(&)[N], const Args&...);
|
||||
}
|
||||
|
||||
template <typename T, typename>
|
||||
template <typename T, typename = void>
|
||||
struct fmt_unveil
|
||||
{
|
||||
static_assert(sizeof(T) > 0, "fmt_unveil<> error: incomplete type");
|
||||
@@ -19,7 +19,7 @@ struct fmt_unveil
|
||||
|
||||
static inline u64 get(const T& arg)
|
||||
{
|
||||
return reinterpret_cast<std::uintptr_t>(&arg);
|
||||
return reinterpret_cast<uptr>(&arg);
|
||||
}
|
||||
|
||||
// Temporary value container (can possibly be created by other fmt_unveil<> specializations)
|
||||
@@ -30,7 +30,7 @@ struct fmt_unveil
|
||||
// Allow implicit conversion
|
||||
operator u64() const
|
||||
{
|
||||
return reinterpret_cast<std::uintptr_t>(&arg);
|
||||
return reinterpret_cast<uptr>(&arg);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -64,17 +64,6 @@ struct fmt_unveil<T, std::enable_if_t<std::is_floating_point<T>::value && sizeof
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt_unveil<f16, void>
|
||||
{
|
||||
using type = f16;
|
||||
|
||||
static inline u64 get(const f16& arg)
|
||||
{
|
||||
return fmt_unveil<f64>::get(arg.operator float());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct fmt_unveil<T, std::enable_if_t<std::is_enum<T>::value>>
|
||||
{
|
||||
@@ -93,29 +82,29 @@ struct fmt_unveil<T*, void>
|
||||
|
||||
static inline u64 get(type arg)
|
||||
{
|
||||
return reinterpret_cast<std::uintptr_t>(arg);
|
||||
return reinterpret_cast<uptr>(arg);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
template <typename T, usz N>
|
||||
struct fmt_unveil<T[N], void>
|
||||
{
|
||||
using type = std::add_const_t<T>*;
|
||||
|
||||
static inline u64 get(type arg)
|
||||
{
|
||||
return reinterpret_cast<std::uintptr_t>(arg);
|
||||
return reinterpret_cast<uptr>(arg);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt_unveil<b8, void>
|
||||
template <typename T, bool Se, usz Align>
|
||||
struct fmt_unveil<se_t<T, Se, Align>, void>
|
||||
{
|
||||
using type = bool;
|
||||
using type = typename fmt_unveil<T>::type;
|
||||
|
||||
static inline u64 get(const b8& value)
|
||||
static inline auto get(const se_t<T, Se, Align>& arg)
|
||||
{
|
||||
return fmt_unveil<bool>::get(value);
|
||||
return fmt_unveil<T>::get(arg);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -130,16 +119,16 @@ struct fmt_class_string
|
||||
using type = T;
|
||||
|
||||
// Helper function (converts arg to object reference)
|
||||
static SAFE_BUFFERS FORCE_INLINE const T& get_object(u64 arg)
|
||||
static FORCE_INLINE SAFE_BUFFERS(const T&) get_object(u64 arg)
|
||||
{
|
||||
return *reinterpret_cast<const T*>(static_cast<std::uintptr_t>(arg));
|
||||
return *reinterpret_cast<const T*>(static_cast<uptr>(arg));
|
||||
}
|
||||
|
||||
// Enum -> string function type
|
||||
using convert_t = const char*(*)(T value);
|
||||
|
||||
// Helper function (safely converts arg to enum value)
|
||||
static SAFE_BUFFERS FORCE_INLINE void format_enum(std::string& out, u64 arg, convert_t convert)
|
||||
static FORCE_INLINE SAFE_BUFFERS(void) format_enum(std::string& out, u64 arg, convert_t convert)
|
||||
{
|
||||
const auto value = static_cast<std::underlying_type_t<T>>(arg);
|
||||
|
||||
@@ -158,7 +147,7 @@ struct fmt_class_string
|
||||
}
|
||||
|
||||
// Helper function (bitset formatting)
|
||||
static SAFE_BUFFERS FORCE_INLINE void format_bitset(std::string& out, u64 arg, const char* prefix, const char* delim, const char* suffix, void (*fmt)(std::string&, u64))
|
||||
static FORCE_INLINE SAFE_BUFFERS(void) format_bitset(std::string& out, u64 arg, const char* prefix, const char* delim, const char* suffix, void (*fmt)(std::string&, u64))
|
||||
{
|
||||
// Start from raw value
|
||||
fmt_class_string<u64>::format(out, arg);
|
||||
@@ -234,13 +223,16 @@ struct fmt_type_info
|
||||
template <typename... Args>
|
||||
using fmt_args_t = const u64(&&)[sizeof...(Args) + 1];
|
||||
|
||||
template <typename Arg>
|
||||
using fmt_unveil_t = typename fmt_unveil<Arg>::type;
|
||||
|
||||
namespace fmt
|
||||
{
|
||||
// Base-57 format helper
|
||||
struct base57
|
||||
{
|
||||
const uchar* data;
|
||||
std::size_t size;
|
||||
usz size;
|
||||
|
||||
template <typename T>
|
||||
base57(const T& arg)
|
||||
@@ -249,7 +241,7 @@ namespace fmt
|
||||
{
|
||||
}
|
||||
|
||||
base57(const uchar* data, std::size_t size)
|
||||
base57(const uchar* data, usz size)
|
||||
: data(data)
|
||||
, size(size)
|
||||
{
|
||||
@@ -257,7 +249,7 @@ namespace fmt
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
SAFE_BUFFERS FORCE_INLINE const fmt_type_info* get_type_info()
|
||||
FORCE_INLINE SAFE_BUFFERS(const fmt_type_info*) get_type_info()
|
||||
{
|
||||
// Constantly initialized null-terminated list of type-specific information
|
||||
static constexpr fmt_type_info result[sizeof...(Args) + 1]{fmt_type_info::make<fmt_unveil_t<Args>>()...};
|
||||
@@ -272,16 +264,16 @@ namespace fmt
|
||||
void raw_append(std::string& out, const char*, const fmt_type_info*, const u64*) noexcept;
|
||||
|
||||
// Formatting function
|
||||
template <typename CharT, std::size_t N, typename... Args>
|
||||
SAFE_BUFFERS FORCE_INLINE void append(std::string& out, const CharT(&fmt)[N], const Args&... args)
|
||||
template <typename CharT, usz N, typename... Args>
|
||||
FORCE_INLINE SAFE_BUFFERS(void) append(std::string& out, const CharT(&fmt)[N], const Args&... args)
|
||||
{
|
||||
static constexpr fmt_type_info type_list[sizeof...(Args) + 1]{fmt_type_info::make<fmt_unveil_t<Args>>()...};
|
||||
raw_append(out, reinterpret_cast<const char*>(fmt), type_list, fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...});
|
||||
}
|
||||
|
||||
// Formatting function
|
||||
template <typename CharT, std::size_t N, typename... Args>
|
||||
SAFE_BUFFERS FORCE_INLINE std::string format(const CharT(&fmt)[N], const Args&... args)
|
||||
template <typename CharT, usz N, typename... Args>
|
||||
FORCE_INLINE SAFE_BUFFERS(std::string) format(const CharT(&fmt)[N], const Args&... args)
|
||||
{
|
||||
std::string result;
|
||||
append(result, fmt, args...);
|
||||
@@ -289,13 +281,27 @@ namespace fmt
|
||||
}
|
||||
|
||||
// Internal exception message formatting template, must be explicitly specialized or instantiated in cpp to minimize code bloat
|
||||
[[noreturn]] void raw_throw_exception(const char*, const fmt_type_info*, const u64*);
|
||||
[[noreturn]] void raw_throw_exception(const src_loc&, const char*, const fmt_type_info*, const u64*);
|
||||
|
||||
// Throw exception with formatting
|
||||
template <typename... Args>
|
||||
[[noreturn]] SAFE_BUFFERS FORCE_INLINE void throw_exception(const char* fmt, const Args&... args)
|
||||
template <typename CharT, usz N, typename... Args>
|
||||
struct throw_exception
|
||||
{
|
||||
static constexpr fmt_type_info type_list[sizeof...(Args) + 1]{fmt_type_info::make<fmt_unveil_t<Args>>()...};
|
||||
raw_throw_exception(fmt, type_list, fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...});
|
||||
}
|
||||
[[noreturn]] FORCE_INLINE SAFE_BUFFERS() throw_exception(const CharT(&fmt)[N], const Args&... args,
|
||||
u32 line = __builtin_LINE(),
|
||||
u32 col = __builtin_COLUMN(),
|
||||
const char* file = __builtin_FILE(),
|
||||
const char* func = __builtin_FUNCTION())
|
||||
{
|
||||
static constexpr fmt_type_info type_list[sizeof...(Args) + 1]{fmt_type_info::make<fmt_unveil_t<Args>>()...};
|
||||
raw_throw_exception({line, col, file, func}, reinterpret_cast<const char*>(fmt), type_list, fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...});
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
[[noreturn]] ~throw_exception();
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename CharT, usz N, typename... Args>
|
||||
throw_exception(const CharT(&)[N], const Args&...) -> throw_exception<CharT, N, Args...>;
|
||||
}
|
||||
|
||||
+11
-13
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -17,24 +16,23 @@ std::string utf8_path_to_ansi_path(const std::string& src);
|
||||
template <typename D, typename T>
|
||||
inline void strcpy_trunc(D& dst, const T& src)
|
||||
{
|
||||
const std::size_t count = std::size(src) >= std::size(dst) ? std::size(dst) - 1 : std::size(src);
|
||||
const usz count = std::size(src) >= std::size(dst) ? std::size(dst) - 1 : std::size(src);
|
||||
std::memcpy(std::data(dst), std::data(src), count);
|
||||
std::memset(std::data(dst) + count, 0, std::size(dst) - count);
|
||||
}
|
||||
|
||||
namespace fmt
|
||||
{
|
||||
std::string replace_first(const std::string& src, const std::string& from, const std::string& to);
|
||||
std::string replace_all(const std::string& src, const std::string& from, const std::string& to);
|
||||
std::string replace_all(std::string_view src, std::string_view from, std::string_view to, usz count = -1);
|
||||
|
||||
template <size_t list_size>
|
||||
template <usz list_size>
|
||||
std::string replace_all(std::string src, const std::pair<std::string, std::string> (&list)[list_size])
|
||||
{
|
||||
for (size_t pos = 0; pos < src.length(); ++pos)
|
||||
for (usz pos = 0; pos < src.length(); ++pos)
|
||||
{
|
||||
for (size_t i = 0; i < list_size; ++i)
|
||||
for (usz i = 0; i < list_size; ++i)
|
||||
{
|
||||
const size_t comp_length = list[i].first.length();
|
||||
const usz comp_length = list[i].first.length();
|
||||
|
||||
if (src.length() - pos < comp_length)
|
||||
continue;
|
||||
@@ -51,14 +49,14 @@ namespace fmt
|
||||
return src;
|
||||
}
|
||||
|
||||
template <size_t list_size>
|
||||
template <usz list_size>
|
||||
std::string replace_all(std::string src, const std::pair<std::string, std::function<std::string()>> (&list)[list_size])
|
||||
{
|
||||
for (size_t pos = 0; pos < src.length(); ++pos)
|
||||
for (usz pos = 0; pos < src.length(); ++pos)
|
||||
{
|
||||
for (size_t i = 0; i < list_size; ++i)
|
||||
for (usz i = 0; i < list_size; ++i)
|
||||
{
|
||||
const size_t comp_length = list[i].first.length();
|
||||
const usz comp_length = list[i].first.length();
|
||||
|
||||
if (src.length() - pos < comp_length)
|
||||
continue;
|
||||
@@ -75,7 +73,7 @@ namespace fmt
|
||||
return src;
|
||||
}
|
||||
|
||||
std::vector<std::string> split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty = true);
|
||||
std::vector<std::string> split(std::string_view source, std::initializer_list<std::string_view> separators, bool is_skip_empty = true);
|
||||
std::string trim(const std::string& source, const std::string& values = " \t");
|
||||
|
||||
template <typename T>
|
||||
|
||||
+781
-301
File diff suppressed because it is too large
Load Diff
+332
-129
@@ -1,20 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
#include "util/atomic.hpp"
|
||||
#include "util/shared_cptr.hpp"
|
||||
#include "util/shared_ptr.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include "mutex.h"
|
||||
#include "cond.h"
|
||||
#include "lockless.h"
|
||||
|
||||
// Report error and call std::abort(), defined in main.cpp
|
||||
[[noreturn]] void report_fatal_error(const std::string&);
|
||||
|
||||
// Hardware core layout
|
||||
enum class native_core_arrangement : u32
|
||||
{
|
||||
@@ -34,10 +28,11 @@ enum class thread_class : u32
|
||||
|
||||
enum class thread_state : u32
|
||||
{
|
||||
created, // Initial state
|
||||
aborting, // The thread has been joined in the destructor or explicitly aborted
|
||||
errored, // Set after the emergency_exit call
|
||||
finished // Final state, always set at the end of thread execution
|
||||
created = 0, // Initial state
|
||||
aborting = 1, // The thread has been joined in the destructor or explicitly aborted
|
||||
errored = 2, // Set after the emergency_exit call
|
||||
finished = 3, // Final state, always set at the end of thread execution
|
||||
mask = 3
|
||||
};
|
||||
|
||||
class need_wakeup {};
|
||||
@@ -45,10 +40,22 @@ class need_wakeup {};
|
||||
template <class Context>
|
||||
class named_thread;
|
||||
|
||||
template <typename T>
|
||||
class thread_base;
|
||||
|
||||
template <typename Ctx, typename... Args>
|
||||
struct result_storage
|
||||
{
|
||||
static_assert(std::is_default_constructible_v<T> && noexcept(T()));
|
||||
static constexpr bool empty = true;
|
||||
|
||||
using type = void;
|
||||
};
|
||||
|
||||
template <typename Ctx, typename... Args> requires (!std::is_void_v<std::invoke_result_t<Ctx, Args&&...>>)
|
||||
struct result_storage<Ctx, Args...>
|
||||
{
|
||||
using T = std::invoke_result_t<Ctx, Args&&...>;
|
||||
|
||||
static_assert(std::is_default_constructible_v<T>);
|
||||
|
||||
alignas(T) std::byte data[sizeof(T)];
|
||||
|
||||
@@ -56,42 +63,63 @@ struct result_storage
|
||||
|
||||
using type = T;
|
||||
|
||||
T* get()
|
||||
T* _get()
|
||||
{
|
||||
return reinterpret_cast<T*>(&data);
|
||||
}
|
||||
|
||||
const T* get() const
|
||||
const T* _get() const
|
||||
{
|
||||
return reinterpret_cast<const T*>(&data);
|
||||
}
|
||||
|
||||
void init() noexcept
|
||||
{
|
||||
new (data) T();
|
||||
}
|
||||
|
||||
void destroy() noexcept
|
||||
{
|
||||
get()->~T();
|
||||
_get()->~T();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct result_storage<void>
|
||||
template <typename T>
|
||||
concept NamedThreadName = requires (T& t)
|
||||
{
|
||||
static constexpr bool empty = true;
|
||||
|
||||
using type = void;
|
||||
std::string_view(t.thread_name);
|
||||
};
|
||||
|
||||
template <class Context, typename... Args>
|
||||
using result_storage_t = result_storage<std::invoke_result_t<Context, Args...>>;
|
||||
// Base class for task queue (linked list)
|
||||
class thread_future
|
||||
{
|
||||
friend class thread_base;
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct thread_thread_name : std::bool_constant<false> {};
|
||||
shared_ptr<thread_future> next{};
|
||||
|
||||
template <typename T>
|
||||
struct thread_thread_name<T, std::void_t<decltype(named_thread<T>::thread_name)>> : std::bool_constant<true> {};
|
||||
shared_ptr<thread_future>* prev{};
|
||||
|
||||
protected:
|
||||
atomic_t<void(*)(thread_base*, thread_future*)> exec{};
|
||||
|
||||
public:
|
||||
// Get reference to the atomic variable for inspection and waiting for
|
||||
const auto& get_wait() const
|
||||
{
|
||||
return exec;
|
||||
}
|
||||
|
||||
// Wait (preset)
|
||||
void wait() const
|
||||
{
|
||||
exec.wait<atomic_wait::op_ne>(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
// Thread base class
|
||||
class thread_base
|
||||
{
|
||||
public:
|
||||
// Native thread entry point function type
|
||||
#ifdef _WIN32
|
||||
using native_entry = uint(__stdcall*)(void* arg);
|
||||
@@ -99,38 +127,38 @@ class thread_base
|
||||
using native_entry = void*(*)(void* arg);
|
||||
#endif
|
||||
|
||||
const native_entry entry_point;
|
||||
|
||||
private:
|
||||
// Thread handle (platform-specific)
|
||||
atomic_t<std::uintptr_t> m_thread{0};
|
||||
atomic_t<u64> m_thread{0};
|
||||
|
||||
// Thread playtoy, that shouldn't be used
|
||||
atomic_t<u32> m_signal{0};
|
||||
|
||||
// Thread state
|
||||
atomic_t<thread_state> m_state = thread_state::created;
|
||||
|
||||
// Thread state notification info
|
||||
atomic_t<const void*> m_state_notifier{nullptr};
|
||||
// Thread state and cycles
|
||||
atomic_t<u64> m_sync{0};
|
||||
|
||||
// Thread name
|
||||
stx::atomic_cptr<std::string> m_tname;
|
||||
atomic_ptr<std::string> m_tname;
|
||||
|
||||
//
|
||||
atomic_t<u64> m_cycles = 0;
|
||||
// Thread task queue (reversed linked list)
|
||||
atomic_ptr<thread_future> m_taskq{};
|
||||
|
||||
// Start thread
|
||||
void start(native_entry);
|
||||
void start();
|
||||
|
||||
// Called at the thread start
|
||||
void initialize(void (*error_cb)(), bool(*wait_cb)(const void*));
|
||||
void initialize(void (*error_cb)());
|
||||
|
||||
// May be called in destructor
|
||||
void notify_abort() noexcept;
|
||||
|
||||
// Called at the thread end, returns true if needs destruction
|
||||
bool finalize(thread_state result) noexcept;
|
||||
// Called at the thread end, returns self handle
|
||||
u64 finalize(thread_state result) noexcept;
|
||||
|
||||
// Cleanup after possibly deleting the thread instance
|
||||
static void finalize() noexcept;
|
||||
static native_entry finalize(u64 _self) noexcept;
|
||||
|
||||
// Set name for debugger
|
||||
static void set_name(std::string);
|
||||
|
||||
// Make entry point
|
||||
static native_entry make_trampoline(u64(*)(thread_base*));
|
||||
|
||||
friend class thread_ctrl;
|
||||
|
||||
@@ -138,7 +166,7 @@ class thread_base
|
||||
friend class named_thread;
|
||||
|
||||
protected:
|
||||
thread_base(std::string_view name);
|
||||
thread_base(native_entry, std::string_view name);
|
||||
|
||||
~thread_base();
|
||||
|
||||
@@ -147,10 +175,20 @@ public:
|
||||
u64 get_cycles();
|
||||
|
||||
// Wait for the thread (it does NOT change thread state, and can be called from multiple threads)
|
||||
bool join() const;
|
||||
bool join(bool dtor = false) const;
|
||||
|
||||
// Notify the thread
|
||||
void notify();
|
||||
|
||||
// Get thread id
|
||||
u64 get_native_id() const;
|
||||
|
||||
// Add work to the queue
|
||||
void push(shared_ptr<thread_future>);
|
||||
|
||||
private:
|
||||
// Clear task queue (execute unless aborting)
|
||||
void exec();
|
||||
};
|
||||
|
||||
// Collection of global function for current thread
|
||||
@@ -190,14 +228,14 @@ public:
|
||||
// Set current thread name (not recommended)
|
||||
static void set_name(std::string_view name)
|
||||
{
|
||||
g_tls_this_thread->m_tname.store(stx::shared_cptr<std::string>::make(name));
|
||||
g_tls_this_thread->m_tname.store(make_single<std::string>(name));
|
||||
}
|
||||
|
||||
// Set thread name (not recommended)
|
||||
template <typename T>
|
||||
static void set_name(named_thread<T>& thread, std::string_view name)
|
||||
{
|
||||
static_cast<thread_base&>(thread).m_tname.store(stx::shared_cptr<std::string>::make(name));
|
||||
static_cast<thread_base&>(thread).m_tname.store(make_single<std::string>(name));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -213,16 +251,13 @@ public:
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void raw_notify(named_thread<T>& thread)
|
||||
static u64 get_native_id(named_thread<T>& thread)
|
||||
{
|
||||
static_cast<thread_base&>(thread).notify_abort();
|
||||
return static_cast<thread_base&>(thread).get_native_id();
|
||||
}
|
||||
|
||||
// Read current state
|
||||
static inline thread_state state()
|
||||
{
|
||||
return g_tls_this_thread->m_state;
|
||||
}
|
||||
// Read current state, possibly executing some tasks
|
||||
static thread_state state();
|
||||
|
||||
// Wait once with timeout. May spuriously return false.
|
||||
static inline void wait_for(u64 usec, bool alert = true)
|
||||
@@ -236,6 +271,24 @@ public:
|
||||
_wait_for(-1, true);
|
||||
}
|
||||
|
||||
// Wait for both thread sync var and provided atomic var
|
||||
template <atomic_wait::op Op = atomic_wait::op::eq, typename T, typename U>
|
||||
static inline void wait_on(T& wait, U old, u64 usec = -1)
|
||||
{
|
||||
auto _this = g_tls_this_thread;
|
||||
|
||||
if (_this->m_sync.bit_test_reset(2) || _this->m_taskq)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
atomic_wait::list<3> list{};
|
||||
list.set<0, Op>(wait, old);
|
||||
list.set<1>(_this->m_sync, 0, 4 + 1);
|
||||
list.set<2>(_this->m_taskq, nullptr);
|
||||
list.wait(atomic_wait_timeout{usec <= 0xffff'ffff'ffff'ffff / 1000 ? usec * 1000 : 0xffff'ffff'ffff'ffff});
|
||||
}
|
||||
|
||||
// Exit.
|
||||
[[noreturn]] static void emergency_exit(std::string_view reason);
|
||||
|
||||
@@ -263,116 +316,193 @@ public:
|
||||
// Miscellaneous
|
||||
static u64 get_thread_affinity_mask();
|
||||
|
||||
// Get current thread stack addr and size
|
||||
static std::pair<void*, usz> get_thread_stack();
|
||||
|
||||
// Sets the native thread priority and returns it to zero at destructor
|
||||
struct scoped_priority
|
||||
{
|
||||
explicit scoped_priority(int prio)
|
||||
{
|
||||
set_native_priority(prio);
|
||||
}
|
||||
|
||||
scoped_priority(const scoped_priority&) = delete;
|
||||
|
||||
scoped_priority& operator=(const scoped_priority&) = delete;
|
||||
|
||||
~scoped_priority()
|
||||
{
|
||||
set_native_priority(0);
|
||||
}
|
||||
};
|
||||
|
||||
// Get thread ID (works for all threads)
|
||||
static u64 get_tid();
|
||||
|
||||
// Check whether current thread is main thread (usually Qt GUI)
|
||||
static bool is_main();
|
||||
|
||||
private:
|
||||
// Miscellaneous
|
||||
static const u64 process_affinity_mask;
|
||||
};
|
||||
|
||||
// Derived from the callable object Context, possibly a lambda
|
||||
template <class Context>
|
||||
class named_thread final : public Context, result_storage_t<Context>, thread_base
|
||||
// Used internally
|
||||
template <bool Discard, typename Ctx, typename... Args>
|
||||
class thread_future_t : public thread_future, result_storage<Ctx, std::conditional_t<Discard, int, void>, Args...>
|
||||
{
|
||||
using result = result_storage_t<Context>;
|
||||
using thread = thread_base;
|
||||
[[no_unique_address]] decltype(std::make_tuple(std::forward<Args>(std::declval<Args>())...)) m_args;
|
||||
|
||||
// Type-erased thread entry point
|
||||
#ifdef _WIN32
|
||||
static inline uint __stdcall entry_point(void* arg)
|
||||
#else
|
||||
static inline void* entry_point(void* arg)
|
||||
#endif
|
||||
[[no_unique_address]] Ctx m_func;
|
||||
|
||||
using future = thread_future_t;
|
||||
|
||||
public:
|
||||
thread_future_t(Ctx&& func, Args&&... args)
|
||||
: m_args(std::forward<Args>(args)...)
|
||||
, m_func(std::forward<Ctx>(func))
|
||||
{
|
||||
const auto _this = static_cast<named_thread*>(static_cast<thread*>(arg));
|
||||
|
||||
// Perform self-cleanup if necessary
|
||||
if (_this->entry_point())
|
||||
thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf)
|
||||
{
|
||||
delete _this;
|
||||
}
|
||||
const auto _this = static_cast<future*>(tf);
|
||||
|
||||
thread::finalize();
|
||||
return 0;
|
||||
if (!tb) [[unlikely]]
|
||||
{
|
||||
if constexpr (!future::empty && !Discard)
|
||||
{
|
||||
_this->init();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (future::empty || Discard)
|
||||
{
|
||||
std::apply(_this->m_func, std::move(_this->m_args));
|
||||
}
|
||||
else
|
||||
{
|
||||
new (_this->_get()) decltype(auto)(std::apply(_this->m_func, std::move(_this->m_args)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool entry_point()
|
||||
~thread_future_t()
|
||||
{
|
||||
auto tls_error_cb = []()
|
||||
if constexpr (!future::empty && !Discard)
|
||||
{
|
||||
if (!this->exec)
|
||||
{
|
||||
this->destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decltype(auto) get()
|
||||
{
|
||||
while (this->exec)
|
||||
{
|
||||
this->wait();
|
||||
}
|
||||
|
||||
if constexpr (!future::empty && !Discard)
|
||||
{
|
||||
return *this->_get();
|
||||
}
|
||||
}
|
||||
|
||||
decltype(auto) get() const
|
||||
{
|
||||
while (this->exec)
|
||||
{
|
||||
this->wait();
|
||||
}
|
||||
|
||||
if constexpr (!future::empty && !Discard)
|
||||
{
|
||||
return *this->_get();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Derived from the callable object Context, possibly a lambda
|
||||
template <class Context>
|
||||
class named_thread final : public Context, result_storage<Context>, thread_base
|
||||
{
|
||||
using result = result_storage<Context>;
|
||||
using thread = thread_base;
|
||||
|
||||
static u64 entry_point(thread_base* _base)
|
||||
{
|
||||
return static_cast<named_thread*>(_base)->entry_point2();
|
||||
}
|
||||
|
||||
u64 entry_point2()
|
||||
{
|
||||
thread::initialize([]()
|
||||
{
|
||||
if constexpr (!result::empty)
|
||||
{
|
||||
// Construct using default constructor in the case of failure
|
||||
new (static_cast<result*>(static_cast<named_thread*>(thread_ctrl::get_current()))->get()) typename result::type();
|
||||
static_cast<result*>(static_cast<named_thread*>(thread_ctrl::get_current()))->init();
|
||||
}
|
||||
};
|
||||
|
||||
thread::initialize(tls_error_cb, [](const void* data)
|
||||
{
|
||||
const auto _this = thread_ctrl::get_current();
|
||||
|
||||
if (_this->m_state >= thread_state::aborting)
|
||||
{
|
||||
_this->m_state_notifier.store(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!data)
|
||||
{
|
||||
_this->m_state_notifier.release(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
_this->m_state_notifier.store(data);
|
||||
|
||||
if (_this->m_state >= thread_state::aborting)
|
||||
{
|
||||
_this->m_state_notifier.release(nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if constexpr (result::empty)
|
||||
{
|
||||
// No result
|
||||
Context::operator()();
|
||||
if constexpr (std::is_invocable_v<Context>)
|
||||
{
|
||||
Context::operator()();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default event loop
|
||||
while (thread_ctrl::state() != thread_state::aborting)
|
||||
{
|
||||
thread_ctrl::wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Construct the result using placement new (copy elision should happen)
|
||||
new (result::get()) typename result::type(Context::operator()());
|
||||
new (result::_get()) decltype(auto)(Context::operator()());
|
||||
}
|
||||
|
||||
return thread::finalize(thread_state::finished);
|
||||
}
|
||||
|
||||
static inline thread::native_entry trampoline = thread::make_trampoline(entry_point);
|
||||
|
||||
friend class thread_ctrl;
|
||||
|
||||
public:
|
||||
// Default constructor
|
||||
template <bool Valid = std::is_default_constructible_v<Context> && thread_thread_name<Context>(), typename = std::enable_if_t<Valid>>
|
||||
named_thread()
|
||||
: Context()
|
||||
, thread(Context::thread_name)
|
||||
// Forwarding constructor with default name (also potentially the default constructor)
|
||||
template <typename... Args> requires (std::is_constructible_v<Context, Args&&...>) && (NamedThreadName<Context>)
|
||||
named_thread(Args&&... args)
|
||||
: Context(std::forward<Args>(args)...)
|
||||
, thread(trampoline, Context::thread_name)
|
||||
{
|
||||
thread::start(&named_thread::entry_point);
|
||||
thread::start();
|
||||
}
|
||||
|
||||
// Normal forwarding constructor
|
||||
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<Context, Args&&...>>>
|
||||
template <typename... Args> requires (std::is_constructible_v<Context, Args&&...>) && (!NamedThreadName<Context>)
|
||||
named_thread(std::string_view name, Args&&... args)
|
||||
: Context(std::forward<Args>(args)...)
|
||||
, thread(name)
|
||||
, thread(trampoline, name)
|
||||
{
|
||||
thread::start(&named_thread::entry_point);
|
||||
thread::start();
|
||||
}
|
||||
|
||||
// Lambda constructor, also the implicit deduction guide candidate
|
||||
named_thread(std::string_view name, Context&& f)
|
||||
: Context(std::forward<Context>(f))
|
||||
, thread(name)
|
||||
, thread(trampoline, name)
|
||||
{
|
||||
thread::start(&named_thread::entry_point);
|
||||
thread::start();
|
||||
}
|
||||
|
||||
named_thread(const named_thread&) = delete;
|
||||
@@ -386,7 +516,7 @@ public:
|
||||
|
||||
if constexpr (!result::empty)
|
||||
{
|
||||
return *result::get();
|
||||
return *result::_get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,26 +527,99 @@ public:
|
||||
|
||||
if constexpr (!result::empty)
|
||||
{
|
||||
return *result::get();
|
||||
return *result::_get();
|
||||
}
|
||||
}
|
||||
|
||||
// Send command to the thread to invoke directly (references should be passed via std::ref())
|
||||
template <bool Discard = true, typename Arg, typename... Args>
|
||||
auto operator()(Arg&& arg, Args&&... args)
|
||||
{
|
||||
// Overloaded operator() of the Context.
|
||||
constexpr bool v1 = std::is_invocable_v<Context, Arg&&, Args&&...>;
|
||||
|
||||
// Anything invocable, not necessarily involving the Context.
|
||||
constexpr bool v2 = std::is_invocable_v<Arg&&, Args&&...>;
|
||||
|
||||
// Could be pointer to a non-static member function (or data member) of the Context.
|
||||
constexpr bool v3 = std::is_member_pointer_v<std::decay_t<Arg>> && std::is_invocable_v<Arg, Context&, Args&&...>;
|
||||
|
||||
// Only one invocation type shall be valid, otherwise we don't know.
|
||||
static_assert((v1 + v2 + v3) == 1, "Ambiguous or invalid named_thread call.");
|
||||
|
||||
if constexpr (v1)
|
||||
{
|
||||
using future = thread_future_t<Discard, Context&, Arg, Args...>;
|
||||
|
||||
single_ptr<future> target = make_single<future>(*static_cast<Context*>(this), std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||
|
||||
if constexpr (!Discard)
|
||||
{
|
||||
shared_ptr<future> result = std::move(target);
|
||||
|
||||
// Copy result
|
||||
thread::push(result);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move target
|
||||
thread::push(std::move(target));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if constexpr (v2)
|
||||
{
|
||||
using future = thread_future_t<Discard, Arg, Args...>;
|
||||
|
||||
single_ptr<future> target = make_single<future>(std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||
|
||||
if constexpr (!Discard)
|
||||
{
|
||||
shared_ptr<future> result = std::move(target);
|
||||
thread::push(result);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
thread::push(std::move(target));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if constexpr (v3)
|
||||
{
|
||||
using future = thread_future_t<Discard, Arg, Context&, Args...>;
|
||||
|
||||
single_ptr<future> target = make_single<future>(std::forward<Arg>(arg), std::ref(*static_cast<Context*>(this)), std::forward<Args>(args)...);
|
||||
|
||||
if constexpr (!Discard)
|
||||
{
|
||||
shared_ptr<future> result = std::move(target);
|
||||
thread::push(result);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
thread::push(std::move(target));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Access thread state
|
||||
operator thread_state() const
|
||||
{
|
||||
return thread::m_state.load();
|
||||
return static_cast<thread_state>(thread::m_sync.load() & 3);
|
||||
}
|
||||
|
||||
// Try to abort by assigning thread_state::aborting (UB if assigning different state)
|
||||
named_thread& operator=(thread_state s)
|
||||
{
|
||||
ASSUME(s == thread_state::aborting);
|
||||
|
||||
if (s == thread_state::aborting && thread::m_state.compare_and_swap_test(thread_state::created, s))
|
||||
if (s == thread_state::aborting && thread::m_sync.fetch_op([](u64& v){ return !(v & 3) && (v |= 1); }).second)
|
||||
{
|
||||
if (s == thread_state::aborting)
|
||||
{
|
||||
thread::notify_abort();
|
||||
thread::m_sync.notify_one(1);
|
||||
}
|
||||
|
||||
if constexpr (std::is_base_of_v<need_wakeup, Context>)
|
||||
@@ -433,7 +636,7 @@ public:
|
||||
{
|
||||
// Assign aborting state forcefully
|
||||
operator=(thread_state::aborting);
|
||||
thread::join();
|
||||
thread::join(true);
|
||||
|
||||
if constexpr (!result::empty)
|
||||
{
|
||||
|
||||
+11
-11
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
@@ -8,8 +8,8 @@ class Timer
|
||||
{
|
||||
private:
|
||||
bool m_stopped;
|
||||
std::chrono::steady_clock::time_point m_start;
|
||||
std::chrono::steady_clock::time_point m_end;
|
||||
steady_clock::time_point m_start;
|
||||
steady_clock::time_point m_end;
|
||||
|
||||
public:
|
||||
Timer() : m_stopped(false)
|
||||
@@ -19,42 +19,42 @@ public:
|
||||
void Start()
|
||||
{
|
||||
m_stopped = false;
|
||||
m_start = std::chrono::steady_clock::now();
|
||||
m_start = steady_clock::now();
|
||||
}
|
||||
|
||||
void Stop()
|
||||
{
|
||||
m_stopped = true;
|
||||
m_end = std::chrono::steady_clock::now();
|
||||
m_end = steady_clock::now();
|
||||
}
|
||||
|
||||
double GetElapsedTimeInSec() const
|
||||
{
|
||||
return double(GetElapsedTimeInMicroSec()) / 1000000.0;
|
||||
return static_cast<double>(GetElapsedTimeInMicroSec()) / 1000000.0;
|
||||
}
|
||||
|
||||
double GetElapsedTimeInMilliSec() const
|
||||
{
|
||||
return double(GetElapsedTimeInMicroSec()) / 1000.0;
|
||||
return static_cast<double>(GetElapsedTimeInMicroSec()) / 1000.0;
|
||||
}
|
||||
|
||||
u64 GetElapsedTimeInMicroSec() const
|
||||
{
|
||||
std::chrono::steady_clock::time_point now = m_stopped ? m_end : std::chrono::steady_clock::now();
|
||||
const steady_clock::time_point now = m_stopped ? m_end : steady_clock::now();
|
||||
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(now - m_start).count();
|
||||
}
|
||||
|
||||
u64 GetElapsedTimeInNanoSec() const
|
||||
{
|
||||
std::chrono::steady_clock::time_point now = m_stopped ? m_end : std::chrono::steady_clock::now();
|
||||
const steady_clock::time_point now = m_stopped ? m_end : steady_clock::now();
|
||||
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(now - m_start).count();
|
||||
}
|
||||
|
||||
u64 GetMsSince(std::chrono::steady_clock::time_point timestamp)
|
||||
u64 GetMsSince(steady_clock::time_point timestamp) const
|
||||
{
|
||||
std::chrono::steady_clock::time_point now = m_stopped ? m_end : std::chrono::steady_clock::now();
|
||||
const steady_clock::time_point now = m_stopped ? m_end : steady_clock::now();
|
||||
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(now - timestamp).count();
|
||||
}
|
||||
|
||||
@@ -1,312 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
#include "util/logs.hpp"
|
||||
#include "VirtualMemory.h"
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#ifdef __NR_memfd_create
|
||||
#elif __x86_64__
|
||||
#define __NR_memfd_create 319
|
||||
#elif __aarch64__
|
||||
#define __NR_memfd_create 279
|
||||
#endif
|
||||
|
||||
static int memfd_create_(const char *name, uint flags)
|
||||
{
|
||||
return syscall(__NR_memfd_create, name, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace utils
|
||||
{
|
||||
// Convert memory protection (internal)
|
||||
static auto operator +(protection prot)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD _prot = PAGE_NOACCESS;
|
||||
switch (prot)
|
||||
{
|
||||
case protection::rw: _prot = PAGE_READWRITE; break;
|
||||
case protection::ro: _prot = PAGE_READONLY; break;
|
||||
case protection::no: break;
|
||||
case protection::wx: _prot = PAGE_EXECUTE_READWRITE; break;
|
||||
case protection::rx: _prot = PAGE_EXECUTE_READ; break;
|
||||
}
|
||||
#else
|
||||
int _prot = PROT_NONE;
|
||||
switch (prot)
|
||||
{
|
||||
case protection::rw: _prot = PROT_READ | PROT_WRITE; break;
|
||||
case protection::ro: _prot = PROT_READ; break;
|
||||
case protection::no: break;
|
||||
case protection::wx: _prot = PROT_READ | PROT_WRITE | PROT_EXEC; break;
|
||||
case protection::rx: _prot = PROT_READ | PROT_EXEC; break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return _prot;
|
||||
}
|
||||
|
||||
void* memory_reserve(std::size_t size, void* use_addr)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return ::VirtualAlloc(use_addr, size, MEM_RESERVE, PAGE_NOACCESS);
|
||||
#else
|
||||
if (use_addr && reinterpret_cast<uptr>(use_addr) % 0x10000)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!use_addr)
|
||||
{
|
||||
// Hack: Ensure aligned 64k allocations
|
||||
size += 0x10000;
|
||||
}
|
||||
|
||||
auto ptr = ::mmap(use_addr, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
|
||||
if (ptr == reinterpret_cast<void*>(-1))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (use_addr && ptr != use_addr)
|
||||
{
|
||||
::munmap(ptr, size);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!use_addr && ptr)
|
||||
{
|
||||
// Continuation of the hack above
|
||||
const auto misalign = reinterpret_cast<uptr>(ptr) % 0x10000;
|
||||
::munmap(ptr, 0x10000 - misalign);
|
||||
|
||||
if (misalign)
|
||||
{
|
||||
::munmap(static_cast<u8*>(ptr) + size - misalign, misalign);
|
||||
}
|
||||
|
||||
ptr = static_cast<u8*>(ptr) + (0x10000 - misalign);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void memory_commit(void* pointer, std::size_t size, protection prot)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
verify(HERE), ::VirtualAlloc(pointer, size, MEM_COMMIT, +prot);
|
||||
#else
|
||||
const u64 ptr64 = reinterpret_cast<u64>(pointer);
|
||||
verify(HERE), ::mprotect(reinterpret_cast<void*>(ptr64 & -4096), size + (ptr64 & 4095), +prot) != -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void memory_decommit(void* pointer, std::size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
verify(HERE), ::VirtualFree(pointer, size, MEM_DECOMMIT);
|
||||
#else
|
||||
verify(HERE), ::mmap(pointer, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0) != reinterpret_cast<void*>(-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void memory_reset(void* pointer, std::size_t size, protection prot)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
memory_decommit(pointer, size);
|
||||
memory_commit(pointer, size, prot);
|
||||
#else
|
||||
verify(HERE), ::mmap(pointer, size, +prot, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0) != reinterpret_cast<void*>(-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void memory_release(void* pointer, std::size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
verify(HERE), ::VirtualFree(pointer, 0, MEM_RELEASE);
|
||||
#else
|
||||
verify(HERE), ::munmap(pointer, size) != -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void memory_protect(void* pointer, std::size_t size, protection prot)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
for (u64 addr = reinterpret_cast<u64>(pointer), end = addr + size; addr < end;)
|
||||
{
|
||||
const u64 boundary = (addr + 0x10000) & -0x10000;
|
||||
const u64 block_size = std::min(boundary, end) - addr;
|
||||
|
||||
DWORD old;
|
||||
if (!::VirtualProtect(reinterpret_cast<LPVOID>(addr), block_size, +prot, &old))
|
||||
{
|
||||
fmt::throw_exception("VirtualProtect failed (%p, 0x%x, addr=0x%x, error=%#x)", pointer, size, addr, GetLastError());
|
||||
}
|
||||
|
||||
// Next region
|
||||
addr += block_size;
|
||||
}
|
||||
#else
|
||||
const u64 ptr64 = reinterpret_cast<u64>(pointer);
|
||||
verify(HERE), ::mprotect(reinterpret_cast<void*>(ptr64 & -4096), size + (ptr64 & 4095), +prot) != -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
shm::shm(u32 size, u32 flags)
|
||||
: m_size(::align(size, 0x10000))
|
||||
, m_flags(flags)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
m_handle = ::CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, m_size, NULL);
|
||||
verify(HERE), m_handle != INVALID_HANDLE_VALUE;
|
||||
#elif __linux__
|
||||
m_file = ::memfd_create_("", 0);
|
||||
verify(HERE), m_file >= 0;
|
||||
verify(HERE), ::ftruncate(m_file, m_size) >= 0;
|
||||
#else
|
||||
while ((m_file = ::shm_open("/rpcs3-mem1", O_RDWR | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) == -1)
|
||||
{
|
||||
if (errno == EMFILE)
|
||||
{
|
||||
fmt::throw_exception("Too many open files. Raise the limit and try again.");
|
||||
}
|
||||
|
||||
verify(HERE), errno == EEXIST;
|
||||
}
|
||||
|
||||
verify(HERE), ::shm_unlink("/rpcs3-mem1") >= 0;
|
||||
verify(HERE), ::ftruncate(m_file, m_size) >= 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
shm::~shm()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::CloseHandle(m_handle);
|
||||
#else
|
||||
::close(m_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
u8* shm::map(void* ptr, protection prot) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD access = FILE_MAP_WRITE;
|
||||
switch (prot)
|
||||
{
|
||||
case protection::rw:
|
||||
case protection::ro:
|
||||
case protection::no:
|
||||
break;
|
||||
case protection::wx:
|
||||
case protection::rx:
|
||||
access |= FILE_MAP_EXECUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (auto ret = static_cast<u8*>(::MapViewOfFileEx(m_handle, access, 0, 0, m_size, ptr)))
|
||||
{
|
||||
if (prot != protection::rw && prot != protection::wx)
|
||||
{
|
||||
DWORD old;
|
||||
if (!::VirtualProtect(ret, m_size, +prot, &old))
|
||||
{
|
||||
::UnmapViewOfFile(ret);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
#else
|
||||
const u64 ptr64 = reinterpret_cast<u64>(ptr);
|
||||
return static_cast<u8*>(::mmap(reinterpret_cast<void*>(ptr64 & -0x10000), m_size, +prot, MAP_SHARED | (ptr ? MAP_FIXED : 0), m_file, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
u8* shm::map_critical(void* ptr, protection prot)
|
||||
{
|
||||
const auto target = reinterpret_cast<u8*>(reinterpret_cast<u64>(ptr) & -0x10000);
|
||||
|
||||
#ifdef _WIN32
|
||||
::MEMORY_BASIC_INFORMATION mem;
|
||||
if (!::VirtualQuery(target, &mem, sizeof(mem)) || mem.State != MEM_RESERVE || !::VirtualFree(mem.AllocationBase, 0, MEM_RELEASE))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto base = (u8*)mem.AllocationBase;
|
||||
const auto size = mem.RegionSize + (target - base);
|
||||
|
||||
if (base < target && !::VirtualAlloc(base, target - base, MEM_RESERVE, PAGE_NOACCESS))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (target + m_size < base + size && !::VirtualAlloc(target + m_size, base + size - target - m_size, MEM_RESERVE, PAGE_NOACCESS))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return this->map(target, prot);
|
||||
}
|
||||
|
||||
void shm::unmap(void* ptr) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::UnmapViewOfFile(ptr);
|
||||
#else
|
||||
::munmap(ptr, m_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void shm::unmap_critical(void* ptr)
|
||||
{
|
||||
const auto target = reinterpret_cast<u8*>(reinterpret_cast<u64>(ptr) & -0x10000);
|
||||
|
||||
this->unmap(target);
|
||||
|
||||
#ifdef _WIN32
|
||||
::MEMORY_BASIC_INFORMATION mem, mem2;
|
||||
if (!::VirtualQuery(target - 1, &mem, sizeof(mem)) || !::VirtualQuery(target + m_size, &mem2, sizeof(mem2)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mem.State == MEM_RESERVE && !::VirtualFree(mem.AllocationBase, 0, MEM_RELEASE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mem2.State == MEM_RESERVE && !::VirtualFree(mem2.AllocationBase, 0, MEM_RELEASE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto size1 = mem.State == MEM_RESERVE ? target - (u8*)mem.AllocationBase : 0;
|
||||
const auto size2 = mem2.State == MEM_RESERVE ? mem2.RegionSize : 0;
|
||||
|
||||
if (!::VirtualAlloc(mem.State == MEM_RESERVE ? mem.AllocationBase : target, m_size + size1 + size2, MEM_RESERVE, PAGE_NOACCESS))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
+26
-59
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
#include "StrFmt.h"
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace utils
|
||||
@@ -65,7 +66,6 @@ namespace utils
|
||||
public:
|
||||
// Constructors
|
||||
constexpr address_range() = default;
|
||||
constexpr address_range(const address_range &other) : start(other.start), end(other.end) {}
|
||||
|
||||
static constexpr address_range start_length(u32 _start, u32 _length)
|
||||
{
|
||||
@@ -92,7 +92,7 @@ namespace utils
|
||||
void set_length(const u32 new_length)
|
||||
{
|
||||
end = start + new_length - 1;
|
||||
ASSERT(valid());
|
||||
ensure(valid());
|
||||
}
|
||||
|
||||
u32 next_address() const
|
||||
@@ -239,16 +239,11 @@ namespace utils
|
||||
}
|
||||
|
||||
// Comparison Operators
|
||||
bool operator ==(const address_range &other) const
|
||||
bool operator ==(const address_range& other) const
|
||||
{
|
||||
return (start == other.start && end == other.end);
|
||||
}
|
||||
|
||||
bool operator !=(const address_range &other) const
|
||||
{
|
||||
return (start != other.start || end != other.end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug
|
||||
*/
|
||||
@@ -272,17 +267,17 @@ namespace utils
|
||||
class address_range_vector
|
||||
{
|
||||
public:
|
||||
using vector_type = typename std::vector<address_range>;
|
||||
using iterator = typename vector_type::iterator;
|
||||
using const_iterator = typename vector_type::const_iterator;
|
||||
using size_type = typename vector_type::size_type;
|
||||
using vector_type = std::vector<address_range>;
|
||||
using iterator = vector_type::iterator;
|
||||
using const_iterator = vector_type::const_iterator;
|
||||
using size_type = vector_type::size_type;
|
||||
|
||||
private:
|
||||
vector_type data;
|
||||
|
||||
public:
|
||||
// Wrapped functions
|
||||
inline void reserve(size_t nr) { data.reserve(nr); }
|
||||
inline void reserve(usz nr) { data.reserve(nr); }
|
||||
inline void clear() { data.clear(); }
|
||||
inline size_type size() const { return data.size(); }
|
||||
inline bool empty() const { return data.empty(); }
|
||||
@@ -456,9 +451,9 @@ namespace utils
|
||||
// Will fail if ranges within the vector overlap our touch each-other
|
||||
bool check_consistency() const
|
||||
{
|
||||
size_t _size = data.size();
|
||||
const usz _size = data.size();
|
||||
|
||||
for (size_t i = 0; i < _size; ++i)
|
||||
for (usz i = 0; i < _size; ++i)
|
||||
{
|
||||
const auto &r1 = data[i];
|
||||
if (!r1.valid())
|
||||
@@ -466,7 +461,7 @@ namespace utils
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t j = i + 1; j < _size; ++j)
|
||||
for (usz j = i + 1; j < _size; ++j)
|
||||
{
|
||||
const auto &r2 = data[j];
|
||||
if (!r2.valid())
|
||||
@@ -486,20 +481,10 @@ namespace utils
|
||||
// Test for overlap with a given range
|
||||
bool overlaps(const address_range &range) const
|
||||
{
|
||||
for (const address_range ¤t : data)
|
||||
return std::any_of(data.cbegin(), data.cend(), [&range](const address_range& cur)
|
||||
{
|
||||
if (!current.valid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current.overlaps(range))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return cur.valid() && cur.overlaps(range);
|
||||
});
|
||||
}
|
||||
|
||||
// Test for overlap with a given address_range vector
|
||||
@@ -531,37 +516,19 @@ namespace utils
|
||||
// Test if a given range is fully contained inside this vector
|
||||
bool contains(const address_range &range) const
|
||||
{
|
||||
for (const address_range &cur : *this)
|
||||
return std::any_of(this->begin(), this->end(), [&range](const address_range& cur)
|
||||
{
|
||||
if (!cur.valid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (range.inside(cur))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return cur.valid() && cur.inside(range);
|
||||
});
|
||||
}
|
||||
|
||||
// Test if all ranges in this vector are full contained inside a specific range
|
||||
bool inside(const address_range &range) const
|
||||
{
|
||||
for (const address_range &cur : *this)
|
||||
return std::all_of(this->begin(), this->end(), [&range](const address_range& cur)
|
||||
{
|
||||
if (!cur.valid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cur.inside(range))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return !cur.valid() || cur.inside(range);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -582,15 +549,15 @@ namespace utils
|
||||
|
||||
namespace std
|
||||
{
|
||||
static_assert(sizeof(size_t) >= 2 * sizeof(u32), "size_t must be at least twice the size of u32");
|
||||
static_assert(sizeof(usz) >= 2 * sizeof(u32), "usz must be at least twice the size of u32");
|
||||
|
||||
template <>
|
||||
struct hash<utils::address_range>
|
||||
{
|
||||
std::size_t operator()(const utils::address_range& k) const
|
||||
usz operator()(const utils::address_range& k) const
|
||||
{
|
||||
// we can guarantee a unique hash since our type is 64 bits and size_t as well
|
||||
return (size_t{ k.start } << 32) | size_t{ k.end };
|
||||
// we can guarantee a unique hash since our type is 64 bits and usz as well
|
||||
return (usz{ k.start } << 32) | usz{ k.end };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
-279
@@ -1,279 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
extern bool g_use_rtm;
|
||||
extern u64 g_rtm_tx_limit1;
|
||||
|
||||
namespace utils
|
||||
{
|
||||
// Transaction helper (result = pair of success and op result, or just bool)
|
||||
template <typename F, typename R = std::invoke_result_t<F>>
|
||||
inline auto tx_start(F op)
|
||||
{
|
||||
uint status = -1;
|
||||
|
||||
for (auto stamp0 = __rdtsc(), stamp1 = stamp0; g_use_rtm && stamp1 - stamp0 <= g_rtm_tx_limit1; stamp1 = __rdtsc())
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
__asm__ goto ("xbegin %l[retry];" ::: "memory" : retry);
|
||||
#else
|
||||
status = _xbegin();
|
||||
|
||||
if (status != _XBEGIN_STARTED) [[unlikely]]
|
||||
{
|
||||
goto retry;
|
||||
}
|
||||
#endif
|
||||
|
||||
if constexpr (std::is_void_v<R>)
|
||||
{
|
||||
std::invoke(op);
|
||||
#ifndef _MSC_VER
|
||||
__asm__ volatile ("xend;" ::: "memory");
|
||||
#else
|
||||
_xend();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto result = std::invoke(op);
|
||||
#ifndef _MSC_VER
|
||||
__asm__ volatile ("xend;" ::: "memory");
|
||||
#else
|
||||
_xend();
|
||||
#endif
|
||||
return std::make_pair(true, std::move(result));
|
||||
}
|
||||
|
||||
retry:
|
||||
#ifndef _MSC_VER
|
||||
__asm__ volatile ("movl %%eax, %0;" : "=r" (status) :: "memory");
|
||||
#endif
|
||||
if (!status) [[unlikely]]
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (std::is_void_v<R>)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::make_pair(false, R());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Rotate helpers
|
||||
#if defined(__GNUG__)
|
||||
|
||||
inline u8 rol8(u8 x, u8 n)
|
||||
{
|
||||
#if __has_builtin(__builtin_rotateleft8)
|
||||
return __builtin_rotateleft8(x, n);
|
||||
#else
|
||||
u8 result = x;
|
||||
__asm__("rolb %[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline u8 ror8(u8 x, u8 n)
|
||||
{
|
||||
#if __has_builtin(__builtin_rotateright8)
|
||||
return __builtin_rotateright8(x, n);
|
||||
#else
|
||||
u8 result = x;
|
||||
__asm__("rorb %[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline u16 rol16(u16 x, u16 n)
|
||||
{
|
||||
#if __has_builtin(__builtin_rotateleft16)
|
||||
return __builtin_rotateleft16(x, n);
|
||||
#else
|
||||
u16 result = x;
|
||||
__asm__("rolw %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline u16 ror16(u16 x, u16 n)
|
||||
{
|
||||
#if __has_builtin(__builtin_rotateright16)
|
||||
return __builtin_rotateright16(x, n);
|
||||
#else
|
||||
u16 result = x;
|
||||
__asm__("rorw %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline u32 rol32(u32 x, u32 n)
|
||||
{
|
||||
#if __has_builtin(__builtin_rotateleft32)
|
||||
return __builtin_rotateleft32(x, n);
|
||||
#else
|
||||
u32 result = x;
|
||||
__asm__("roll %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline u32 ror32(u32 x, u32 n)
|
||||
{
|
||||
#if __has_builtin(__builtin_rotateright32)
|
||||
return __builtin_rotateright32(x, n);
|
||||
#else
|
||||
u32 result = x;
|
||||
__asm__("rorl %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline u64 rol64(u64 x, u64 n)
|
||||
{
|
||||
#if __has_builtin(__builtin_rotateleft64)
|
||||
return __builtin_rotateleft64(x, n);
|
||||
#else
|
||||
u64 result = x;
|
||||
__asm__("rolq %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline u64 ror64(u64 x, u64 n)
|
||||
{
|
||||
#if __has_builtin(__builtin_rotateright64)
|
||||
return __builtin_rotateright64(x, n);
|
||||
#else
|
||||
u64 result = x;
|
||||
__asm__("rorq %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
constexpr u64 umulh64(u64 a, u64 b)
|
||||
{
|
||||
const __uint128_t x = a;
|
||||
const __uint128_t y = b;
|
||||
return (x * y) >> 64;
|
||||
}
|
||||
|
||||
constexpr s64 mulh64(s64 a, s64 b)
|
||||
{
|
||||
const __int128_t x = a;
|
||||
const __int128_t y = b;
|
||||
return (x * y) >> 64;
|
||||
}
|
||||
|
||||
constexpr s64 div128(s64 high, s64 low, s64 divisor, s64* remainder = nullptr)
|
||||
{
|
||||
const __int128_t x = (__uint128_t{u64(high)} << 64) | u64(low);
|
||||
const __int128_t r = x / divisor;
|
||||
|
||||
if (remainder)
|
||||
{
|
||||
*remainder = x % divisor;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
constexpr u64 udiv128(u64 high, u64 low, u64 divisor, u64* remainder = nullptr)
|
||||
{
|
||||
const __uint128_t x = (__uint128_t{high} << 64) | low;
|
||||
const __uint128_t r = x / divisor;
|
||||
|
||||
if (remainder)
|
||||
{
|
||||
*remainder = x % divisor;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
inline u8 rol8(u8 x, u8 n)
|
||||
{
|
||||
return _rotl8(x, n);
|
||||
}
|
||||
|
||||
inline u8 ror8(u8 x, u8 n)
|
||||
{
|
||||
return _rotr8(x, n);
|
||||
}
|
||||
|
||||
inline u16 rol16(u16 x, u16 n)
|
||||
{
|
||||
return _rotl16(x, (u8)n);
|
||||
}
|
||||
|
||||
inline u16 ror16(u16 x, u16 n)
|
||||
{
|
||||
return _rotr16(x, (u8)n);
|
||||
}
|
||||
|
||||
inline u32 rol32(u32 x, u32 n)
|
||||
{
|
||||
return _rotl(x, (int)n);
|
||||
}
|
||||
|
||||
inline u32 ror32(u32 x, u32 n)
|
||||
{
|
||||
return _rotr(x, (int)n);
|
||||
}
|
||||
|
||||
inline u64 rol64(u64 x, u64 n)
|
||||
{
|
||||
return _rotl64(x, (int)n);
|
||||
}
|
||||
|
||||
inline u64 ror64(u64 x, u64 n)
|
||||
{
|
||||
return _rotr64(x, (int)n);
|
||||
}
|
||||
|
||||
inline u64 umulh64(u64 x, u64 y)
|
||||
{
|
||||
return __umulh(x, y);
|
||||
}
|
||||
|
||||
inline s64 mulh64(s64 x, s64 y)
|
||||
{
|
||||
return __mulh(x, y);
|
||||
}
|
||||
|
||||
inline s64 div128(s64 high, s64 low, s64 divisor, s64* remainder = nullptr)
|
||||
{
|
||||
s64 rem;
|
||||
s64 r = _div128(high, low, divisor, &rem);
|
||||
|
||||
if (remainder)
|
||||
{
|
||||
*remainder = rem;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline u64 udiv128(u64 high, u64 low, u64 divisor, u64* remainder = nullptr)
|
||||
{
|
||||
u64 rem;
|
||||
u64 r = _udiv128(high, low, divisor, &rem);
|
||||
|
||||
if (remainder)
|
||||
{
|
||||
*remainder = rem;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
} // namespace utils
|
||||
+87
-165
@@ -1,15 +1,13 @@
|
||||
#include "bin_patch.h"
|
||||
#include "bin_patch.h"
|
||||
#include "File.h"
|
||||
#include "Config.h"
|
||||
#include "version.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
LOG_CHANNEL(patch_log);
|
||||
#include "util/types.hpp"
|
||||
#include "util/endian.hpp"
|
||||
|
||||
namespace config_key
|
||||
{
|
||||
static const std::string enable_legacy_patches = "Enable Legacy Patches";
|
||||
}
|
||||
LOG_CHANNEL(patch_log, "PAT");
|
||||
|
||||
template <>
|
||||
void fmt_class_string<YAML::NodeType::value>::format(std::string& out, u64 arg)
|
||||
@@ -46,9 +44,12 @@ void fmt_class_string<patch_type>::format(std::string& out, u64 arg)
|
||||
case patch_type::bef64: return "bef64";
|
||||
case patch_type::be16: return "be16";
|
||||
case patch_type::be32: return "be32";
|
||||
case patch_type::bd32: return "bd32";
|
||||
case patch_type::be64: return "be64";
|
||||
case patch_type::bd64: return "bd64";
|
||||
case patch_type::lef32: return "lef32";
|
||||
case patch_type::lef64: return "lef64";
|
||||
case patch_type::utf8: return "utf8";
|
||||
}
|
||||
|
||||
return unknown;
|
||||
@@ -125,16 +126,14 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
|
||||
}
|
||||
|
||||
// Load patch config to determine which patches are enabled
|
||||
bool enable_legacy_patches = false;
|
||||
patch_map patch_config;
|
||||
|
||||
if (!importing)
|
||||
{
|
||||
patch_config = load_config(enable_legacy_patches);
|
||||
patch_config = load_config();
|
||||
}
|
||||
|
||||
std::string version;
|
||||
bool is_legacy_patch = false;
|
||||
|
||||
if (const auto version_node = root[patch_key::version])
|
||||
{
|
||||
@@ -150,17 +149,12 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
|
||||
// We don't need the Version node in local memory anymore
|
||||
root.remove(patch_key::version);
|
||||
}
|
||||
else if (importing)
|
||||
else
|
||||
{
|
||||
append_log_message(log_messages, fmt::format("Error: No '%s' entry found. Patch engine version = %s (file: %s)", patch_key::version, patch_engine_version, path));
|
||||
patch_log.error("No '%s' entry found. Patch engine version = %s (file: %s)", patch_key::version, patch_engine_version, path);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
patch_log.warning("Patch engine version %s: Reading legacy patch file %s", patch_engine_version, path);
|
||||
is_legacy_patch = true;
|
||||
}
|
||||
|
||||
bool is_valid = true;
|
||||
|
||||
@@ -169,30 +163,6 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
|
||||
{
|
||||
const auto& main_key = pair.first.Scalar();
|
||||
|
||||
// Use old logic and yaml layout if this is a legacy patch
|
||||
if (is_legacy_patch)
|
||||
{
|
||||
struct patch_info info{};
|
||||
info.hash = main_key;
|
||||
info.is_enabled = enable_legacy_patches;
|
||||
info.is_legacy = true;
|
||||
info.source_path = path;
|
||||
|
||||
if (!read_patch_node(info, pair.second, root, log_messages))
|
||||
{
|
||||
is_valid = false;
|
||||
}
|
||||
|
||||
// Find or create an entry matching the key/hash in our map
|
||||
auto& container = patches_map[main_key];
|
||||
container.hash = main_key;
|
||||
container.is_legacy = true;
|
||||
container.patch_info_map["legacy"] = info;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Use new logic and yaml layout
|
||||
|
||||
if (const auto yml_type = pair.second.Type(); yml_type != YAML::NodeType::Map)
|
||||
{
|
||||
append_log_message(log_messages, fmt::format("Error: Skipping key %s: expected Map, found %s", main_key, yml_type));
|
||||
@@ -209,7 +179,6 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
|
||||
|
||||
// Find or create an entry matching the key/hash in our map
|
||||
auto& container = patches_map[main_key];
|
||||
container.is_legacy = false;
|
||||
container.hash = main_key;
|
||||
container.version = version;
|
||||
|
||||
@@ -428,35 +397,6 @@ bool patch_engine::add_patch_data(YAML::Node node, patch_info& info, u32 modifie
|
||||
{
|
||||
// Special syntax: anchors (named sequence)
|
||||
|
||||
// Most legacy patches don't use the anchor syntax correctly, so try to sanitize it.
|
||||
if (info.is_legacy)
|
||||
{
|
||||
if (const auto yml_type = addr_node.Type(); yml_type == YAML::NodeType::Scalar)
|
||||
{
|
||||
if (!root)
|
||||
{
|
||||
patch_log.fatal("Trying to parse legacy patch with invalid root."); // Sanity Check
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto anchor = addr_node.Scalar();
|
||||
const auto anchor_node = root[anchor];
|
||||
|
||||
if (anchor_node)
|
||||
{
|
||||
addr_node = anchor_node;
|
||||
append_log_message(log_messages, fmt::format("Incorrect anchor syntax found in legacy patch: %s (key: %s)", anchor, info.hash));
|
||||
patch_log.warning("Incorrect anchor syntax found in legacy patch: %s (key: %s)", anchor, info.hash);
|
||||
}
|
||||
else
|
||||
{
|
||||
append_log_message(log_messages, fmt::format("Anchor not found in legacy patch: %s (key: %s)", anchor, info.hash));
|
||||
patch_log.error("Anchor not found in legacy patch: %s (key: %s)", anchor, info.hash);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the anchor was resolved.
|
||||
if (const auto yml_type = addr_node.Type(); yml_type != YAML::NodeType::Sequence)
|
||||
{
|
||||
@@ -490,6 +430,10 @@ bool patch_engine::add_patch_data(YAML::Node node, patch_info& info, u32 modifie
|
||||
|
||||
switch (p_data.type)
|
||||
{
|
||||
case patch_type::utf8:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case patch_type::bef32:
|
||||
case patch_type::lef32:
|
||||
case patch_type::bef64:
|
||||
@@ -524,7 +468,7 @@ bool patch_engine::read_patch_node(patch_info& info, YAML::Node node, const YAML
|
||||
if (!node)
|
||||
{
|
||||
append_log_message(log_messages, fmt::format("Skipping invalid patch node %s. (key: %s)", info.description, info.hash));
|
||||
patch_log.error("Skipping invalid patch node %s. (key: %s)" HERE, info.description, info.hash);
|
||||
patch_log.error("Skipping invalid patch node %s. (key: %s)", info.description, info.hash);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -550,10 +494,7 @@ bool patch_engine::read_patch_node(patch_info& info, YAML::Node node, const YAML
|
||||
|
||||
void patch_engine::append_global_patches()
|
||||
{
|
||||
// Legacy patch.yml
|
||||
load(m_map, fs::get_config_dir() + "patch.yml");
|
||||
|
||||
// New patch.yml
|
||||
// Regular patch.yml
|
||||
load(m_map, get_patches_path() + "patch.yml");
|
||||
|
||||
// Imported patch.yml
|
||||
@@ -567,45 +508,30 @@ void patch_engine::append_title_patches(const std::string& title_id)
|
||||
return;
|
||||
}
|
||||
|
||||
// Legacy patch.yml
|
||||
load(m_map, fs::get_config_dir() + "data/" + title_id + "/patch.yml");
|
||||
|
||||
// New patch.yml
|
||||
// Regular patch.yml
|
||||
load(m_map, get_patches_path() + title_id + "_patch.yml");
|
||||
}
|
||||
|
||||
std::size_t patch_engine::apply(const std::string& name, u8* dst)
|
||||
static std::basic_string<u32> apply_modification(const patch_engine::patch_info& patch, u8* dst, u32 filesz, u32 min_addr)
|
||||
{
|
||||
return apply_patch<false>(name, dst, 0, 0);
|
||||
}
|
||||
|
||||
std::size_t patch_engine::apply_with_ls_check(const std::string& name, u8* dst, u32 filesz, u32 ls_addr)
|
||||
{
|
||||
return apply_patch<true>(name, dst, filesz, ls_addr);
|
||||
}
|
||||
|
||||
template <bool check_local_storage>
|
||||
static std::size_t apply_modification(const patch_engine::patch_info& patch, u8* dst, u32 filesz, u32 ls_addr)
|
||||
{
|
||||
size_t applied = 0;
|
||||
std::basic_string<u32> applied;
|
||||
|
||||
for (const auto& p : patch.data_list)
|
||||
{
|
||||
u32 offset = p.offset;
|
||||
|
||||
if constexpr (check_local_storage)
|
||||
if (offset < min_addr || offset - min_addr >= filesz)
|
||||
{
|
||||
if (offset < ls_addr || offset >= (ls_addr + filesz))
|
||||
{
|
||||
// This patch is out of range for this segment
|
||||
continue;
|
||||
}
|
||||
|
||||
offset -= ls_addr;
|
||||
// This patch is out of range for this segment
|
||||
continue;
|
||||
}
|
||||
|
||||
offset -= min_addr;
|
||||
|
||||
auto ptr = dst + offset;
|
||||
|
||||
u32 resval = umax;
|
||||
|
||||
switch (p.type)
|
||||
{
|
||||
case patch_type::invalid:
|
||||
@@ -621,77 +547,113 @@ static std::size_t apply_modification(const patch_engine::patch_info& patch, u8*
|
||||
}
|
||||
case patch_type::le16:
|
||||
{
|
||||
*reinterpret_cast<le_t<u16, 1>*>(ptr) = static_cast<u16>(p.value.long_value);
|
||||
le_t<u16> val = static_cast<u16>(p.value.long_value);
|
||||
std::memcpy(ptr, &val, sizeof(val));
|
||||
break;
|
||||
}
|
||||
case patch_type::le32:
|
||||
{
|
||||
*reinterpret_cast<le_t<u32, 1>*>(ptr) = static_cast<u32>(p.value.long_value);
|
||||
le_t<u32> val = static_cast<u32>(p.value.long_value);
|
||||
std::memcpy(ptr, &val, sizeof(val));
|
||||
break;
|
||||
}
|
||||
case patch_type::lef32:
|
||||
{
|
||||
*reinterpret_cast<le_t<u32, 1>*>(ptr) = std::bit_cast<u32, f32>(static_cast<f32>(p.value.double_value));
|
||||
le_t<f32> val = static_cast<f32>(p.value.double_value);
|
||||
std::memcpy(ptr, &val, sizeof(val));
|
||||
break;
|
||||
}
|
||||
case patch_type::le64:
|
||||
{
|
||||
*reinterpret_cast<le_t<u64, 1>*>(ptr) = static_cast<u64>(p.value.long_value);
|
||||
le_t<u64> val = static_cast<u64>(p.value.long_value);
|
||||
std::memcpy(ptr, &val, sizeof(val));
|
||||
break;
|
||||
}
|
||||
case patch_type::lef64:
|
||||
{
|
||||
*reinterpret_cast<le_t<u64, 1>*>(ptr) = std::bit_cast<u64, f64>(p.value.double_value);
|
||||
le_t<f64> val = p.value.double_value;
|
||||
std::memcpy(ptr, &val, sizeof(val));
|
||||
break;
|
||||
}
|
||||
case patch_type::be16:
|
||||
{
|
||||
*reinterpret_cast<be_t<u16, 1>*>(ptr) = static_cast<u16>(p.value.long_value);
|
||||
be_t<u16> val = static_cast<u16>(p.value.long_value);
|
||||
std::memcpy(ptr, &val, sizeof(val));
|
||||
break;
|
||||
}
|
||||
case patch_type::bd32:
|
||||
{
|
||||
be_t<u32> val = static_cast<u32>(p.value.long_value);
|
||||
std::memcpy(ptr, &val, sizeof(val));
|
||||
break;
|
||||
}
|
||||
case patch_type::be32:
|
||||
{
|
||||
*reinterpret_cast<be_t<u32, 1>*>(ptr) = static_cast<u32>(p.value.long_value);
|
||||
be_t<u32> val = static_cast<u32>(p.value.long_value);
|
||||
std::memcpy(ptr, &val, sizeof(val));
|
||||
if (offset % 4 == 0)
|
||||
resval = offset;
|
||||
break;
|
||||
}
|
||||
case patch_type::bef32:
|
||||
{
|
||||
*reinterpret_cast<be_t<u32, 1>*>(ptr) = std::bit_cast<u32, f32>(static_cast<f32>(p.value.double_value));
|
||||
be_t<f32> val = static_cast<f32>(p.value.double_value);
|
||||
std::memcpy(ptr, &val, sizeof(val));
|
||||
break;
|
||||
}
|
||||
case patch_type::bd64:
|
||||
{
|
||||
be_t<u64> val = static_cast<u64>(p.value.long_value);
|
||||
std::memcpy(ptr, &val, sizeof(val));
|
||||
break;
|
||||
}
|
||||
case patch_type::be64:
|
||||
{
|
||||
*reinterpret_cast<be_t<u64, 1>*>(ptr) = static_cast<u64>(p.value.long_value);
|
||||
be_t<u64> val = static_cast<u64>(p.value.long_value);
|
||||
std::memcpy(ptr, &val, sizeof(val));
|
||||
|
||||
if (offset % 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
resval = offset;
|
||||
applied.push_back((offset + 7) & -4); // Two 32-bit locations
|
||||
break;
|
||||
}
|
||||
case patch_type::bef64:
|
||||
{
|
||||
*reinterpret_cast<be_t<u64, 1>*>(ptr) = std::bit_cast<u64, f64>(p.value.double_value);
|
||||
be_t<f64> val = p.value.double_value;
|
||||
std::memcpy(ptr, &val, sizeof(val));
|
||||
break;
|
||||
}
|
||||
case patch_type::utf8:
|
||||
{
|
||||
std::memcpy(ptr, p.original_value.data(), p.original_value.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++applied;
|
||||
// Possibly an executable instruction
|
||||
applied.push_back(resval);
|
||||
}
|
||||
|
||||
return applied;
|
||||
}
|
||||
|
||||
template <bool check_local_storage>
|
||||
std::size_t patch_engine::apply_patch(const std::string& name, u8* dst, u32 filesz, u32 ls_addr)
|
||||
std::basic_string<u32> patch_engine::apply(const std::string& name, u8* dst, u32 filesz, u32 min_addr)
|
||||
{
|
||||
if (m_map.find(name) == m_map.cend())
|
||||
{
|
||||
return 0;
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t applied_total = 0;
|
||||
std::basic_string<u32> applied_total;
|
||||
const auto& container = m_map.at(name);
|
||||
const auto serial = Emu.GetTitleID();
|
||||
const auto app_version = Emu.GetAppVersion();
|
||||
const auto& serial = Emu.GetTitleID();
|
||||
const auto& app_version = Emu.GetAppVersion();
|
||||
|
||||
// Different containers in order to seperate the patches
|
||||
std::vector<patch_engine::patch_info> legacy_patches;
|
||||
std::vector<patch_engine::patch_info> patches_for_this_serial_and_this_version;
|
||||
std::vector<patch_engine::patch_info> patches_for_this_serial_and_all_versions;
|
||||
std::vector<patch_engine::patch_info> patches_for_all_serials_and_this_version;
|
||||
@@ -700,17 +662,6 @@ std::size_t patch_engine::apply_patch(const std::string& name, u8* dst, u32 file
|
||||
// Sort patches into different vectors based on their serial and version
|
||||
for (const auto& [description, patch] : container.patch_info_map)
|
||||
{
|
||||
// Find out if this legacy patch is enabled
|
||||
if (patch.is_legacy)
|
||||
{
|
||||
if (patch.is_enabled)
|
||||
{
|
||||
legacy_patches.push_back(patch);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find out if this patch is enabled
|
||||
for (const auto& [title, serials] : patch.titles)
|
||||
{
|
||||
@@ -777,7 +728,6 @@ std::size_t patch_engine::apply_patch(const std::string& name, u8* dst, u32 file
|
||||
|
||||
// Sort specific patches in front of global patches
|
||||
std::vector<patch_engine::patch_info> sorted_patches;
|
||||
sorted_patches.insert(sorted_patches.end(), legacy_patches.begin(), legacy_patches.end());
|
||||
sorted_patches.insert(sorted_patches.end(), patches_for_this_serial_and_this_version.begin(), patches_for_this_serial_and_this_version.end());
|
||||
sorted_patches.insert(sorted_patches.end(), patches_for_this_serial_and_all_versions.begin(), patches_for_this_serial_and_all_versions.end());
|
||||
sorted_patches.insert(sorted_patches.end(), patches_for_all_serials_and_this_version.begin(), patches_for_all_serials_and_this_version.end());
|
||||
@@ -796,23 +746,17 @@ std::size_t patch_engine::apply_patch(const std::string& name, u8* dst, u32 file
|
||||
m_applied_groups.insert(patch.patch_group);
|
||||
}
|
||||
|
||||
const size_t applied = apply_modification<check_local_storage>(patch, dst, filesz, ls_addr);
|
||||
auto applied = apply_modification(patch, dst, filesz, min_addr);
|
||||
|
||||
applied_total += applied;
|
||||
|
||||
if (patch.is_legacy)
|
||||
{
|
||||
patch_log.success("Applied legacy patch (hash='%s')(<- %d)", patch.hash, applied);
|
||||
}
|
||||
else
|
||||
{
|
||||
patch_log.success("Applied patch (hash='%s', description='%s', author='%s', patch_version='%s', file_version='%s') (<- %d)", patch.hash, patch.description, patch.author, patch.patch_version, patch.version, applied);
|
||||
}
|
||||
patch_log.success("Applied patch (hash='%s', description='%s', author='%s', patch_version='%s', file_version='%s') (<- %u)", patch.hash, patch.description, patch.author, patch.patch_version, patch.version, applied.size());
|
||||
}
|
||||
|
||||
return applied_total;
|
||||
}
|
||||
|
||||
void patch_engine::save_config(const patch_map& patches_map, bool enable_legacy_patches)
|
||||
void patch_engine::save_config(const patch_map& patches_map)
|
||||
{
|
||||
const std::string path = get_patch_config_path();
|
||||
patch_log.notice("Saving patch config file %s", path);
|
||||
@@ -827,26 +771,13 @@ void patch_engine::save_config(const patch_map& patches_map, bool enable_legacy_
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginMap;
|
||||
|
||||
// Save "Enable Legacy Patches"
|
||||
out << config_key::enable_legacy_patches << enable_legacy_patches;
|
||||
|
||||
// Save 'enabled' state per hash, description, serial and app_version
|
||||
patch_map config_map;
|
||||
|
||||
for (const auto& [hash, container] : patches_map)
|
||||
{
|
||||
if (container.is_legacy)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto& [description, patch] : container.patch_info_map)
|
||||
{
|
||||
if (patch.is_legacy)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto& [title, serials] : patch.titles)
|
||||
{
|
||||
for (const auto& [serial, app_versions] : serials)
|
||||
@@ -862,7 +793,7 @@ void patch_engine::save_config(const patch_map& patches_map, bool enable_legacy_
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto& enabled_patches = config_map[hash].patch_info_map; enabled_patches.size() > 0)
|
||||
if (const auto& enabled_patches = config_map[hash].patch_info_map; !enabled_patches.empty())
|
||||
{
|
||||
out << hash << YAML::BeginMap;
|
||||
|
||||
@@ -903,7 +834,7 @@ void patch_engine::save_config(const patch_map& patches_map, bool enable_legacy_
|
||||
file.write(out.c_str(), out.size());
|
||||
}
|
||||
|
||||
static void append_patches(patch_engine::patch_map& existing_patches, const patch_engine::patch_map& new_patches, size_t& count, size_t& total, std::stringstream* log_messages)
|
||||
static void append_patches(patch_engine::patch_map& existing_patches, const patch_engine::patch_map& new_patches, usz& count, usz& total, std::stringstream* log_messages)
|
||||
{
|
||||
for (const auto& [hash, new_container] : new_patches)
|
||||
{
|
||||
@@ -1055,7 +986,7 @@ bool patch_engine::save_patches(const patch_map& patches, const std::string& pat
|
||||
return true;
|
||||
}
|
||||
|
||||
bool patch_engine::import_patches(const patch_engine::patch_map& patches, const std::string& path, size_t& count, size_t& total, std::stringstream* log_messages)
|
||||
bool patch_engine::import_patches(const patch_engine::patch_map& patches, const std::string& path, usz& count, usz& total, std::stringstream* log_messages)
|
||||
{
|
||||
patch_engine::patch_map existing_patches;
|
||||
|
||||
@@ -1089,10 +1020,8 @@ bool patch_engine::remove_patch(const patch_info& info)
|
||||
return false;
|
||||
}
|
||||
|
||||
patch_engine::patch_map patch_engine::load_config(bool& enable_legacy_patches)
|
||||
patch_engine::patch_map patch_engine::load_config()
|
||||
{
|
||||
enable_legacy_patches = true; // Default to true
|
||||
|
||||
patch_map config_map;
|
||||
|
||||
const std::string path = get_patch_config_path();
|
||||
@@ -1108,13 +1037,6 @@ patch_engine::patch_map patch_engine::load_config(bool& enable_legacy_patches)
|
||||
return config_map;
|
||||
}
|
||||
|
||||
// Try to load "Enable Legacy Patches" (default to true)
|
||||
if (auto enable_legacy_node = root[config_key::enable_legacy_patches])
|
||||
{
|
||||
enable_legacy_patches = enable_legacy_node.as<bool>(true);
|
||||
root.remove(config_key::enable_legacy_patches); // Remove the node in order to skip it in the next part
|
||||
}
|
||||
|
||||
for (const auto pair : root)
|
||||
{
|
||||
const auto& hash = pair.first.Scalar();
|
||||
|
||||
+32
-35
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "BEType.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "util/types.hpp"
|
||||
#include "util/yaml.hpp"
|
||||
|
||||
namespace patch_key
|
||||
@@ -20,7 +20,7 @@ namespace patch_key
|
||||
static const std::string version = "Version";
|
||||
}
|
||||
|
||||
static const std::string patch_engine_version = "1.2";
|
||||
inline static const std::string patch_engine_version = "1.2";
|
||||
|
||||
enum class patch_type
|
||||
{
|
||||
@@ -34,9 +34,12 @@ enum class patch_type
|
||||
lef64,
|
||||
be16,
|
||||
be32,
|
||||
bd32, // be32 with data hint (non-code)
|
||||
be64,
|
||||
bd64, // be64 with data hint (non-code)
|
||||
bef32,
|
||||
bef64,
|
||||
utf8, // Text of string (not null-terminated automatically)
|
||||
};
|
||||
|
||||
class patch_engine
|
||||
@@ -46,14 +49,14 @@ public:
|
||||
{
|
||||
patch_type type = patch_type::load;
|
||||
u32 offset = 0;
|
||||
std::string original_value; // Used for import consistency (avoid rounding etc.)
|
||||
std::string original_value{}; // Used for import consistency (avoid rounding etc.)
|
||||
union
|
||||
{
|
||||
u64 long_value;
|
||||
f64 double_value;
|
||||
} value { 0 };
|
||||
} value{0};
|
||||
};
|
||||
|
||||
|
||||
using patch_app_versions = std::unordered_map<std::string /*app_version*/, bool /*enabled*/>;
|
||||
using patch_serials = std::unordered_map<std::string /*serial*/, patch_app_versions>;
|
||||
using patch_titles = std::unordered_map<std::string /*serial*/, patch_serials>;
|
||||
@@ -61,34 +64,35 @@ public:
|
||||
struct patch_info
|
||||
{
|
||||
// Patch information
|
||||
std::vector<patch_data> data_list;
|
||||
patch_titles titles;
|
||||
std::string description;
|
||||
std::string patch_version;
|
||||
std::string patch_group;
|
||||
std::string author;
|
||||
std::string notes;
|
||||
std::string source_path;
|
||||
std::vector<patch_data> data_list{};
|
||||
patch_titles titles{};
|
||||
std::string description{};
|
||||
std::string patch_version{};
|
||||
std::string patch_group{};
|
||||
std::string author{};
|
||||
std::string notes{};
|
||||
std::string source_path{};
|
||||
|
||||
// Redundant information for accessibility (see patch_container)
|
||||
std::string hash;
|
||||
std::string version;
|
||||
bool is_legacy = false;
|
||||
bool is_enabled = false; // only for legacy patches
|
||||
std::string hash{};
|
||||
std::string version{};
|
||||
};
|
||||
|
||||
struct patch_container
|
||||
{
|
||||
std::unordered_map<std::string /*description*/, patch_info> patch_info_map;
|
||||
std::string hash;
|
||||
std::string version;
|
||||
bool is_legacy = false;
|
||||
std::unordered_map<std::string /*description*/, patch_info> patch_info_map{};
|
||||
std::string hash{};
|
||||
std::string version{};
|
||||
};
|
||||
|
||||
using patch_map = std::unordered_map<std::string /*hash*/, patch_container>;
|
||||
|
||||
patch_engine();
|
||||
|
||||
patch_engine(const patch_engine&) = delete;
|
||||
|
||||
patch_engine& operator=(const patch_engine&) = delete;
|
||||
|
||||
// Returns the directory in which patch_config.yml is located
|
||||
static std::string get_patch_config_path();
|
||||
|
||||
@@ -111,19 +115,19 @@ public:
|
||||
static bool add_patch_data(YAML::Node node, patch_info& info, u32 modifier, const YAML::Node& root, std::stringstream* log_messages = nullptr);
|
||||
|
||||
// Save to patch_config.yml
|
||||
static void save_config(const patch_map& patches_map, bool enable_legacy_patches);
|
||||
static void save_config(const patch_map& patches_map);
|
||||
|
||||
// Save a patch file
|
||||
static bool save_patches(const patch_map& patches, const std::string& path, std::stringstream* log_messages = nullptr);
|
||||
|
||||
// Create or append patches to a file
|
||||
static bool import_patches(const patch_map& patches, const std::string& path, size_t& count, size_t& total, std::stringstream* log_messages = nullptr);
|
||||
static bool import_patches(const patch_map& patches, const std::string& path, usz& count, usz& total, std::stringstream* log_messages = nullptr);
|
||||
|
||||
// Remove a patch from a file
|
||||
static bool remove_patch(const patch_info& info);
|
||||
|
||||
// Load patch_config.yml
|
||||
static patch_map load_config(bool& enable_legacy_patches);
|
||||
static patch_map load_config();
|
||||
|
||||
// Load from file and append to member patches map
|
||||
void append_global_patches();
|
||||
@@ -132,19 +136,12 @@ public:
|
||||
void append_title_patches(const std::string& title_id);
|
||||
|
||||
// Apply patch (returns the number of entries applied)
|
||||
std::size_t apply(const std::string& name, u8* dst);
|
||||
|
||||
// Apply patch with a check that the address exists in SPU local storage
|
||||
std::size_t apply_with_ls_check(const std::string& name, u8* dst, u32 filesz, u32 ls_addr);
|
||||
std::basic_string<u32> apply(const std::string& name, u8* dst, u32 filesz = UINT32_MAX, u32 min_addr = 0);
|
||||
|
||||
private:
|
||||
// Internal: Apply patch (returns the number of entries applied)
|
||||
template <bool check_local_storage>
|
||||
std::size_t apply_patch(const std::string& name, u8* dst, u32 filesz, u32 ls_addr);
|
||||
|
||||
// Database
|
||||
patch_map m_map;
|
||||
patch_map m_map{};
|
||||
|
||||
// Only one patch per patch group can be applied
|
||||
std::set<std::string> m_applied_groups;
|
||||
std::set<std::string> m_applied_groups{};
|
||||
};
|
||||
|
||||
+66
-104
@@ -21,14 +21,21 @@ Examples:
|
||||
Intersection (&) and symmetric difference (^) is also available.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
#include "util/atomic.hpp"
|
||||
#include "Utilities/StrFmt.h"
|
||||
|
||||
template <typename T>
|
||||
concept BitSetEnum = std::is_enum_v<T> && requires(T x)
|
||||
{
|
||||
T::__bitset_enum_max;
|
||||
};
|
||||
|
||||
template <BitSetEnum T>
|
||||
class atomic_bs_t;
|
||||
|
||||
// Bitset type for enum class with available bits [0, T::__bitset_enum_max)
|
||||
template <typename T>
|
||||
template <BitSetEnum T>
|
||||
class bs_t final
|
||||
{
|
||||
public:
|
||||
@@ -48,8 +55,8 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr std::size_t bitmax = sizeof(T) * 8;
|
||||
static constexpr std::size_t bitsize = static_cast<under>(T::__bitset_enum_max);
|
||||
static constexpr usz bitmax = sizeof(T) * 8;
|
||||
static constexpr usz bitsize = static_cast<under>(T::__bitset_enum_max);
|
||||
|
||||
static_assert(std::is_enum<T>::value, "bs_t<> error: invalid type (must be enum)");
|
||||
static_assert(bitsize <= bitmax, "bs_t<> error: invalid __bitset_enum_max");
|
||||
@@ -111,24 +118,24 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr bs_t operator +(bs_t rhs) const
|
||||
friend constexpr bs_t operator +(bs_t lhs, bs_t rhs)
|
||||
{
|
||||
return bs_t(0, m_data | rhs.m_data);
|
||||
return bs_t(0, lhs.m_data | rhs.m_data);
|
||||
}
|
||||
|
||||
constexpr bs_t operator -(bs_t rhs) const
|
||||
friend constexpr bs_t operator -(bs_t lhs, bs_t rhs)
|
||||
{
|
||||
return bs_t(0, m_data & ~rhs.m_data);
|
||||
return bs_t(0, lhs.m_data & ~rhs.m_data);
|
||||
}
|
||||
|
||||
constexpr bs_t operator &(bs_t rhs) const
|
||||
friend constexpr bs_t operator &(bs_t lhs, bs_t rhs)
|
||||
{
|
||||
return bs_t(0, m_data & rhs.m_data);
|
||||
return bs_t(0, lhs.m_data & rhs.m_data);
|
||||
}
|
||||
|
||||
constexpr bs_t operator ^(bs_t rhs) const
|
||||
friend constexpr bs_t operator ^(bs_t lhs, bs_t rhs)
|
||||
{
|
||||
return bs_t(0, m_data ^ rhs.m_data);
|
||||
return bs_t(0, lhs.m_data ^ rhs.m_data);
|
||||
}
|
||||
|
||||
constexpr bool operator ==(bs_t rhs) const
|
||||
@@ -136,16 +143,6 @@ public:
|
||||
return m_data == rhs.m_data;
|
||||
}
|
||||
|
||||
constexpr bool operator !=(bs_t rhs) const
|
||||
{
|
||||
return m_data != rhs.m_data;
|
||||
}
|
||||
|
||||
constexpr bool test(bs_t rhs) const
|
||||
{
|
||||
return (m_data & rhs.m_data) != 0;
|
||||
}
|
||||
|
||||
constexpr bool test_and_set(T bit)
|
||||
{
|
||||
bool r = (m_data & shift(bit)) != 0;
|
||||
@@ -169,43 +166,71 @@ public:
|
||||
};
|
||||
|
||||
// Unary '+' operator: promote plain enum value to bitset value
|
||||
template <typename T, typename = decltype(T::__bitset_enum_max)>
|
||||
template <BitSetEnum T>
|
||||
constexpr bs_t<T> operator +(T bit)
|
||||
{
|
||||
return bit;
|
||||
return bs_t<T>(bit);
|
||||
}
|
||||
|
||||
// Binary '+' operator: bitset union
|
||||
template <typename T, typename = decltype(T::__bitset_enum_max)>
|
||||
constexpr bs_t<T> operator +(T lhs, T rhs)
|
||||
template <BitSetEnum T, typename U> requires (std::is_constructible_v<bs_t<T>, U>)
|
||||
constexpr bs_t<T> operator +(T lhs, const U& rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) + bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '+' operator: bitset union
|
||||
template <typename U, BitSetEnum T> requires (std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr bs_t<T> operator +(const U& lhs, T rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) + bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '-' operator: bitset difference
|
||||
template <typename T, typename = decltype(T::__bitset_enum_max)>
|
||||
constexpr bs_t<T> operator -(T lhs, T rhs)
|
||||
template <BitSetEnum T, typename U> requires (std::is_constructible_v<bs_t<T>, U>)
|
||||
constexpr bs_t<T> operator -(T lhs, const U& rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) - bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '-' operator: bitset difference
|
||||
template <typename U, BitSetEnum T> requires (std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr bs_t<T> operator -(const U& lhs, T rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) - bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '&' operator: bitset intersection
|
||||
template <typename T, typename = decltype(T::__bitset_enum_max)>
|
||||
constexpr bs_t<T> operator &(T lhs, T rhs)
|
||||
template <BitSetEnum T, typename U> requires (std::is_constructible_v<bs_t<T>, U>)
|
||||
constexpr bs_t<T> operator &(T lhs, const U& rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) & bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '&' operator: bitset intersection
|
||||
template <typename U, BitSetEnum T> requires (std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr bs_t<T> operator &(const U& lhs, T rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) & bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '^' operator: bitset symmetric difference
|
||||
template <typename T, typename = decltype(T::__bitset_enum_max)>
|
||||
constexpr bs_t<T> operator ^(T lhs, T rhs)
|
||||
template <BitSetEnum T, typename U> requires (std::is_constructible_v<bs_t<T>, U>)
|
||||
constexpr bs_t<T> operator ^(T lhs, const U& rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) ^ bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Binary '^' operator: bitset symmetric difference
|
||||
template <typename U, BitSetEnum T> requires (std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>)
|
||||
constexpr bs_t<T> operator ^(const U& lhs, T rhs)
|
||||
{
|
||||
return bs_t<T>(lhs) ^ bs_t<T>(rhs);
|
||||
}
|
||||
|
||||
// Atomic bitset specialization with optimized operations
|
||||
template <typename T>
|
||||
class atomic_bs_t : public atomic_t<::bs_t<T>> // TODO: true specialization
|
||||
template <BitSetEnum T>
|
||||
class atomic_bs_t : public atomic_t<::bs_t<T>>
|
||||
{
|
||||
// Corresponding bitset type
|
||||
using bs_t = ::bs_t<T>;
|
||||
@@ -236,6 +261,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
using base::operator bs_t;
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return static_cast<bool>(base::load());
|
||||
@@ -314,75 +341,6 @@ public:
|
||||
auto fetch_or(const bs_t&) = delete;
|
||||
auto or_fetch(const bs_t&) = delete;
|
||||
auto operator |=(const bs_t&) = delete;
|
||||
auto operator ++() = delete;
|
||||
auto operator --() = delete;
|
||||
auto operator ++(int) = delete;
|
||||
auto operator --(int) = delete;
|
||||
|
||||
bs_t operator +(bs_t rhs) const
|
||||
{
|
||||
return bs_t(0, base::load().m_data | rhs.m_data);
|
||||
}
|
||||
|
||||
bs_t operator -(bs_t rhs) const
|
||||
{
|
||||
return bs_t(0, base::load().m_data & ~rhs.m_data);
|
||||
}
|
||||
|
||||
bs_t operator &(bs_t rhs) const
|
||||
{
|
||||
return bs_t(0, base::load().m_data & rhs.m_data);
|
||||
}
|
||||
|
||||
bs_t operator ^(bs_t rhs) const
|
||||
{
|
||||
return bs_t(0, base::load().m_data ^ rhs.m_data);
|
||||
}
|
||||
|
||||
bs_t operator ==(bs_t rhs) const
|
||||
{
|
||||
return base::load().m_data == rhs.m_data;
|
||||
}
|
||||
|
||||
bs_t operator !=(bs_t rhs) const
|
||||
{
|
||||
return base::load().m_data != rhs.m_data;
|
||||
}
|
||||
|
||||
friend bs_t operator +(bs_t lhs, const atomic_bs_t& rhs)
|
||||
{
|
||||
return bs_t(0, lhs.m_data | rhs.load().m_data);
|
||||
}
|
||||
|
||||
friend bs_t operator -(bs_t lhs, const atomic_bs_t& rhs)
|
||||
{
|
||||
return bs_t(0, lhs.m_data & ~rhs.load().m_data);
|
||||
}
|
||||
|
||||
friend bs_t operator &(bs_t lhs, const atomic_bs_t& rhs)
|
||||
{
|
||||
return bs_t(0, lhs.m_data & rhs.load().m_data);
|
||||
}
|
||||
|
||||
friend bs_t operator ^(bs_t lhs, const atomic_bs_t& rhs)
|
||||
{
|
||||
return bs_t(0, lhs.m_data ^ rhs.load().m_data);
|
||||
}
|
||||
|
||||
friend bs_t operator ==(bs_t lhs, const atomic_bs_t& rhs)
|
||||
{
|
||||
return lhs.m_data == rhs.load().m_data;
|
||||
}
|
||||
|
||||
friend bs_t operator !=(bs_t lhs, const atomic_bs_t& rhs)
|
||||
{
|
||||
return lhs.m_data != rhs.load().m_data;
|
||||
}
|
||||
|
||||
bool test(const bs_t& rhs)
|
||||
{
|
||||
return base::load().test(rhs);
|
||||
}
|
||||
|
||||
bool test_and_set(T rhs)
|
||||
{
|
||||
@@ -394,10 +352,14 @@ public:
|
||||
return atomic_storage<under>::btr(m_data.m_data, static_cast<uint>(static_cast<under>(rhs)));
|
||||
}
|
||||
|
||||
bool test_and_complement(T rhs)
|
||||
bool test_and_invert(T rhs)
|
||||
{
|
||||
return atomic_storage<under>::btc(m_data.m_data, static_cast<uint>(static_cast<under>(rhs)));
|
||||
}
|
||||
|
||||
bool bit_test_set(uint bit) = delete;
|
||||
bool bit_test_reset(uint bit) = delete;
|
||||
bool bit_test_invert(uint bit) = delete;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
||||
+109
-47
@@ -1,12 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
#include <climits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
static const size_t size_dropped = std::numeric_limits<size_t>::max();
|
||||
#include "util/asm.hpp"
|
||||
|
||||
/*
|
||||
C-style format parser. Appends formatted string to `out`, returns number of characters written.
|
||||
@@ -15,13 +14,13 @@ C-style format parser. Appends formatted string to `out`, returns number of char
|
||||
`src`: rvalue reference to argument provider.
|
||||
*/
|
||||
template<typename Dst, typename Char, typename Src>
|
||||
std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
{
|
||||
const std::size_t start_pos = out.size();
|
||||
const usz start_pos = out.size();
|
||||
|
||||
struct cfmt_context
|
||||
{
|
||||
std::size_t size; // Size of current format sequence
|
||||
usz size; // Size of current format sequence
|
||||
|
||||
u8 args; // Number of extra args used
|
||||
u8 type; // Integral type bytesize
|
||||
@@ -42,7 +41,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
const auto drop_sequence = [&]
|
||||
{
|
||||
out.insert(out.end(), fmt - ctx.size, fmt);
|
||||
ctx.size = size_dropped;
|
||||
ctx.size = umax;
|
||||
};
|
||||
|
||||
const auto read_decimal = [&](uint result) -> uint
|
||||
@@ -56,41 +55,70 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
return result;
|
||||
};
|
||||
|
||||
const auto write_octal = [&](u64 value, u64 min_num)
|
||||
const auto write_octal = [&](auto value, u64 min_num)
|
||||
{
|
||||
out.resize(out.size() + std::max<u64>(min_num, 66 / 3 - (std::countl_zero<u64>(value | 1) + 2) / 3), '0');
|
||||
if constexpr (sizeof(value) == 16)
|
||||
{
|
||||
out.resize(out.size() + std::max<u64>(min_num, 129 / 3 - (utils::clz128(value | 1) + 1) / 3), '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
out.resize(out.size() + std::max<u64>(min_num, 66 / 3 - (std::countl_zero<u64>(value | 1) + 2) / 3), '0');
|
||||
}
|
||||
|
||||
// Write in reversed order
|
||||
for (auto i = out.rbegin(); value; i++, value /= 8)
|
||||
for (auto i = out.rbegin(); value; i++, value >>= 3)
|
||||
{
|
||||
*i = value % 8 + '0';
|
||||
*i = static_cast<char>(static_cast<u64>(value) & 7) + '0';
|
||||
}
|
||||
};
|
||||
|
||||
const auto write_hex = [&](u64 value, bool upper, u64 min_num)
|
||||
const auto write_hex = [&](auto value, bool upper, u64 min_num)
|
||||
{
|
||||
out.resize(out.size() + std::max<u64>(min_num, 64 / 4 - std::countl_zero<u64>(value | 1) / 4), '0');
|
||||
if constexpr (sizeof(value) == 16)
|
||||
{
|
||||
out.resize(out.size() + std::max<u64>(min_num, 128 / 4 - utils::clz128(value | 1) / 4), '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
out.resize(out.size() + std::max<u64>(min_num, 64 / 4 - std::countl_zero<u64>(value | 1) / 4), '0');
|
||||
}
|
||||
|
||||
// Write in reversed order
|
||||
for (auto i = out.rbegin(); value; i++, value /= 16)
|
||||
for (auto i = out.rbegin(); value; i++, value >>= 4)
|
||||
{
|
||||
*i = (upper ? "0123456789ABCDEF" : "0123456789abcdef")[value % 16];
|
||||
*i = (upper ? "0123456789ABCDEF" : "0123456789abcdef")[static_cast<usz>(value & 0xf)];
|
||||
}
|
||||
};
|
||||
|
||||
const auto write_decimal = [&](u64 value, s64 min_size)
|
||||
const auto write_decimal = [&](auto value, s64 min_size)
|
||||
{
|
||||
const std::size_t start = out.size();
|
||||
const usz start = out.size();
|
||||
|
||||
do
|
||||
{
|
||||
out.push_back(value % 10 + '0');
|
||||
value /= 10;
|
||||
if constexpr (sizeof(value) == 16)
|
||||
{
|
||||
const u128 v0 = value;
|
||||
value >>= 1;
|
||||
constexpr u128 by_five = 0x3333'3333'3333'3333;
|
||||
const u128 v1 = (value >> 64) * by_five;
|
||||
const u128 v2 = ((value >> 64) * by_five) >> 64;
|
||||
const u128 v3 = (static_cast<u64>(value) * by_five) >> 64;
|
||||
value = v1 + v2 + v3;
|
||||
|
||||
out.push_back(static_cast<char>(static_cast<u64>(v0 - (value * 10))) + '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
out.push_back(value % 10 + '0');
|
||||
value /= 10;
|
||||
}
|
||||
}
|
||||
while (0 < --min_size || value);
|
||||
|
||||
// Revert written characters
|
||||
for (std::size_t i = start, j = out.size() - 1; i < j; i++, j--)
|
||||
for (usz i = start, j = out.size() - 1; i < j; i++, j--)
|
||||
{
|
||||
std::swap(out[i], out[j]);
|
||||
}
|
||||
@@ -113,7 +141,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
ctx = {0};
|
||||
out.push_back(ch);
|
||||
}
|
||||
else if (ctx.size == size_dropped)
|
||||
else if (ctx.size == umax)
|
||||
{
|
||||
out.push_back(ch);
|
||||
}
|
||||
@@ -285,7 +313,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
break;
|
||||
}
|
||||
|
||||
const std::size_t start = out.size();
|
||||
const usz start = out.size();
|
||||
out.push_back(src.template get<Char>(ctx.args));
|
||||
|
||||
if (1 < ctx.width)
|
||||
@@ -307,8 +335,8 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
break;
|
||||
}
|
||||
|
||||
const std::size_t start = out.size();
|
||||
const std::size_t size1 = src.fmt_string(out, ctx.args);
|
||||
const usz start = out.size();
|
||||
const usz size1 = src.fmt_string(out, ctx.args);
|
||||
|
||||
if (ctx.dot && size1 > ctx.prec)
|
||||
{
|
||||
@@ -316,7 +344,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
out.resize(start + ctx.prec);
|
||||
}
|
||||
|
||||
const std::size_t size2 = out.size() - start;
|
||||
const usz size2 = out.size() - start;
|
||||
|
||||
if (size2 < ctx.width)
|
||||
{
|
||||
@@ -352,7 +380,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
const u64 val = src.template get<u64>(ctx.args);
|
||||
const bool negative = ctx.type && static_cast<s64>(val) < 0;
|
||||
|
||||
const std::size_t start = out.size();
|
||||
const usz start = out.size();
|
||||
|
||||
if (!ctx.dot || ctx.prec)
|
||||
{
|
||||
@@ -369,10 +397,19 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
out.push_back(' ');
|
||||
}
|
||||
|
||||
write_decimal(negative ? 0 - val : val, ctx.prec);
|
||||
if (ctx.type == 16)
|
||||
{
|
||||
// TODO: support negative values (s128)
|
||||
u128 val2 = *reinterpret_cast<u128*>(val);
|
||||
write_decimal(val2, ctx.prec);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_decimal(negative ? 0 - val : val, ctx.prec);
|
||||
}
|
||||
}
|
||||
|
||||
const std::size_t size2 = out.size() - start;
|
||||
const usz size2 = out.size() - start;
|
||||
|
||||
if (size2 < ctx.width)
|
||||
{
|
||||
@@ -419,23 +456,32 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
// Trunc sign-extended signed types
|
||||
const u64 val = src.template get<u64>(ctx.args) & mask;
|
||||
|
||||
const std::size_t start = out.size();
|
||||
const usz start = out.size();
|
||||
|
||||
if (ctx.alter)
|
||||
{
|
||||
out.push_back('0');
|
||||
|
||||
if (val)
|
||||
if (ctx.prec)
|
||||
{
|
||||
write_octal(val, ctx.prec ? ctx.prec - 1 : 0);
|
||||
ctx.prec--;
|
||||
}
|
||||
}
|
||||
else if (!ctx.dot || ctx.prec)
|
||||
|
||||
if ((ctx.alter && val) || !ctx.dot || ctx.prec)
|
||||
{
|
||||
write_octal(val, ctx.prec);
|
||||
if (ctx.type == 16)
|
||||
{
|
||||
u128 val2 = *reinterpret_cast<u128*>(val);
|
||||
write_octal(val2, ctx.prec);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_octal(val, ctx.prec);
|
||||
}
|
||||
}
|
||||
|
||||
const std::size_t size2 = out.size() - start;
|
||||
const usz size2 = out.size() - start;
|
||||
|
||||
if (size2 < ctx.width)
|
||||
{
|
||||
@@ -476,7 +522,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
// Trunc sign-extended signed types
|
||||
const u64 val = src.template get<u64>(ctx.args) & mask;
|
||||
|
||||
const std::size_t start = out.size();
|
||||
const usz start = out.size();
|
||||
|
||||
if (ctx.alter)
|
||||
{
|
||||
@@ -485,15 +531,23 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
if (val)
|
||||
{
|
||||
out.push_back(ch); // Prepend 0x or 0X
|
||||
}
|
||||
}
|
||||
|
||||
if ((ctx.alter && val) || !ctx.dot || ctx.prec)
|
||||
{
|
||||
if (ctx.type == 16)
|
||||
{
|
||||
u128 val2 = *reinterpret_cast<u128*>(val);
|
||||
write_hex(val2, ch == 'X', ctx.prec);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_hex(val, ch == 'X', ctx.prec);
|
||||
}
|
||||
}
|
||||
else if (!ctx.dot || ctx.prec)
|
||||
{
|
||||
write_hex(val, ch == 'X', ctx.prec);
|
||||
}
|
||||
|
||||
const std::size_t size2 = out.size() - start;
|
||||
const usz size2 = out.size() - start;
|
||||
|
||||
if (size2 < ctx.width)
|
||||
{
|
||||
@@ -540,14 +594,22 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
// Trunc sign-extended signed types
|
||||
const u64 val = src.template get<u64>(ctx.args) & mask;
|
||||
|
||||
const std::size_t start = out.size();
|
||||
const usz start = out.size();
|
||||
|
||||
if (!ctx.dot || ctx.prec)
|
||||
{
|
||||
write_decimal(val, ctx.prec);
|
||||
if (ctx.type == 16)
|
||||
{
|
||||
u128 val2 = *reinterpret_cast<u128*>(val);
|
||||
write_decimal(val2, ctx.prec);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_decimal(val, ctx.prec);
|
||||
}
|
||||
}
|
||||
|
||||
const std::size_t size2 = out.size() - start;
|
||||
const usz size2 = out.size() - start;
|
||||
|
||||
if (size2 < ctx.width)
|
||||
{
|
||||
@@ -570,11 +632,11 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
|
||||
const u64 val = src.template get<u64>(ctx.args);
|
||||
|
||||
const std::size_t start = out.size();
|
||||
const usz start = out.size();
|
||||
|
||||
write_hex(val, false, sizeof(void*) * 2);
|
||||
|
||||
const std::size_t size2 = out.size() - start;
|
||||
const usz size2 = out.size() - start;
|
||||
|
||||
if (size2 < ctx.width)
|
||||
{
|
||||
@@ -610,7 +672,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
const u64 arg1 = ctx.args >= 1 ? src.template get<u64>(1) : 0;
|
||||
const u64 arg2 = ctx.args >= 2 ? src.template get<u64>(2) : 0;
|
||||
|
||||
if (const std::size_t _size = std::snprintf(0, 0, _fmt.c_str(), arg0, arg1, arg2))
|
||||
if (const usz _size = std::snprintf(nullptr, 0, _fmt.c_str(), arg0, arg1, arg2))
|
||||
{
|
||||
out.resize(out.size() + _size);
|
||||
std::snprintf(&out.front() + out.size() - _size, _size + 1, _fmt.c_str(), arg0, arg1, arg2);
|
||||
@@ -630,7 +692,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
||||
}
|
||||
|
||||
// Handle unfinished sequence
|
||||
if (ctx.size && ctx.size != size_dropped)
|
||||
if (ctx.size && ctx.size != umax)
|
||||
{
|
||||
fmt--, drop_sequence();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "cheat_info.h"
|
||||
#include "Config.h"
|
||||
#include "StrUtil.h"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "util/types.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
enum class cheat_type : u8
|
||||
{
|
||||
@@ -19,11 +21,11 @@ constexpr u8 cheat_type_max = static_cast<u8>(cheat_type::max);
|
||||
|
||||
struct cheat_info
|
||||
{
|
||||
std::string game;
|
||||
std::string description;
|
||||
std::string game{};
|
||||
std::string description{};
|
||||
cheat_type type = cheat_type::max;
|
||||
u32 offset{};
|
||||
std::string red_script;
|
||||
std::string red_script{};
|
||||
|
||||
bool from_str(const std::string& cheat_line);
|
||||
std::string to_str() const;
|
||||
|
||||
+4
-7
@@ -1,15 +1,12 @@
|
||||
#include "cond.h"
|
||||
#include "cond.h"
|
||||
#include "sync.h"
|
||||
#include "lockless.h"
|
||||
|
||||
#include <climits>
|
||||
|
||||
// use constants, increase signal space
|
||||
|
||||
void cond_variable::imp_wait(u32 _old, u64 _timeout) noexcept
|
||||
{
|
||||
// Not supposed to fail
|
||||
verify(HERE), _old;
|
||||
ensure(_old);
|
||||
|
||||
// Wait with timeout
|
||||
m_value.wait(_old, c_signal_mask, atomic_wait_timeout{_timeout > max_timeout ? UINT64_MAX : _timeout * 1000});
|
||||
@@ -50,10 +47,10 @@ void cond_variable::imp_wake(u32 _count) noexcept
|
||||
if (_count > 1 || ((_old + (c_signal_mask & (0 - c_signal_mask))) & c_signal_mask) == c_signal_mask)
|
||||
{
|
||||
// Resort to notify_all if signal count reached max
|
||||
m_value.notify_all();
|
||||
m_value.notify_all(c_signal_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_value.notify_one();
|
||||
m_value.notify_one(c_signal_mask);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -1,8 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
#include "util/atomic.hpp"
|
||||
#include <shared_mutex>
|
||||
|
||||
// Lightweight condition variable
|
||||
class cond_variable
|
||||
|
||||
+16
-2
@@ -17,10 +17,24 @@ namespace date_time
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline std::string fmt_time(const char* fmt, const s64 time)
|
||||
{
|
||||
tm buf;
|
||||
time_t t = time;
|
||||
#ifdef _MSC_VER
|
||||
localtime_s(&buf, &t);
|
||||
#else
|
||||
buf = *localtime(&t);
|
||||
#endif
|
||||
char str[80];
|
||||
strftime(str, sizeof(str), fmt, &buf);
|
||||
return str;
|
||||
}
|
||||
|
||||
static inline std::string current_time()
|
||||
{
|
||||
char str[80];
|
||||
tm now = get_time(0);
|
||||
tm now = get_time(nullptr);
|
||||
strftime(str, sizeof(str), "%c", &now);
|
||||
return str;
|
||||
}
|
||||
@@ -29,7 +43,7 @@ namespace date_time
|
||||
static inline std::string current_time_narrow()
|
||||
{
|
||||
char str[80];
|
||||
tm now = get_time(0);
|
||||
tm now = get_time(nullptr);
|
||||
|
||||
std::string parse_buf;
|
||||
|
||||
|
||||
+5
-111
@@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@@ -102,14 +102,6 @@ struct size2_base
|
||||
return width == rhs.width && height == rhs.height;
|
||||
}
|
||||
|
||||
#if __cpp_impl_three_way_comparison >= 201711
|
||||
#else
|
||||
constexpr bool operator !=(const size2_base& rhs) const
|
||||
{
|
||||
return width != rhs.width || height != rhs.height;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename NT>
|
||||
explicit constexpr operator size2_base<NT>() const
|
||||
{
|
||||
@@ -211,19 +203,6 @@ struct position1_base
|
||||
return x == rhs;
|
||||
}
|
||||
|
||||
#if __cpp_impl_three_way_comparison >= 201711
|
||||
#else
|
||||
bool operator !=(const position1_base& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
bool operator !=(T rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename NT>
|
||||
explicit operator position1_base<NT>() const
|
||||
{
|
||||
@@ -383,19 +362,6 @@ struct position2_base
|
||||
return x == rhs && y == rhs;
|
||||
}
|
||||
|
||||
#if __cpp_impl_three_way_comparison >= 201711
|
||||
#else
|
||||
constexpr bool operator !=(const position2_base& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
constexpr bool operator !=(T rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename NT>
|
||||
explicit constexpr operator position2_base<NT>() const
|
||||
{
|
||||
@@ -478,19 +444,6 @@ struct position3_base
|
||||
return x == rhs && y == rhs && z == rhs;
|
||||
}
|
||||
|
||||
#if __cpp_impl_three_way_comparison >= 201711
|
||||
#else
|
||||
bool operator !=(const position3_base& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
bool operator !=(T rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename NT>
|
||||
explicit operator position3_base<NT>() const
|
||||
{
|
||||
@@ -571,19 +524,6 @@ struct position4_base
|
||||
return x == rhs && y == rhs && z == rhs && w == rhs;
|
||||
}
|
||||
|
||||
#if __cpp_impl_three_way_comparison >= 201711
|
||||
#else
|
||||
constexpr bool operator !=(const position4_base& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
constexpr bool operator !=(T rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename NT>
|
||||
explicit constexpr operator position4_base<NT>() const
|
||||
{
|
||||
@@ -639,14 +579,6 @@ struct coord_base
|
||||
return position == rhs.position && size == rhs.size;
|
||||
}
|
||||
|
||||
#if __cpp_impl_three_way_comparison >= 201711
|
||||
#else
|
||||
constexpr bool operator != (const coord_base& rhs) const
|
||||
{
|
||||
return position != rhs.position || size != rhs.size;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename NT>
|
||||
explicit constexpr operator coord_base<NT>() const
|
||||
{
|
||||
@@ -718,14 +650,6 @@ struct area_base
|
||||
return x1 == rhs.x1 && x2 == rhs.x2 && y1 == rhs.y1 && y2 == rhs.y2;
|
||||
}
|
||||
|
||||
#if __cpp_impl_three_way_comparison >= 201711
|
||||
#else
|
||||
constexpr bool operator != (const area_base& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
constexpr area_base operator - (const size2_base<T>& size) const
|
||||
{
|
||||
return{ x1 - size.width, y1 - size.height, x2 - size.width, y2 - size.height };
|
||||
@@ -864,17 +788,10 @@ struct color4_base
|
||||
{
|
||||
}
|
||||
|
||||
constexpr bool operator == (const color4_base& rhs) const
|
||||
constexpr bool operator ==(const color4_base& rhs) const
|
||||
{
|
||||
return r == rhs.r && g == rhs.g && b == rhs.b && a == rhs.a;
|
||||
}
|
||||
#if __cpp_impl_three_way_comparison >= 201711
|
||||
#else
|
||||
constexpr bool operator != (const color4_base& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
void operator *= (const color4_base<T>& rhs)
|
||||
{
|
||||
@@ -940,17 +857,10 @@ struct color3_base
|
||||
{
|
||||
}
|
||||
|
||||
constexpr bool operator == (const color3_base& rhs) const
|
||||
constexpr bool operator ==(const color3_base& rhs) const
|
||||
{
|
||||
return r == rhs.r && g == rhs.g && b == rhs.b;
|
||||
}
|
||||
#if __cpp_impl_three_way_comparison >= 201711
|
||||
#else
|
||||
constexpr bool operator != (const color3_base& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename NT>
|
||||
explicit constexpr operator color3_base<NT>() const
|
||||
@@ -984,19 +894,11 @@ struct color2_base
|
||||
{
|
||||
}
|
||||
|
||||
constexpr bool operator == (const color2_base& rhs) const
|
||||
constexpr bool operator ==(const color2_base& rhs) const
|
||||
{
|
||||
return r == rhs.r && g == rhs.g;
|
||||
}
|
||||
|
||||
#if __cpp_impl_three_way_comparison >= 201711
|
||||
#else
|
||||
constexpr bool operator != (const color2_base& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename NT>
|
||||
explicit constexpr operator color2_base<NT>() const
|
||||
{
|
||||
@@ -1018,19 +920,11 @@ struct color1_base
|
||||
{
|
||||
}
|
||||
|
||||
constexpr bool operator == (const color1_base& rhs) const
|
||||
constexpr bool operator ==(const color1_base& rhs) const
|
||||
{
|
||||
return r == rhs.r;
|
||||
}
|
||||
|
||||
#if __cpp_impl_three_way_comparison >= 201711
|
||||
#else
|
||||
constexpr bool operator != (const color1_base& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename NT>
|
||||
explicit constexpr operator color1_base<NT>() const
|
||||
{
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Utilities/types.h"
|
||||
|
||||
namespace rpcs3
|
||||
{
|
||||
template<typename T>
|
||||
static size_t hash_base(T value)
|
||||
{
|
||||
return static_cast<size_t>(value);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
static size_t hash_struct_base(const T& value)
|
||||
{
|
||||
// FNV 64-bit
|
||||
size_t result = 14695981039346656037ull;
|
||||
const U *bits = reinterpret_cast<const U*>(&value);
|
||||
|
||||
for (size_t n = 0; n < (sizeof(T) / sizeof(U)); ++n)
|
||||
{
|
||||
result ^= bits[n];
|
||||
result *= 1099511628211ull;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static size_t hash_struct(const T& value)
|
||||
{
|
||||
static constexpr auto block_sz = sizeof(T);
|
||||
|
||||
if constexpr ((block_sz & 0x7) == 0)
|
||||
{
|
||||
return hash_struct_base<T, u64>(value);
|
||||
}
|
||||
|
||||
if constexpr ((block_sz & 0x3) == 0)
|
||||
{
|
||||
return hash_struct_base<T, u32>(value);
|
||||
}
|
||||
|
||||
if constexpr ((block_sz & 0x1) == 0)
|
||||
{
|
||||
return hash_struct_base<T, u16>(value);
|
||||
}
|
||||
|
||||
return hash_struct_base<T, u8>(value);
|
||||
}
|
||||
}
|
||||
+20
-72
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
#include "util/atomic.hpp"
|
||||
|
||||
//! Simple sizeless array base for concurrent access. Cannot shrink, only growths automatically.
|
||||
@@ -8,7 +8,7 @@
|
||||
//!
|
||||
//! T is the type of elements. Currently, default constructor of T shall be constexpr.
|
||||
//! N is initial element count, available without any memory allocation and only stored contiguously.
|
||||
template <typename T, std::size_t N>
|
||||
template <typename T, usz N>
|
||||
class lf_array
|
||||
{
|
||||
// Data (default-initialized)
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
T& operator [](std::size_t index)
|
||||
T& operator [](usz index)
|
||||
{
|
||||
if (index < N) [[likely]]
|
||||
{
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
|
||||
//! Simple lock-free FIFO queue base. Based on lf_array<T, N> itself. Currently uses 32-bit counters.
|
||||
//! There is no "push_end" or "pop_begin" provided, the queue element must signal its state on its own.
|
||||
template<typename T, std::size_t N>
|
||||
template<typename T, usz N>
|
||||
class lf_fifo : public lf_array<T, N>
|
||||
{
|
||||
// LSB 32-bit: push, MSB 32-bit: pop
|
||||
@@ -161,11 +161,6 @@ public:
|
||||
return m_ptr == rhs.m_ptr;
|
||||
}
|
||||
|
||||
bool operator !=(const lf_queue_iterator& rhs) const
|
||||
{
|
||||
return m_ptr != rhs.m_ptr;
|
||||
}
|
||||
|
||||
T& operator *() const
|
||||
{
|
||||
return m_ptr->m_data;
|
||||
@@ -307,14 +302,25 @@ public:
|
||||
delete m_head.load();
|
||||
}
|
||||
|
||||
void wait() noexcept
|
||||
template <atomic_wait::op Flags = atomic_wait::op::eq>
|
||||
void wait(std::nullptr_t /*null*/ = nullptr) noexcept
|
||||
{
|
||||
if (m_head == nullptr)
|
||||
{
|
||||
m_head.wait(nullptr);
|
||||
m_head.template wait<Flags>(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
const volatile void* observe() const noexcept
|
||||
{
|
||||
return m_head.load();
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return m_head != nullptr;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void push(Args&&... args)
|
||||
{
|
||||
@@ -343,9 +349,9 @@ public:
|
||||
|
||||
// Apply func(data) to each element, return the total length
|
||||
template <typename F>
|
||||
std::size_t apply(F func)
|
||||
usz apply(F func)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
usz count = 0;
|
||||
|
||||
for (auto slice = pop_all(); slice; slice.pop_front())
|
||||
{
|
||||
@@ -354,64 +360,6 @@ public:
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// Iterator that enables direct endless range-for loop: for (auto* ptr : queue) ...
|
||||
class iterator
|
||||
{
|
||||
lf_queue* _this = nullptr;
|
||||
|
||||
lf_queue_slice<T> m_data;
|
||||
|
||||
public:
|
||||
constexpr iterator() = default;
|
||||
|
||||
explicit iterator(lf_queue* _this)
|
||||
: _this(_this)
|
||||
{
|
||||
m_data = _this->pop_all();
|
||||
}
|
||||
|
||||
bool operator !=(const iterator& rhs) const
|
||||
{
|
||||
return _this != rhs._this;
|
||||
}
|
||||
|
||||
T* operator *() const
|
||||
{
|
||||
return m_data ? m_data.get() : nullptr;
|
||||
}
|
||||
|
||||
iterator& operator ++()
|
||||
{
|
||||
if (m_data)
|
||||
{
|
||||
m_data.pop_front();
|
||||
}
|
||||
|
||||
if (!m_data)
|
||||
{
|
||||
m_data = _this->pop_all();
|
||||
|
||||
if (!m_data)
|
||||
{
|
||||
_this->wait();
|
||||
m_data = _this->pop_all();
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator{this};
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator{};
|
||||
}
|
||||
};
|
||||
|
||||
// Concurrent linked list, elements remain until destroyed.
|
||||
|
||||
+11
-9
@@ -1,8 +1,10 @@
|
||||
#include "mutex.h"
|
||||
|
||||
#include "util/asm.hpp"
|
||||
|
||||
void shared_mutex::imp_lock_shared(u32 val)
|
||||
{
|
||||
verify("shared_mutex underflow" HERE), val < c_err;
|
||||
ensure(val < c_err); // "shared_mutex underflow"
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
@@ -23,14 +25,14 @@ void shared_mutex::imp_lock_shared(u32 val)
|
||||
return;
|
||||
}
|
||||
|
||||
verify("shared_mutex overflow" HERE), (old % c_sig) + c_one < c_sig;
|
||||
ensure((old % c_sig) + c_one < c_sig); // "shared_mutex overflow"
|
||||
imp_wait();
|
||||
lock_downgrade();
|
||||
}
|
||||
|
||||
void shared_mutex::imp_unlock_shared(u32 old)
|
||||
{
|
||||
verify("shared_mutex underflow" HERE), old - 1 < c_err;
|
||||
ensure(old - 1 < c_err); // "shared_mutex underflow"
|
||||
|
||||
// Check reader count, notify the writer if necessary
|
||||
if ((old - 1) % c_one == 0)
|
||||
@@ -59,19 +61,19 @@ void shared_mutex::imp_wait()
|
||||
break;
|
||||
}
|
||||
|
||||
m_value.wait(old);
|
||||
m_value.wait(old, c_sig);
|
||||
}
|
||||
}
|
||||
|
||||
void shared_mutex::imp_signal()
|
||||
{
|
||||
m_value += c_sig;
|
||||
m_value.notify_one();
|
||||
m_value.notify_one(c_sig);
|
||||
}
|
||||
|
||||
void shared_mutex::imp_lock(u32 val)
|
||||
{
|
||||
verify("shared_mutex underflow" HERE), val < c_err;
|
||||
ensure(val < c_err); // "shared_mutex underflow"
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
@@ -90,13 +92,13 @@ void shared_mutex::imp_lock(u32 val)
|
||||
return;
|
||||
}
|
||||
|
||||
verify("shared_mutex overflow" HERE), (old % c_sig) + c_one < c_sig;
|
||||
ensure((old % c_sig) + c_one < c_sig); // "shared_mutex overflow"
|
||||
imp_wait();
|
||||
}
|
||||
|
||||
void shared_mutex::imp_unlock(u32 old)
|
||||
{
|
||||
verify("shared_mutex underflow" HERE), old - c_one < c_err;
|
||||
ensure(old - c_one < c_err); // "shared_mutex underflow"
|
||||
|
||||
// 1) Notify the next writer if necessary
|
||||
// 2) Notify all readers otherwise if necessary (currently indistinguishable from writers)
|
||||
@@ -121,7 +123,7 @@ void shared_mutex::imp_lock_upgrade()
|
||||
// Convert to writer lock
|
||||
const u32 old = m_value.fetch_add(c_one - 1);
|
||||
|
||||
verify("shared_mutex overflow" HERE), (old % c_sig) + c_one - 1 < c_sig;
|
||||
ensure((old % c_sig) + c_one - 1 < c_sig); // "shared_mutex overflow"
|
||||
|
||||
if (old % c_one == 1)
|
||||
{
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
#include "util/atomic.hpp"
|
||||
|
||||
// Shared mutex with small size (u32).
|
||||
|
||||
+3
-6
@@ -1,9 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "restore_new.h"
|
||||
#include "Utilities/rXml.h"
|
||||
#include "define_new_memleakdetect.h"
|
||||
|
||||
rXmlNode::rXmlNode() : handle()
|
||||
rXmlNode::rXmlNode()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -54,10 +52,10 @@ std::string rXmlNode::GetAttribute(const std::string &name)
|
||||
|
||||
std::string rXmlNode::GetNodeContent()
|
||||
{
|
||||
return handle.text().get();
|
||||
return handle.text().get();
|
||||
}
|
||||
|
||||
rXmlDocument::rXmlDocument() : handle()
|
||||
rXmlDocument::rXmlDocument()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -70,4 +68,3 @@ std::shared_ptr<rXmlNode> rXmlDocument::GetRoot()
|
||||
{
|
||||
return std::make_shared<rXmlNode>(handle.root());
|
||||
}
|
||||
|
||||
|
||||
+16
-3
@@ -1,6 +1,19 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#include <pugixml.hpp>
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wall"
|
||||
#pragma GCC diagnostic ignored "-Wextra"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#include <pugixml.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct rXmlNode
|
||||
@@ -13,7 +26,7 @@ struct rXmlNode
|
||||
std::string GetAttribute( const std::string &name);
|
||||
std::string GetNodeContent();
|
||||
|
||||
pugi::xml_node handle;
|
||||
pugi::xml_node handle{};
|
||||
};
|
||||
|
||||
struct rXmlDocument
|
||||
@@ -24,5 +37,5 @@ struct rXmlDocument
|
||||
void Read(const std::string& data);
|
||||
std::shared_ptr<rXmlNode> GetRoot();
|
||||
|
||||
pugi::xml_document handle;
|
||||
pugi::xml_document handle{};
|
||||
};
|
||||
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
#include "sema.h"
|
||||
|
||||
#include "util/asm.hpp"
|
||||
|
||||
void semaphore_base::imp_wait()
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
@@ -52,7 +54,7 @@ void semaphore_base::imp_wait()
|
||||
|
||||
void semaphore_base::imp_post(s32 _old)
|
||||
{
|
||||
verify("semaphore_base: overflow" HERE), _old < 0;
|
||||
ensure(_old < 0); // "semaphore_base: overflow"
|
||||
|
||||
m_value.notify_one();
|
||||
}
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
#include "util/atomic.hpp"
|
||||
|
||||
// Lightweight semaphore helper class
|
||||
|
||||
+8
-6
@@ -2,22 +2,24 @@
|
||||
|
||||
/* For internal use. Don't include. */
|
||||
|
||||
#include "types.h"
|
||||
#include "util/atomic.hpp"
|
||||
#include "dynamic_library.h"
|
||||
#include "util/types.hpp"
|
||||
#include "util/dyn_lib.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
#include <time.h>
|
||||
#include <ctime>
|
||||
#elif __linux__
|
||||
#include <errno.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/futex.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
@@ -67,7 +69,7 @@ inline int futex(volatile void* uaddr, int futex_op, uint val, const timespec* t
|
||||
};
|
||||
|
||||
std::mutex mutex;
|
||||
std::unordered_multimap<volatile void*, waiter*, pointer_hash<volatile void, alignof(int)>> map;
|
||||
std::unordered_multimap<volatile void*, waiter*> map;
|
||||
|
||||
int operator()(volatile void* uaddr, int futex_op, uint val, const timespec* timeout, uint mask)
|
||||
{
|
||||
|
||||
-1046
File diff suppressed because it is too large
Load Diff
-1093
File diff suppressed because it is too large
Load Diff
@@ -67,7 +67,7 @@ namespace utils
|
||||
int vnum2 = 0;
|
||||
|
||||
// Loop until both strings are processed
|
||||
for (size_t i = 0, j = 0; (i < v1.length() || j < v2.length());)
|
||||
for (usz i = 0, j = 0; (i < v1.length() || j < v2.length());)
|
||||
{
|
||||
// Storing numeric part of version 1 in vnum1
|
||||
while (i < v1.length() && v1[i] != '.')
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "util/types.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace utils
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
set(ENABLE_PCH OFF CACHE BOOL "Enables Precompiled header" FORCE)
|
||||
set(BUILD_EXTERNAL OFF CACHE BOOL "Build external dependencies in /External" FORCE)
|
||||
set(SKIP_GLSLANG_INSTALL ON CACHE BOOL "Skip installation" FORCE)
|
||||
set(ENABLE_SPVREMAPPER OFF CACHE BOOL "Enables building of SPVRemapper" FORCE)
|
||||
|
||||
+1
-1
Submodule Vulkan/glslang updated: 3ee5f2f1d3...18eef33bd7
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user