Compare commits

..

501 Commits

Author SHA1 Message Date
gymnast86 4b0a58b8f2 add hint signs to various maps 2026-07-23 05:06:31 -07:00
gymnast86 f16290d1e0 better accounting for custom flow/text ids 2026-07-23 00:58:20 -07:00
gymnast86 e9a84c2fb5 change default param value for BreakLines 2026-07-23 00:57:54 -07:00
gymnast86 c1d34d7b68 change default custom message attributes 2026-07-22 23:32:54 -07:00
gymnast86 d12cf18ce1 change name of default entry 2026-07-22 04:23:07 -07:00
gymnast86 1643474573 handle custom text id attributes 2026-07-22 04:17:26 -07:00
gymnast86 3d06c6607c account for custom flow indices in getInitNodeIndex 2026-07-22 04:17:07 -07:00
gymnast86 1d275f4ead actually save attribute overrides 2026-07-22 04:15:39 -07:00
gymnast86 957dbe976e add extra exit out of City in the Sky 2026-07-22 02:44:52 -07:00
gymnast86 ba994a4e65 add required dungeons to Midna hint text 2026-07-22 02:12:59 -07:00
gymnast86 21e75bac1c properly set flag for cutscene in Hyrule Castle 2026-07-22 00:46:11 -07:00
gymnast86 9b087aadda Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-07-21 00:57:59 -07:00
gymnast86 1aa81ff907 remove warp to start from menu (it's on midna now) 2026-07-21 00:55:06 -07:00
gymnast86 21a7823045 custom flow nodes and initial custom midna choices 2026-07-21 00:51:33 -07:00
gymnast86 a245876f7f Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-07-16 01:11:04 -07:00
gymnast86 1c59d124dc fix include 2026-07-15 01:50:15 -07:00
gymnast86 7766739df1 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-07-15 01:08:32 -07:00
gymnast86 0b23015ddb fix Hyrule Castle being wrongly considered a barren dungeon when placing "any dungeon" items 2026-07-15 00:49:30 -07:00
gymnast86 9537df2ee7 fixes for running standalone generator 2026-07-15 00:48:22 -07:00
gymnast86 9e6dd59e49 fix "any dungeon" items sometimes being placed wrong 2026-07-15 00:47:42 -07:00
gymnast86 fa34335a09 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-07-14 15:33:40 -07:00
gymnast86 a4c619ad58 move yeta fixes to flow patches 2026-07-14 15:24:34 -07:00
gymnast86 cf0c1c3160 fix goron mines key shards in tracker 2026-07-13 23:48:25 -07:00
gymnast86 6be65a461d fix include paths to not pollute d_com_inf_game.h 2026-07-13 22:50:41 -07:00
gymnast86 bb1c1447d0 fix conflicts 2026-07-13 16:55:08 -07:00
gymnast86 dce6b4c666 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-07-13 15:52:24 -07:00
gymnast86 9756612b35 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-07-02 20:01:09 -07:00
gymnast86 49f27acb2b fix rando config not saving when it should 2026-07-02 20:01:02 -07:00
gymnast86 d1ea637d22 add midna hair and charge ring colors 2026-07-02 20:00:47 -07:00
gymnast86 591c38e871 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-07-01 00:27:50 -07:00
gymnast86 a5bc71795e add various cosmetic options 2026-07-01 00:27:35 -07:00
gymnast86 26d0725c76 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-26 11:56:32 -07:00
gymnast86 1b3b493fbf reset rando context if current seed is deleted 2026-06-26 11:53:33 -07:00
gymnast86 f62a70f9d0 update starting time of day descriptions 2026-06-26 11:40:09 -07:00
gymnast86 ec2173db9f change seed option menu styling 2026-06-26 11:34:22 -07:00
gymnast86 563944d4a3 use updated shadow crystal bti from melonspeedruns 2026-06-26 11:32:59 -07:00
gymnast86 b8f69e82dd add shadow crystal icon 2026-06-25 08:57:34 -07:00
gymnast86 830b560933 text changes to account for long item names 2026-06-25 03:15:14 -07:00
gymnast86 6592871fa2 add mirror chamber access setting 2026-06-23 09:16:39 -07:00
gymnast86 e57c952deb print required dungeons to spoiler log 2026-06-21 16:18:07 -07:00
gymnast86 4239cea3d5 Fix arbiters grounds sometimes not being listed as a required dungeon 2026-06-21 15:59:39 -07:00
gymnast86 9bd34a0d02 fix gor liggs always setting item bit for 3 key shards 2026-06-21 09:07:54 -07:00
gymnast86 cce67c1809 fix dpad icon not drawing at unlocked framerates 2026-06-21 08:32:58 -07:00
gymnast86 6bf0dfd92a properly patch CT malo mart door to be open at any time of day 2026-06-20 10:24:17 -07:00
gymnast86 4d8fcfa551 add permalink sharing 2026-06-20 07:57:49 -07:00
gymnast86 a3de85fb4b Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-19 03:09:50 -07:00
gymnast86 08e0645ef8 add functionality for saving and loading presets 2026-06-19 03:08:12 -07:00
gymnast86 f20cf3c24e change spoiler log wording 2026-06-19 03:03:03 -07:00
gymnast86 b2dfdf4158 fix entrance metadata 2026-06-19 03:02:47 -07:00
gymnast86 99689258a2 misc cleanup 2026-06-17 23:56:37 -07:00
gymnast86 08345d01ed Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-17 03:01:05 -07:00
gymnast86 56d47d475f add button to reset settings to default 2026-06-17 03:00:40 -07:00
gymnast86 8a92efbe0d properly save rando file during autosave 2026-06-17 02:30:54 -07:00
gymnast86 1790ad6faf fix merge conflicts 2026-06-16 05:30:08 -04:00
gymnast86 e39c139b97 Merge branch 'main' of https://github.com/TwilitRealm/dusklight into randomizer 2026-06-16 05:18:57 -04:00
gymnast86 54b3545736 properly refocus child element after deleting a seed 2026-06-16 05:14:32 -04:00
gymnast86 2428ca2efe Merge branch 'main' of https://github.com/TwilitRealm/dusklight into randomizer 2026-06-15 06:04:32 -04:00
gymnast86 05d9cf0402 make requirement tooltips more readable 2026-06-15 06:03:08 -04:00
gymnast86 2651640ee0 Merge branch 'main' of https://github.com/TwilitRealm/dusklight into randomizer 2026-06-13 20:59:48 -04:00
gymnast86 f8c5a8988b fix getTempleKeysFound 2026-06-13 20:57:32 -04:00
gymnast86 544964c1a5 properly implement no logic 2026-06-13 07:56:51 -04:00
gymnast86 7bd3e9cafd move saved file seed load to file select instead of file start 2026-06-12 21:25:49 -04:00
gymnast86 8999c4c9c5 remove asheis sketch after showing it to Ralis 2026-06-12 20:48:24 -04:00
gymnast86 917def4732 fix missed string 2026-06-12 20:48:02 -04:00
gymnast86 0516282bb6 cleanup settings_list.yaml and related files 2026-06-12 19:26:09 -04:00
gymnast86 d855efe513 remove instances of double actors 2026-06-10 23:05:25 -06:00
gymnast86 28733f5c15 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-10 06:23:31 -07:00
gymnast86 b2ac2d6600 overhaul seed selection to be on file creation 2026-06-10 06:22:03 -07:00
gymnast86 68bebfad3a Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-08 22:58:46 -07:00
gymnast86 a0f5b250b4 Merge branch 'randomizer' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-08 22:58:41 -07:00
gymnast86 cb70f2c3b3 use C-style array for adjectives and nouns 2026-06-08 22:58:29 -07:00
Luke Street 5851954ca1 Revert "Move RegisteredConfigVars to function-local static"
This reverts commit ea09dd73c6.
2026-06-08 22:16:10 -06:00
gymnast86 c65f0bb0ac Merge branch 'randomizer' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-08 21:06:52 -07:00
gymnast86 038254db48 decouple generation modal from config menu 2026-06-08 21:05:30 -07:00
Luke Street c1997b3d68 Remove huge TLS variable; fixes Linux issues
Randomizer code was allocating a 25MB buffer
for file I/O using thread-local storage,
which was starving the stack space of threads
created on Linux.

The buffer appears to be a workaround for
Wii U homebrew I/O, so we can just disable
it altogether.

Resolves #1836
2026-06-08 21:52:12 -06:00
gymnast86 474a7dce00 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-08 18:08:13 -07:00
gymnast86 382f33d021 fix some tracker locations not getting updated fast enough 2026-06-08 18:05:21 -07:00
gymnast86 b743a762b4 fix swapped flags for male/female beetle 2026-06-08 16:04:58 -07:00
gymnast86 302abd6b65 track twilight tears in tracker 2026-06-08 13:44:35 -07:00
gymnast86 3f6ae4324b Merge branch 'randomizer' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-08 00:12:19 -07:00
gymnast86 dccded964b fix hang on swim spawn with no water 2026-06-07 21:09:31 -07:00
Luke Street ea09dd73c6 Move RegisteredConfigVars to function-local static
Defers initialization until used to avoid crash
with specific file-local static initialization ordering.

Fixes #1836
2026-06-07 21:08:41 -06:00
gymnast86 c426b52a15 use constexpr for seed nouns and adjectives 2026-06-07 09:32:53 -07:00
gymnast86 41e0a81c39 fix rando first item bits in editor 2026-06-07 00:54:13 -07:00
gymnast86 5b6f2f6e91 fix some first item bits accidentally getting unset 2026-06-06 23:39:18 -07:00
gymnast86 bbea07ba9e fix boomerang sometimes not spinning as freestanding item 2026-06-06 21:41:16 -07:00
gymnast86 0f0dca5514 fix boomerang potentially not being collected as freestanding item 2026-06-06 21:11:40 -07:00
gymnast86 3fb86dbac8 better plando error messaging 2026-06-06 20:17:51 -07:00
gymnast86 7e367c1e15 parameter cleanup 2026-06-06 18:21:01 -07:00
gymnast86 46e81963e2 focus seed gen modal after seed generates 2026-06-06 17:39:44 -07:00
gymnast86 4f1d4cde3d Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-06 11:14:02 -07:00
gymnast86 45c8fa9f19 update seed generation modal when generation finishes 2026-06-06 11:11:17 -07:00
gymnast86 87635d3cf7 Coro bottle hint in text 2026-06-06 06:46:58 -07:00
gymnast86 e5324c7562 remove old comments 2026-06-05 22:58:58 -07:00
gymnast86 03593def22 fix setting jumpstrike event bit 2026-06-05 22:45:42 -07:00
gymnast86 2ae5518c81 SetPsuedoClass -> SetClass 2026-06-05 21:23:10 -07:00
gymnast86 bc45bf27c2 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-05 21:11:36 -07:00
gymnast86 7d2c9776ea implement excluded locations menu 2026-06-05 21:10:57 -07:00
gymnast86 fbf4fcc50c add crc32.hpp to files.cmake 2026-06-04 18:46:38 -07:00
gymnast86 1868d698f5 include crc32.hpp 2026-06-04 18:05:08 -07:00
gymnast86 d858626be1 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-04 17:56:36 -07:00
gymnast86 f00ad8e0ea maybe fix linux crash 2026-06-04 17:55:48 -07:00
gymnast86 7b521aef02 fix missing location category 2026-06-03 19:39:25 -07:00
gymnast86 4721b8da50 Merge branch 'randomizer' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-03 16:49:15 -07:00
gymnast86 b06af0e057 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-03 16:48:57 -07:00
gymnast86 518dea482e fix lost woods boulder poe logic 2026-06-03 16:48:50 -07:00
gymnast86 daf2f18369 fix asheis sketch disappearing 2026-06-03 16:48:33 -07:00
CraftyBoss 9307d8abde dont throw on failed to obtain item name, fix getTempleKeysFound not checking flag correctly 2026-06-03 16:47:04 -07:00
gymnast86 b3dbf2c71b Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-02 23:25:57 -07:00
gymnast86 4bb5f320c3 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-02 22:15:42 -07:00
gymnast86 f1357f09ed add starting inventory management to UI 2026-06-02 22:15:34 -07:00
gymnast86 e3eb63f158 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-01 19:28:36 -07:00
gymnast86 47c0a399e1 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-01 02:07:47 -07:00
gymnast86 dfdd5250bd fix prologue items sometimes being in excluded locations 2026-06-01 02:07:37 -07:00
gymnast86 ba7211126c only spawn donation bridge after twilights are cleared 2026-06-01 01:54:28 -07:00
gymnast86 ef607434dd fix twilight clear checks 2026-06-01 01:53:43 -07:00
gymnast86 f12838ea3b fix required dungeons sign when no dungeons are required 2026-06-01 01:53:04 -07:00
gymnast86 dc88e11115 implement framework for custom text in other languages 2026-05-31 01:41:12 -07:00
gymnast86 e671ed748b change some custom text coloring 2026-05-31 01:38:49 -07:00
gymnast86 98633a5cb6 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-30 19:28:29 -07:00
gymnast86 6c1aeb0d0a reset conversation bit after exiting ordon shield house 2026-05-30 19:28:24 -07:00
gymnast86 a2d41bcfba Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-29 22:57:56 -07:00
gymnast86 96ed5c671b fix garbled ice trap audio 2026-05-29 22:57:38 -07:00
gymnast86 de12d277d0 restricted fills cleanup 2026-05-29 11:31:29 -07:00
gymnast86 3b8ec9efa6 quick no logic implementation 2026-05-29 11:31:13 -07:00
gymnast86 39b079ddb9 fix plentiful item pool crash 2026-05-28 20:33:20 -07:00
gymnast86 e2790d922a reorganize includes 2026-05-28 20:25:26 -07:00
gymnast86 afed2c1774 Merge branch 'randomizer' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-28 20:22:12 -07:00
gymnast86 46a67c658c Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-28 20:21:14 -07:00
gymnast86 351afd6686 add item text replacements 2026-05-28 20:04:20 -07:00
gymnast86 485374abba Outside Castle Town -> South of Castle Town 2026-05-28 20:02:21 -07:00
gymnast86 8ecd848307 filter out nonprogress locations when placing goal items 2026-05-28 20:02:03 -07:00
CraftyBoss c4a13c8c10 add WIP inventory window in check tracker, only decrease available locations if check is accessible
also fixed issue with getSaveItemPool not counting base skybook item, as well as Aurus Memo if it was used
2026-05-28 01:16:53 -07:00
CraftyBoss 313e9be99d Merge remote-tracking branch 'origin/main' into randomizer
# Conflicts:
#	src/d/actor/d_a_npc_kkri.cpp
#	src/d/actor/d_a_npc_rafrel.cpp
2026-05-28 01:15:08 -07:00
gymnast86 d79088ba05 Merge branch 'randomizer' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-27 10:54:52 -07:00
gymnast86 3aa7abe73f add required dungeons to links house sign 2026-05-27 10:54:35 -07:00
CraftyBoss 8e38f27602 sort checks by status, add hide button, cleanup code layout 2026-05-27 02:00:48 -07:00
Luke Street 7543db2222 Merge branch 'main' into randomizer 2026-05-26 20:58:20 -06:00
gymnast86 32e553e38d Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-25 23:41:18 -07:00
gymnast86 089a947c30 rework some prologue logic 2026-05-25 23:41:10 -07:00
gymnast86 83a5ccce92 fix blank letters 2026-05-25 22:43:09 -07:00
gymnast86 48de086d65 fix logic tests path 2026-05-25 22:39:30 -07:00
gymnast86 5a61b912bb Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-24 22:00:10 -07:00
gymnast86 4e92b22c5d fix auru having a model scale of 0 2026-05-24 21:59:26 -07:00
gymnast86 ede9697dae update bobm refill logic 2026-05-24 19:12:17 -07:00
gymnast86 580b772c3c update tracker flags for various locations 2026-05-24 19:12:10 -07:00
gymnast86 143b548102 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-24 10:32:31 -07:00
gymnast86 15742c71f3 fix aurus memo temporarily disappearing 2026-05-24 10:29:49 -07:00
CraftyBoss 40f753e18b Merge remote-tracking branch 'origin/main' into randomizer
# Conflicts:
#	src/f_op/f_op_actor_mng.cpp
2026-05-24 03:40:08 -07:00
CraftyBoss 65f4048a41 show item name when location is collected, fix ordon shield flag being incorrect 2026-05-23 19:50:45 -07:00
gymnast86 e78a198adf fix horse call get item func 2026-05-23 11:44:21 -07:00
gymnast86 75d86ab296 fix ilia quest logic setting logic 2026-05-23 11:44:05 -07:00
gymnast86 62e48984bf Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-23 09:11:07 -07:00
gymnast86 deb213d07a path cleanup 2026-05-23 09:10:58 -07:00
gymnast86 484c5e8bf3 variable change 2026-05-23 09:10:01 -07:00
gymnast86 bb67fc991d fix isStageItem check 2026-05-23 09:09:13 -07:00
gymnast86 7326a619da fix tears in itempool 2026-05-23 09:08:53 -07:00
CraftyBoss 4ce5800a33 fix some config options not saving on change, move check obtained checking to tool func, tracker cleanup 2026-05-23 03:05:54 -07:00
CraftyBoss 66a8af31b3 fix non msvc compile error 2026-05-23 00:20:38 -07:00
CraftyBoss 85fe76b5be add tracker_isStageItem for Freestanding Item checking 2026-05-22 23:03:06 -07:00
CraftyBoss ffa1fd5da4 add ability to toggle tracker in rmlui (hack for now), show area remaining checks, misc debugging info 2026-05-22 22:49:44 -07:00
gymnast86 3d2c5633cd set nonprogress locations in tracker 2026-05-22 20:35:15 -07:00
gymnast86 08ce522edb add flag checking for more intuitve location marking 2026-05-22 19:58:05 -07:00
gymnast86 ab007b4c44 revert updateTracker check 2026-05-22 19:53:09 -07:00
gymnast86 2cf2442dc8 update location metadata for switch/event flags 2026-05-21 20:03:32 -07:00
gymnast86 7354bfc163 remove unused include 2026-05-21 20:02:18 -07:00
gymnast86 7bca56ea80 uncomment option 2026-05-21 10:04:48 -07:00
gymnast86 42eb9ef518 use region for areas instead of area name 2026-05-21 10:04:38 -07:00
gymnast86 be4a1d8838 don't search if type is NO_SEARCH 2026-05-21 05:53:27 -07:00
gymnast86 fd523a7e4d more intuitive GetWorld function 2026-05-21 05:52:48 -07:00
gymnast86 650b56beee more guarding against null stag info 2026-05-21 05:51:33 -07:00
CraftyBoss 1e3f097e63 start work on detecting if a check has been collected in tracker
the func getStageSaveId in randomizer/game/tools.cpp might not be totally accurate, and is based off google spreadsheet data
2026-05-21 03:26:10 -07:00
CraftyBoss 9fd5678ae4 Merge remote-tracking branch 'origin/main' into randomizer 2026-05-21 00:32:38 -07:00
CraftyBoss dcf6268444 sort tracker checks by area name, uncomment manual update button for now, always generate search when updating tracker 2026-05-20 21:17:27 -07:00
gymnast86 1f4370af85 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-20 17:42:10 -07:00
gymnast86 ed458dc2b3 backend tracker updates 2026-05-20 17:41:03 -07:00
gymnast86 7cebc42266 comments 2026-05-20 14:00:58 -07:00
gymnast86 0d819b215d comment out other options 2026-05-20 13:58:37 -07:00
gymnast86 8113fc3088 Remove entrance rando options until they're hooked up 2026-05-20 13:56:50 -07:00
gymnast86 78bc0216fb Merge branch 'randomizer' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-19 22:13:29 -07:00
gymnast86 b74603c883 basic backend for tracking 2026-05-19 22:13:06 -07:00
gymnast86 9e8b451462 fix starting time of day button 2026-05-19 19:31:05 -07:00
CraftyBoss d25695be0e implement basic warp to start button in rando menu
serves as a sort of placeholder until Midna can be properly edited to behave like console rando
2026-05-19 17:40:49 -07:00
CraftyBoss ba9dc8e9ba finish up rando config ui, remove randomizerEnabled CVar, fix seed strings not saving to config
i would like to have someone more aquainted with the UI system to look over the config menu at some point, as i do think it could be better.
2026-05-19 16:13:50 -07:00
gymnast86 ddb9816158 use config path for imgui seed selection 2026-05-19 08:43:56 -07:00
gymnast86 33e19f58e0 github action fixes 2026-05-19 07:56:32 -07:00
gymnast86 ece92765c9 use dusk config path for settings file 2026-05-19 00:51:17 -07:00
CraftyBoss c2dea2ab8f switch GenerateSeed to use c++ rand instead 2026-05-18 23:21:08 -07:00
CraftyBoss e0dea86134 embed rando generator yamls into binary 2026-05-18 22:37:55 -07:00
gymnast86 8409c2ab9f Merge branch 'randomizer' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-18 20:00:57 -07:00
gymnast86 3eb4181b9c Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-18 20:00:51 -07:00
gymnast86 0d33d44e75 fix crash after getting Ook item 2026-05-18 20:00:44 -07:00
CraftyBoss 6ea50f33e4 remove fog lantern cooldown while rando is active 2026-05-18 19:17:34 -07:00
CraftyBoss 769b8f02c8 optimize config option finding a bit, add optional settings in config menu, load last generated seed and set generator seed 2026-05-18 19:14:42 -07:00
gymnast86 d77da3fba3 don't show special text for 20 poe souls 2026-05-18 17:50:08 -07:00
gymnast86 ea0c697afa fix key count inconsistency 2026-05-18 11:05:46 -07:00
gymnast86 6321bcf0d8 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-18 07:31:38 -07:00
gymnast86 1e7e9b3513 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-17 17:40:24 -07:00
gymnast86 63e7fb4187 Merge branch 'randomizer' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-17 17:39:59 -07:00
gymnast86 453accc674 draw d-pad icon for quest item slot 2026-05-17 17:39:53 -07:00
madeline a565601849 fix rando_config.cpp on linux maybe 2026-05-17 16:45:18 -07:00
gymnast86 e92a3b4a90 fix epona crash on ordon layer 0 2026-05-17 15:52:16 -07:00
gymnast86 141ddafdc8 another tbox id swap 2026-05-17 13:47:03 -07:00
gymnast86 007561874d Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-17 13:41:36 -07:00
gymnast86 b167124a70 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-17 07:07:09 -07:00
gymnast86 879c68f8a3 fix incorrect stage check 2026-05-17 07:07:02 -07:00
gymnast86 ccaee02c2e Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-17 02:19:59 -07:00
gymnast86 ff498af6e8 add horse jump scob on post mdh kak gorge 2026-05-17 02:19:24 -07:00
gymnast86 9c3420bcc7 fix midna being on players back 2026-05-17 01:56:24 -07:00
gymnast86 23a6719e99 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-16 01:56:46 -07:00
gymnast86 95c1a93332 poe soul option swap 2026-05-16 01:56:37 -07:00
gymnast86 63a91bffde another tbox id swap 2026-05-16 01:56:17 -07:00
gymnast86 d33b3c16e1 zlib cmake fix 2026-05-16 01:56:06 -07:00
gymnast86 33e2ffbb6e Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-15 17:14:46 -07:00
gymnast86 491a73f517 fix swapped tbox IDs 2026-05-15 15:09:54 -07:00
gymnast86 54efc49bd8 fix lake hylia poe logic 2026-05-15 15:09:41 -07:00
gymnast86 f6eaa64156 don't check time when going into malo mart 2026-05-15 11:17:25 -07:00
gymnast86 ed1f21f333 allow overriding flw types 2026-05-15 11:16:11 -07:00
gymnast86 0a0f1e9a04 rando rider ub 2026-05-15 09:09:19 -07:00
gymnast86 64720ef0e0 membit onSwitch patches 2026-05-15 09:08:51 -07:00
gymnast86 b213ae2faa more boulder rupee layer patches 2026-05-15 09:08:15 -07:00
gymnast86 d7e0c240d0 fix domain rock rupee layers 2026-05-15 08:42:14 -07:00
gymnast86 56de23e2e6 fix itempool size 2026-05-15 03:39:44 -07:00
gymnast86 0862408ee8 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-15 02:46:23 -07:00
gymnast86 b2b74e5c4d fix transform after faron twilight 2026-05-15 02:46:08 -07:00
gymnast86 39da278394 fix gate to north faron 2026-05-15 02:32:15 -07:00
gymnast86 ec2f2753a2 update versioning in logs 2026-05-15 01:10:58 -07:00
gymnast86 89a0702d2b put kak bomb rock hp on twilight layer 2026-05-15 00:59:49 -07:00
gymnast86 9d94e9684f Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-14 08:00:45 -07:00
gymnast86 f8d01ae6d2 onEventBit patches 2026-05-14 08:00:34 -07:00
gymnast86 9f400543c2 update startflags 2026-05-14 08:00:09 -07:00
gymnast86 3861bf5506 add twilight layer to eldin boulder rupees 2026-05-14 06:44:20 -07:00
gymnast86 5c745735d7 fix faron boulder rupee layers 2026-05-14 06:13:26 -07:00
gymnast86 886fb7f2db Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-14 04:09:12 -07:00
gymnast86 01d0d12af0 comment 2026-05-14 04:08:35 -07:00
gymnast86 c0f882845d add barriers to prevent early lanayru twilight access 2026-05-13 18:28:48 -07:00
gymnast86 7225fb25dc Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-13 17:04:13 -07:00
gymnast86 5ab46c604b always show reekfish scent path after having smelled reekfish 2026-05-13 17:04:06 -07:00
gymnast86 f3b29d97d0 fix bo house door patches 2026-05-13 06:55:25 -07:00
gymnast86 9447f4e89b fix LH cave chest metadata 2026-05-13 05:09:33 -07:00
gymnast86 7db5386885 use main zlib 2026-05-13 02:47:40 -07:00
gymnast86 9c1617d423 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-13 02:24:56 -07:00
gymnast86 4c4e3e4b10 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-11 14:13:11 -07:00
gymnast86 4db50d2843 fix progressive items in chests on the same stage 2026-05-11 14:05:23 -07:00
gymnast86 ba5a59eee2 Foolish items 2026-05-11 13:47:17 -07:00
CraftyBoss 5e69c7bdce Merge remote-tracking branch 'origin/main' into randomizer
# Conflicts:
#	files.cmake
#	src/m_Do/m_Do_main.cpp
2026-05-10 23:14:50 -07:00
CraftyBoss 04d9640eff add config menu and hook it up into current config system
currently any options that requires additional settings, like "Hyrule Barrier Requirements", wont actually have any additional options yet until i figure out a clean way to handle that
2026-05-10 23:13:02 -07:00
CraftyBoss 83480110fd Merge branch 'main' into randomizer 2026-05-10 15:16:07 -07:00
gymnast86 5038068905 patch spawns between faron field and outside sct to not be inside rocks 2026-05-10 10:45:29 -07:00
gymnast86 7388213715 allow patching of PLYR objects 2026-05-10 10:45:04 -07:00
gymnast86 0e1e64fe7d Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-10 09:56:06 -07:00
gymnast86 f48a3be466 patch cits objects 2026-05-10 09:55:52 -07:00
gymnast86 61835c05ba add support for patching objects in stage.dzs 2026-05-10 09:54:55 -07:00
gymnast86 762a597eba delete midna trigger that sometimes prevents going north in palace 2026-05-10 05:12:17 -07:00
gymnast86 69283fc611 remove grove portal fight walls 2026-05-10 04:51:31 -07:00
gymnast86 b0efe464c0 make shoe shiner always available 2026-05-10 04:05:58 -07:00
gymnast86 a6fda86ebf fix sera bottle check if faorn twilight is cleared 2026-05-10 03:02:27 -07:00
gymnast86 4b363dab06 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-10 01:26:10 -07:00
gymnast86 77ae5fd0b3 implement temple of time sword requirement 2026-05-10 01:25:44 -07:00
gymnast86 2890a663f3 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-09 10:38:57 -07:00
gymnast86 f263a33db2 change time of day with midna 2026-05-09 10:38:34 -07:00
gymnast86 99ee9c2f48 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-09 06:38:27 -07:00
gymnast86 1cfb22fdd9 handle unknown patch action 2026-05-09 06:38:14 -07:00
gymnast86 bf85d511a8 make the gate to KB2 stay open permanently once it's been unlocked 2026-05-09 06:24:27 -07:00
gymnast86 dc9dce2cd7 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-09 04:39:24 -07:00
gymnast86 8333ae35a8 refactor object overrides 2026-05-09 04:38:38 -07:00
gymnast86 ced018794f remove invisible wall blocking north palace 2026-05-09 01:52:27 -07:00
gymnast86 bfb715e11a Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-08 16:26:52 -07:00
gymnast86 9e9f36e484 autoskip cutscenes when skip major cutscenes is on 2026-05-08 16:21:26 -07:00
gymnast86 38031e2545 set all letters obtained when skip minor cutscenes is on 2026-05-08 16:00:42 -07:00
gymnast86 2dea7375ef custom text for donating 100 rupees to charlo 2026-05-08 09:11:36 -07:00
gymnast86 48bfcec0a3 missed include 2026-05-07 23:24:45 -07:00
gymnast86 7a4c23fa33 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-07 23:23:16 -07:00
gymnast86 0014be0e82 implement custom item text 2026-05-07 23:17:58 -07:00
gymnast86 870bd6476c show rando stats by default 2026-05-06 18:41:59 -07:00
gymnast86 96d9b5e7b1 update old category name 2026-05-06 15:35:20 -07:00
gymnast86 09a73d5828 organize items.yaml 2026-05-06 09:06:46 -07:00
gymnast86 e14d1f1f68 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-06 07:56:33 -07:00
gymnast86 9f6c39754b rework actor additions 2026-05-06 07:56:17 -07:00
gymnast86 eda9991e6a sols check 2026-05-06 07:53:02 -07:00
gymnast86 95e699fb63 don't transform in twilight fog if the player doesn't have shadow crystal 2026-05-06 03:48:06 -07:00
gymnast86 618d5b5733 fix data typos 2026-05-06 03:27:28 -07:00
gymnast86 2ececa3206 update goal flags during play 2026-05-06 03:27:14 -07:00
gymnast86 4fddaba76b fix conflict 2026-05-05 21:33:24 -07:00
gymnast86 045df82445 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-05 21:33:06 -07:00
gymnast86 b3833be529 don't try to play get item cutscene when swimming or snowboarding 2026-05-05 21:21:47 -07:00
gymnast86 f45aa6040e fix multiple progressive items on the same stage giving the same item 2026-05-05 21:20:56 -07:00
gymnast86 25b273a726 fix single arrow drops being too large 2026-05-05 21:12:24 -07:00
gymnast86 3e99420527 allow keeping ooccoo jr through dungeon exits 2026-05-05 05:13:26 -07:00
gymnast86 f6e526b187 fix missed metadata 2026-05-05 04:15:53 -07:00
gymnast86 23567fba42 fix boss arena music 2026-05-05 03:47:42 -07:00
gymnast86 255a55d4c8 remove uneeded code 2026-05-05 02:46:52 -07:00
gymnast86 d7ca855d9a Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-05 02:40:56 -07:00
gymnast86 e8318e2eb3 switch fishing hole bottle to FLW message patch 2026-05-05 02:26:18 -07:00
gymnast86 f4992aa378 data cleanup 2026-05-05 02:08:51 -07:00
gymnast86 97388be8e5 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-04 23:58:32 -07:00
gymnast86 dbad1a4832 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-04 22:26:07 -07:00
gymnast86 40949474a1 wooden statue check 2026-05-04 22:23:30 -07:00
gymnast86 1166b58447 telma invoice check 2026-05-04 10:34:05 -07:00
gymnast86 2c7cfa8951 ilia reward and hdiden village checks 2026-05-04 08:37:46 -07:00
gymnast86 89621dbff5 allow swapping between different trade quest items 2026-05-04 06:47:09 -07:00
gymnast86 18f688e4b3 fix blank item slot 2026-05-04 06:14:04 -07:00
gymnast86 354d9b2fde Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-03 18:53:42 -07:00
gymnast86 bc7faadc02 bulblin key 2026-05-03 18:52:59 -07:00
gymnast86 c265207c92 ball and chain check 2026-05-03 17:58:11 -07:00
gymnast86 05678f1ddc snowpeak mansion map check 2026-05-03 17:11:09 -07:00
gymnast86 cf015c4219 goron elder checks 2026-05-03 16:49:14 -07:00
gymnast86 a11427a48f dungeon reward and boss heart container checks 2026-05-03 16:06:45 -07:00
gymnast86 c87d7e3875 gale boomerang check 2026-05-03 06:56:57 -07:00
gymnast86 75f6337985 forest temple baba key 2026-05-03 06:28:57 -07:00
gymnast86 71f33021cc comment consistency 2026-05-03 05:57:56 -07:00
gymnast86 5b52f13f4b Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-03 05:34:18 -07:00
gymnast86 0a8cbc8f08 cave of ordeals fairy check 2026-05-03 05:33:13 -07:00
gymnast86 28e907aafd bulblin camp checks 2026-05-03 04:31:39 -07:00
gymnast86 7018796b93 snowboard racing check 2026-05-03 03:13:15 -07:00
gymnast86 b28e21fa18 snowboarding rupees 2026-05-03 02:28:18 -07:00
gymnast86 afc53ce1b2 ashei sketch check 2026-05-03 01:25:29 -07:00
gymnast86 4b0564779f underwater goron check 2026-05-03 01:13:47 -07:00
gymnast86 dc5fd98cfd zoras domain rupee checks 2026-05-03 01:02:40 -07:00
gymnast86 e2c51ec45c Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-02 07:45:21 -07:00
gymnast86 38640354b0 fix getting fishing hole HP with fishing rod 2026-05-02 07:44:59 -07:00
gymnast86 0393fdad6d fishing hole bottle check 2026-05-02 06:08:09 -07:00
gymnast86 5fc0340603 iza 1 and 2 checks 2026-05-01 19:33:59 -07:00
gymnast86 99652c01ed uzr rupee checks 2026-05-01 19:04:32 -07:00
gymnast86 580d50ab05 comment 2026-05-01 18:25:20 -07:00
gymnast86 cfa680f2d8 fruit balloon minigame check 2026-05-01 18:24:02 -07:00
gymnast86 e4e438e1ba lanayru spring rupee checks 2026-05-01 18:14:14 -07:00
gymnast86 4ec1a0e52c lake hylia rupees 2026-05-01 09:52:26 -07:00
gymnast86 f251a3497d bridge of hylia rupee checks 2026-05-01 08:20:18 -07:00
gymnast86 05734d9e93 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-05-01 05:52:41 -07:00
gymnast86 30e4291f14 malo mart magic armor check 2026-05-01 05:52:25 -07:00
gymnast86 88770b90ab STAR minigame checks 2026-05-01 05:39:32 -07:00
gymnast86 5a22ce6321 charlo donation check 2026-05-01 05:23:43 -07:00
gymnast86 62b30d2dad properly spawn jovani house poe 2026-05-01 01:11:31 -07:00
gymnast86 5a5004793a Jovani poe reward checks 2026-05-01 01:11:21 -07:00
gymnast86 d0cb0c001a outside castle town rupees 2026-05-01 00:26:18 -07:00
gymnast86 7a246941f8 fix bomb drops always being blue rupees 2026-04-30 23:01:27 -07:00
gymnast86 c3ad0abd37 lanayru field rupee checks 2026-04-30 22:55:57 -07:00
gymnast86 91d6ec1f26 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-30 21:26:12 -07:00
gymnast86 a863ea253e remove todo 2026-04-30 21:25:51 -07:00
gymnast86 f5789aaebd turn off gravity for zant and stallord hc actors 2026-04-30 21:25:45 -07:00
gymnast86 438fd2fe71 goron springwater check 2026-04-30 21:11:01 -07:00
gymnast86 040094115b move item override checks into param init block 2026-04-30 21:10:51 -07:00
gymnast86 d4bc2daa89 simplify chest and freestanding item lookups 2026-04-30 19:19:42 -07:00
gymnast86 622920d8c0 rutela and ralis checks 2026-04-30 04:39:41 -07:00
gymnast86 2b9dd50a8d fix forest temple compass item resource 2026-04-30 04:36:02 -07:00
gymnast86 ff44cdfd3c talo sharpshooting check 2026-04-30 03:20:44 -07:00
gymnast86 3b0cc4c712 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-30 01:20:30 -07:00
gymnast86 71d73a9db4 barnes bomb bag check 2026-04-30 01:19:59 -07:00
gymnast86 4ef7511336 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-29 16:15:48 -07:00
gymnast86 9b34fd8f8f implement kak malo mart shop checks 2026-04-29 16:15:29 -07:00
gymnast86 a5cc64c2fe Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-28 14:45:45 -07:00
gymnast86 ce88c237a3 always make barne's shop available 2026-04-28 14:45:36 -07:00
gymnast86 cee8101b37 fix includes 2026-04-28 04:00:03 -07:00
gymnast86 409663711b Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-28 03:56:05 -07:00
gymnast86 decf925e5d remove todo 2026-04-28 03:55:58 -07:00
gymnast86 cbead7bbb0 setup shop model overrides 2026-04-28 03:55:51 -07:00
gymnast86 05e5023354 implement eldin rupee checks 2026-04-28 03:02:59 -07:00
gymnast86 3126605cd6 coro boulder rupees 2026-04-28 00:14:29 -07:00
gymnast86 0b932c1993 fix conflict 2026-04-28 00:14:22 -07:00
gymnast86 5ed72f4af2 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-27 23:35:59 -07:00
gymnast86 1a3aac4d05 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-27 21:31:34 -07:00
gymnast86 573414dc83 fix old category name 2026-04-27 16:00:44 -07:00
gymnast86 7132655d42 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-27 15:57:37 -07:00
gymnast86 318bf293ca Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-27 04:08:20 -07:00
gymnast86 3149f929c1 implement golden wolf checks 2026-04-27 04:05:36 -07:00
gymnast86 8acdbf03bf fix portal item ids 2026-04-27 03:52:48 -07:00
gymnast86 11a632511f fix wrong stage on chest near bulblin camp 2026-04-27 02:31:28 -07:00
gymnast86 33941d8ede update warp portal logic 2026-04-26 16:31:30 -07:00
gymnast86 01d217acb5 patch flight by fowl top chest to not always start closed 2026-04-26 04:12:09 -07:00
gymnast86 7c331fdb2c coro bottle check 2026-04-26 02:00:11 -07:00
gymnast86 f7d3cf32fd add red rupee behind canon 2026-04-26 01:59:57 -07:00
gymnast86 95ceb1241b Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-26 01:05:35 -07:00
gymnast86 5c9ff2f5fa properly clear item queue on file load 2026-04-26 01:04:49 -07:00
gymnast86 6b5e251037 auru check 2026-04-26 01:04:24 -07:00
gymnast86 4905718024 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-25 21:48:11 -07:00
gymnast86 00929789a1 add master sword and shadow crystal checks 2026-04-25 21:43:59 -07:00
gymnast86 8e3306f87f add master sword actor to grove layer 2 2026-04-25 21:43:32 -07:00
gymnast86 8ea4b7747d update poe todos 2026-04-25 03:44:36 -07:00
gymnast86 02852eb586 fix pill bug categories 2026-04-25 03:41:59 -07:00
gymnast86 7d9d398844 fix actor patching on room load 2026-04-25 03:35:19 -07:00
gymnast86 dfe6d10c07 implement poe checks 2026-04-25 03:07:25 -07:00
gymnast86 80f4284e82 implement item queue 2026-04-25 03:07:07 -07:00
gymnast86 c7c9b664e8 sky character checks 2026-04-25 00:32:23 -07:00
gymnast86 e2de904f8a fix progressive dominion rod check 2026-04-25 00:18:34 -07:00
gymnast86 1f593812c8 cleanup 2026-04-24 23:41:20 -07:00
gymnast86 d3d0016d16 label locations which are still TODO 2026-04-24 23:05:53 -07:00
gymnast86 b7adbde0d5 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-24 22:42:18 -07:00
gymnast86 94bfb8c9e3 implement freestanding heart pieces 2026-04-24 22:42:12 -07:00
gymnast86 8949a3a8ee Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-24 12:22:31 -07:00
gymnast86 80b0d11319 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-24 03:26:24 -07:00
gymnast86 49e8058f4e implement golden bugs 2026-04-24 03:25:33 -07:00
gymnast86 fccce91ea5 fix yaml field typo 2026-04-24 03:25:05 -07:00
gymnast86 8b117c8ed3 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-23 16:51:45 -07:00
gymnast86 e77fe61596 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-23 06:37:06 -07:00
gymnast86 0da8b4c6dc implement agitha rewards 2026-04-23 06:37:00 -07:00
gymnast86 726999c476 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-22 23:10:54 -07:00
gymnast86 f774cc689c Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-22 16:58:05 -07:00
gymnast86 498db43c62 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-22 03:47:20 -07:00
gymnast86 89f1c6c71f ordon freestanding rupees 2026-04-22 03:47:14 -07:00
gymnast86 c801cb2a84 update randomizer_isActive() 2026-04-21 23:25:34 -07:00
gymnast86 f069be5789 herding goats reward check 2026-04-21 23:16:26 -07:00
gymnast86 b4722177ca Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-21 22:38:37 -07:00
gymnast86 a36695a240 ordon shield check 2026-04-21 22:36:33 -07:00
gymnast86 148a3d23eb sera shop slingshot check 2026-04-21 22:05:38 -07:00
gymnast86 e7e5363c0c Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-21 21:51:09 -07:00
gymnast86 93cc3bd2ce ordon cat rescue check 2026-04-21 21:51:01 -07:00
gymnast86 52a53b64dc Ordon Sword check 2026-04-21 21:05:23 -07:00
gymnast86 fa473d48a9 implement Uli Cradle Delivery check 2026-04-21 20:54:07 -07:00
gymnast86 8774cfa31b fix conflicts 2026-04-21 18:51:14 -07:00
gymnast86 8270ec3050 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-21 18:50:43 -07:00
gymnast86 6113df21e0 fix stuff relating to getting the Iron Boots chest 2026-04-21 18:47:04 -07:00
gymnast86 dbdb4daa58 isEventBit patches 2026-04-21 18:40:44 -07:00
gymnast86 dd04da230f add necessary settings to rando context 2026-04-21 01:32:08 -07:00
gymnast86 7606998ba6 Patch Jovani to only give 60 reward if 20 reward has been gotten. 2026-04-17 18:23:40 -07:00
gymnast86 0f0c10d26a Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-17 18:02:14 -07:00
gymnast86 88dd4a2aae Patch bo to prevent softlock if chest doesn't contain iron boots 2026-04-17 14:44:39 -07:00
gymnast86 cc75af7cce Patch shadow beasts to set Iza flags even if they are defeated as wolf. 2026-04-17 14:36:43 -07:00
gymnast86 7520998aca Patch suits of armor to spawn regardless of boss flag value 2026-04-17 11:20:06 -07:00
gymnast86 ab28ae36e3 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-17 11:12:19 -07:00
gymnast86 88826bd5f8 Patch shad so he spawns until he gives the dominion rod check 2026-04-17 11:07:09 -07:00
gymnast86 39a9dd4029 Patch SPR locks to prevent softlock when opening them from behind. 2026-04-17 10:40:37 -07:00
gymnast86 23fe55fdca Add Yeta door patch for SPR 2026-04-17 09:27:23 -07:00
gymnast86 a31e388b3a Prevent game from removing bulblin camp key from inventory 2026-04-17 09:20:45 -07:00
gymnast86 3e241da2a4 patch Ilia 2026-04-17 09:11:03 -07:00
gymnast86 ce80d83c00 Patch Diababa and Ook to transform player if they are wolf to avoid softlocks 2026-04-17 09:06:32 -07:00
gymnast86 f62fb69a4d patch d_a_obj_life_container so only certain actors sparkle 2026-04-17 08:52:04 -07:00
gymnast86 782bf4e0b3 Patch Yeto and Yeta to not leave the dungeon even if the BK is obtained 2026-04-17 08:46:34 -07:00
gymnast86 727066e54e Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-17 00:17:50 -07:00
gymnast86 f13ecbaec7 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-16 23:45:07 -07:00
gymnast86 be390c3645 fix item scaling mistake 2026-04-16 23:44:58 -07:00
gymnast86 fdfe379824 remove enhancements from randomizer settings list 2026-04-16 22:25:50 -07:00
gymnast86 da2cb85aa1 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-16 19:50:26 -07:00
gymnast86 2b4598821b add imgui menu for generating and selecting seeds 2026-04-16 19:50:17 -07:00
gymnast86 4cd911a114 restructure randomizer folder 2026-04-15 19:55:46 -07:00
gymnast86 5484cd69b5 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-15 19:20:50 -07:00
gymnast86 1ff9421cea set starting time of day 2026-04-15 19:20:44 -07:00
gymnast86 c0e83af35e fix patch being in wrong spot 2026-04-15 19:20:28 -07:00
gymnast86 2c6d0b11dd Add warp portals to item pool 2026-04-15 15:36:20 -07:00
gymnast86 bab1cda97a Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-15 10:42:17 -07:00
gymnast86 da24b6a1e2 fix more startflags 2026-04-15 01:35:46 -07:00
gymnast86 2bb05b0248 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-15 00:05:53 -07:00
gymnast86 96d82c5fc2 add starting inventory to file 2026-04-15 00:02:44 -07:00
gymnast86 5175795814 Add patches for onDungeonItem 2026-04-14 18:58:46 -07:00
gymnast86 049758431c Patch isStageLife calls since we handle hearts differently. Also patch isDungeon item and item wheel amounts 2026-04-14 18:16:10 -07:00
gymnast86 762f103991 Patch setGetItemFace to add more items to expressions 2026-04-14 17:39:25 -07:00
gymnast86 66aeeb8857 Patch execItemGet and patch CoO fairy to give item no matter what 2026-04-14 17:34:07 -07:00
gymnast86 d3a9c52ec5 patch seLineUpItem to use all item slots 2026-04-14 17:21:34 -07:00
gymnast86 dea93938e6 Patch createInit to use custom item scale and prevent giving booomerang on room load 2026-04-14 17:12:11 -07:00
gymnast86 890a42b3ee patch checkFieldItemCreateHeap to properly create certain field models 2026-04-14 17:02:58 -07:00
gymnast86 38f591c521 Patch existing item_funcs 2026-04-14 16:59:35 -07:00
gymnast86 14ec080a23 Add custom item functions and check functions 2026-04-14 16:51:13 -07:00
gymnast86 48da572df0 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-14 15:27:08 -07:00
gymnast86 0cb77802be Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-14 03:21:36 -07:00
gymnast86 dacfe11d95 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-14 03:17:46 -07:00
gymnast86 cc58b41901 Patch create functions to handle progressive items and special circumstances 2026-04-14 03:12:11 -07:00
gymnast86 04a2417f02 progressive item functions 2026-04-14 02:55:09 -07:00
gymnast86 9e74ffd9be Patch d_a_demo item to use special scales for defined items 2026-04-14 02:02:07 -07:00
gymnast86 dec4045e25 add rando item ids enum 2026-04-14 02:01:48 -07:00
gymnast86 4daf410cce throw error if generation fails 2026-04-14 02:01:40 -07:00
gymnast86 cf604b5fb0 tab 2026-04-14 01:32:56 -07:00
gymnast86 8738e5b122 update item resources, field resources, and info 2026-04-14 01:12:54 -07:00
gymnast86 38bea19a7b Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-13 23:51:28 -07:00
gymnast86 bf70de83f1 add basic chest overrides 2026-04-13 23:51:10 -07:00
gymnast86 f478751080 add some location metadata 2026-04-13 23:50:57 -07:00
gymnast86 a18ce4e6dd add item ids 2026-04-13 23:50:42 -07:00
gymnast86 e77bc5c9e5 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-13 07:51:11 -07:00
gymnast86 7e39274da2 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-12 21:43:51 -07:00
gymnast86 4ad05a3445 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-11 23:01:58 -07:00
gymnast86 4e25db0f20 more clean up 2026-04-11 23:01:46 -07:00
gymnast86 98b492bd89 remove redundant specifiers 2026-04-11 20:21:59 -07:00
gymnast86 461d59984f update hyrule castle settings 2026-04-11 19:37:45 -07:00
gymnast86 796a67f207 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-11 13:27:33 -07:00
gymnast86 2d4247f10e fix starting with maps and compasses 2026-04-11 09:06:29 -07:00
gymnast86 d4028fefa8 fix ordon rupee logic 2026-04-11 09:05:00 -07:00
gymnast86 7e5726c255 add rupees to generator 2026-04-11 08:30:39 -07:00
gymnast86 1873330e61 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-11 00:29:48 -07:00
gymnast86 9c9316466b swap fill order of prologue and own dungeon items 2026-04-10 21:39:42 -07:00
gymnast86 123c809e14 hold Z to create randomizer save 2026-04-10 21:04:35 -07:00
gymnast86 8172e672de place goal locations items before prologue items 2026-04-10 20:57:23 -07:00
gymnast86 4d1771649a Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-10 19:23:16 -07:00
gymnast86 c91925f243 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-10 17:21:35 -07:00
gymnast86 87116b871b add randomizer startflags 2026-04-10 17:20:34 -07:00
gymnast86 3547c57de0 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-09 22:34:10 -07:00
gymnast86 2d8a60aa75 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-09 19:03:01 -07:00
gymnast86 dd773bc261 properly set RANDOMIZER_ONLY 2026-04-09 19:02:55 -07:00
gymnast86 535c2f53c1 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-09 16:31:51 -07:00
gymnast86 c8cde246a9 add back SD only twilit insects 2026-04-09 16:31:44 -07:00
gymnast86 bc66d96d8b Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-09 15:39:02 -07:00
gymnast86 6c55f42ce2 Wrap generator in Randomizer class 2026-04-09 15:38:56 -07:00
gymnast86 679044f33d Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-09 12:27:13 -07:00
gymnast86 ac53fdbbff cmake cleanup 2026-04-09 12:27:05 -07:00
gymnast86 0b78547ba1 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-09 09:22:33 -07:00
gymnast86 0ebab8bad3 change how randomizer is included 2026-04-09 00:29:16 -07:00
gymnast86 ab7d3a5e03 change macro name 2026-04-09 00:28:52 -07:00
gymnast86 2f79bbe067 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-08 16:28:14 -07:00
gymnast86 b8b5b7197c Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-08 16:11:17 -07:00
gymnast86 554a461c95 add entrance aliases 2026-04-08 16:11:11 -07:00
gymnast86 1efb6c4a80 change namespace to "randomizer" 2026-04-08 01:18:35 -07:00
gymnast86 377d6a0d25 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-04-08 00:35:08 -07:00
gymnast86 72bed7a1ba initial rando generator hookup 2026-04-08 00:35:02 -07:00
409 changed files with 66293 additions and 4919 deletions
+3
View File
@@ -208,6 +208,9 @@ jobs:
- name: Build bundled mods
run: cmake --build --preset ${{matrix.preset}} --target dusklight_mods
- name: Stage stripped JNI library
run: ANDROID_STAGE_ABIS="${{matrix.abi}}" platforms/android/scripts/stage-jni-libs.sh
- name: Build APK
working-directory: platforms/android
run: ./gradlew :app:assembleRelease --rerun-tasks
+33 -45
View File
@@ -90,7 +90,6 @@ option(DUSK_ENABLE_SENTRY_NATIVE "Enable sentry-native crash reporting support"
option(DUSK_PACKAGE_INSTALL "Install Dusklight with a Linux-native file structure" OFF)
option(DUSK_GFX_DEBUG_GROUPS "Report debug groups to the native graphics API" ${DUSK_GFX_DEBUG_GROUPS_DEFAULT})
option(DUSK_ENABLE_CODE_MODS "Enable code mods" OFF)
option(DUSK_ENABLE_OPUS "Enable loading Opus audio files for mods" ON)
set(DUSK_HAS_FUNCHOOK OFF)
if (DUSK_ENABLE_CODE_MODS AND (NOT APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Darwin"))
@@ -194,21 +193,24 @@ if (DUSK_MOVIE_SUPPORT)
endif ()
endif ()
if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
# -Wno-multichar: Multi-character constants ('ABCD') are implementation-defined but all compilers
# (CW, GCC, Clang, MSVC) encode them identically in big-endian order.
# For >4-char literals (which GCC/Clang truncate to int), use the MULTI_CHAR() macro.
# -Wdeprecated-declarations: JSystem uses std::iterator, deprecated in C++17
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-multichar")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-multichar -Wno-trigraphs -Wno-deprecated-declarations")
set(CMAKE_INSTALL_RPATH "$ORIGIN")
set(CMAKE_BUILD_RPATH "$ORIGIN")
elseif (APPLE)
add_compile_options(-Wno-declaration-after-statement -Wno-non-pod-varargs)
set(CMAKE_INSTALL_RPATH "@loader_path")
set(CMAKE_BUILD_RPATH "@loader_path")
elseif (MSVC)
add_compile_options(
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-multichar>
$<$<COMPILE_LANGUAGE:CXX>:-Wno-trigraphs>
$<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-declarations>
)
elseif (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
add_compile_options(
$<$<COMPILE_LANGUAGE:C,CXX>:/bigobj>
$<$<COMPILE_LANGUAGE:C,CXX>:/MP>
$<$<COMPILE_LANGUAGE:C,CXX>:/FS>
$<$<COMPILE_LANGUAGE:C,CXX>:/bigobj>
$<$<COMPILE_LANGUAGE:C,CXX>:/MP>
$<$<COMPILE_LANGUAGE:C,CXX>:/FS>
)
if (NOT DUSK_BUILD_WARNINGS)
@@ -223,15 +225,6 @@ elseif (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/utf-8>)
endif ()
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
set(CMAKE_INSTALL_RPATH "$ORIGIN")
set(CMAKE_BUILD_RPATH "$ORIGIN")
elseif (APPLE)
add_compile_options(-Wno-declaration-after-statement -Wno-non-pod-varargs)
set(CMAKE_INSTALL_RPATH "@loader_path")
set(CMAKE_BUILD_RPATH "@loader_path")
endif ()
include(FetchContent)
# Declare all dependencies first so CMake can download them in parallel
@@ -255,25 +248,6 @@ FetchContent_Declare(miniz
)
set(_fetch_content_deps cxxopts json miniz)
if (DUSK_ENABLE_OPUS)
message(STATUS "dusklight: Fetching opusfile")
# Opusfile options
SET(OP_DISABLE_HTTP ON CACHE BOOL "" FORCE)
SET(OP_DISABLE_DOCS ON CACHE BOOL "" FORCE)
SET(OP_DISABLE_EXAMPLES ON CACHE BOOL "" FORCE)
message(STATUS "dusklight: Fetching opusfile")
FetchContent_Declare(
opusfile
GIT_REPOSITORY https://github.com/xiph/opusfile.git
GIT_TAG 6dfd29e7adb87f2e193575fc3fa88cbf1a0b27df
)
list(APPEND _fetch_content_deps opusfile)
endif ()
if (DUSK_HAS_FUNCHOOK)
message(STATUS "dusklight: Fetching funchook")
# cmake/PatchFunchook.cmake patches funchook's cmake/capstone.cmake.in to inject a
@@ -366,10 +340,6 @@ set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::p
if (DUSK_HAS_FUNCHOOK)
list(APPEND GAME_LIBS funchook-static)
endif ()
if (DUSK_ENABLE_OPUS)
list(APPEND GAME_LIBS OpusFile::opusfile)
list(APPEND GAME_COMPILE_DEFS DUSK_OPUS=1)
endif ()
if (DUSK_ENABLE_SENTRY_NATIVE)
list(APPEND GAME_LIBS sentry)
@@ -428,6 +398,8 @@ if (DUSK_MOVIE_SUPPORT)
list(APPEND GAME_COMPILE_DEFS MOVIE_SUPPORT=1)
endif ()
include(src/dusk/randomizer/randomizer.cmake)
set(DUSK_ENABLE_DISCORD_DEFAULT ON)
if (DEFINED DUSK_ENABLE_DISCORD_RPC AND NOT DEFINED DUSK_ENABLE_DISCORD)
set(DUSK_ENABLE_DISCORD_DEFAULT ${DUSK_ENABLE_DISCORD_RPC})
@@ -509,6 +481,24 @@ if (ENABLE_ASAN)
target_sources(dusklight PRIVATE src/dusk/asan_options.c)
endif ()
# Add embedded data to target
file(GLOB_RECURSE RANDOMIZER_DATA "src/dusk/randomizer/generator/data/*")
file(GLOB_RECURSE RANDOMIZER_ASSETS "src/dusk/randomizer/assets/*")
list(APPEND RANDOMIZER_DATA ${RANDOMIZER_ASSETS})
set(RANDO_ROOT_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR})
foreach (RANDOMIZER_FILE IN LISTS RANDOMIZER_DATA)
file(RELATIVE_PATH REL_PATH ${RANDO_ROOT_DATA_DIR} ${RANDOMIZER_FILE})
if(REL_PATH MATCHES "^src/dusk/randomizer/generator/data/tests")
message(STATUS "Skipping Embed: ${REL_PATH}")
continue()
endif ()
message(STATUS "Embedding File: ${REL_PATH}")
b_embed(dusklight ${REL_PATH})
endforeach ()
target_compile_definitions(dusklight PRIVATE ${GAME_COMPILE_DEFS})
target_include_directories(dusklight PRIVATE ${miniz_SOURCE_DIR})
target_link_libraries(dusklight PRIVATE aurora::main ${GAME_LIBS} ${JSYSTEM_LINK_LIBRARIES})
@@ -640,8 +630,6 @@ if (DUSK_ENABLE_CODE_MODS AND CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR
add_subdirectory(mods/template_mod)
add_subdirectory(mods/ao_mod)
add_subdirectory(mods/shadow_mod)
add_subdirectory(mods/window_demo)
add_subdirectory(mods/audio_mod)
endif ()
if (APPLE)
-4
View File
@@ -62,7 +62,3 @@ target_sources(dusklight_mod_feature_game INTERFACE
add_library(dusklight_mod_feature_webgpu INTERFACE)
target_link_libraries(dusklight_mod_feature_webgpu INTERFACE dusklight_mod_api)
target_compile_definitions(dusklight_mod_feature_webgpu INTERFACE DUSK_MOD_FEATURE_WEBGPU=1)
add_library(dusklight_mod_feature_fmt INTERFACE)
target_link_libraries(dusklight_mod_feature_fmt INTERFACE dusklight_mod_api)
target_compile_definitions(dusklight_mod_feature_fmt INTERFACE DUSK_MOD_FEATURE_FMT=1)
+1 -27
View File
@@ -113,29 +113,6 @@ function(_mod_add_webgpu_headers target_name)
endif ()
endfunction()
function(_mod_add_fmt target_name)
if (NOT TARGET fmt::fmt-header-only)
find_package(fmt 11 CONFIG QUIET GLOBAL)
endif ()
if (NOT TARGET fmt::fmt-header-only)
include(FetchContent)
message(STATUS "Mod SDK: fetching fmt")
# Keep the fallback version in sync with extern/aurora/extern/CMakeLists.txt.
FetchContent_Declare(fmt
URL https://github.com/fmtlib/fmt/archive/refs/tags/12.1.0.tar.gz
URL_HASH SHA256=ea7de4299689e12b6dddd392f9896f08fb0777ac7168897a244a6d6085043fea
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
EXCLUDE_FROM_ALL)
FetchContent_MakeAvailable(fmt)
endif ()
if (NOT TARGET fmt::fmt-header-only)
message(FATAL_ERROR "add_mod: FEATURES fmt could not provide fmt::fmt-header-only")
endif ()
target_link_libraries(${target_name} PRIVATE fmt::fmt-header-only)
endfunction()
function(add_mod target_name)
cmake_parse_arguments(ARG "BUNDLE" "MOD_JSON;RES_DIR;OVERLAY_DIR;TEXTURES_DIR;OUTPUT_DIR"
"SOURCES;RUNTIME_LIBRARIES;FEATURES" ${ARGN})
@@ -150,7 +127,7 @@ function(add_mod target_name)
message(FATAL_ERROR "add_mod: MOD_JSON does not exist: ${_mod_json}")
endif ()
set(_supported_features fmt game webgpu)
set(_supported_features game webgpu)
set(_features "")
foreach (_feature IN LISTS ARG_FEATURES)
list(FIND _supported_features "${_feature}" _feature_index)
@@ -190,9 +167,6 @@ function(add_mod target_name)
if (_feature STREQUAL "webgpu")
_mod_add_webgpu_headers(${target_name})
endif ()
if (_feature STREQUAL "fmt")
_mod_add_fmt(${target_name})
endif ()
if (_feature STREQUAL "game" OR _feature STREQUAL "webgpu")
set(_needs_host_link TRUE)
endif ()
+4 -25
View File
@@ -2,50 +2,40 @@ include_guard(GLOBAL)
get_filename_component(_SYMBOL_MANIFEST_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
set(_SYMGEN_VERSION "1.3.2")
set(_SYMGEN_VERSION "1.3.1")
set(_SYMGEN_RELEASE_BASE_URL "https://github.com/encounter/symgen/releases/download/v${_SYMGEN_VERSION}")
set(SYMGEN_PATH "" CACHE FILEPATH "Path to a symgen executable; empty downloads the pinned release")
mark_as_advanced(SYMGEN_PATH)
function(symgen_host_asset out_name out_hash)
function(symgen_host_asset out_name)
string(TOLOWER "${CMAKE_HOST_SYSTEM_PROCESSOR}" _host_processor)
set(_asset "")
set(_asset_hash "")
if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
if (_host_processor MATCHES "^(arm64|aarch64)$")
set(_asset "symgen-macos-arm64")
set(_asset_hash "SHA256=0344838d1674df09c17c3eeddcf26eb89c333fdb85dfd78f68adc436070eccbe")
elseif (_host_processor MATCHES "^(x86_64|amd64)$")
set(_asset "symgen-macos-x86_64")
set(_asset_hash "SHA256=ae0674f4a1e9d0dedfa02d35939ac28cdd229276b331c1f507df5df809cbec7e")
endif ()
elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
if (_host_processor MATCHES "^(aarch64|arm64)$")
set(_asset "symgen-linux-aarch64")
set(_asset_hash "SHA256=af766de2bfaeb0a06f6d7bc17bb2510b4a9c40f44a56e49bc4a4b798a6223042")
elseif (_host_processor MATCHES "^(x86_64|amd64)$")
set(_asset "symgen-linux-x86_64")
set(_asset_hash "SHA256=ebd62fb9623acc942b6295609e2306f85a73043b0a8a117f2072b761dd08e68f")
elseif (_host_processor MATCHES "^(i[3-6]86|x86)$")
set(_asset "symgen-linux-i686")
set(_asset_hash "SHA256=07780a4513fd29726578efc4ff2d88736b22f407ed821b32a68e35ff1e9af5f4")
endif ()
elseif (CMAKE_HOST_WIN32)
if (_host_processor MATCHES "^(arm64|aarch64)$")
set(_asset "symgen-windows-arm64.exe")
set(_asset_hash "SHA256=5bb22b4a4a9b5ad45646af411bfb09b8321a732ff3a077eb4c9de1feaef27d2b")
elseif (_host_processor MATCHES "^(x86_64|amd64)$")
set(_asset "symgen-windows-x86_64.exe")
set(_asset_hash "SHA256=1d1ac087f991a96932d108969e15998becfec643e88f3e7d182ca97ebfc6a46f")
elseif (_host_processor MATCHES "^(i[3-6]86|x86)$")
set(_asset "symgen-windows-x86.exe")
set(_asset_hash "SHA256=c113f4cd05f813efe2b1878dbfcf44d6302aee3974271736e0036430b0cced78")
endif ()
endif ()
set(${out_name} "${_asset}" PARENT_SCOPE)
set(${out_hash} "${_asset_hash}" PARENT_SCOPE)
endfunction()
function(ensure_symgen required)
@@ -64,7 +54,7 @@ function(ensure_symgen required)
return()
endif ()
else ()
symgen_host_asset(_asset _asset_hash)
symgen_host_asset(_asset)
if (_asset STREQUAL "")
if (required)
message(FATAL_ERROR "symgen: no prebuilt binary for host "
@@ -85,8 +75,7 @@ function(ensure_symgen required)
file(DOWNLOAD "${_url}" "${_symgen}"
TLS_VERIFY ON
STATUS _download_status
SHOW_PROGRESS
EXPECTED_HASH "${_asset_hash}")
SHOW_PROGRESS)
list(GET _download_status 0 _download_code)
if (NOT _download_code EQUAL 0)
list(GET _download_status 1 _download_message)
@@ -117,16 +106,6 @@ function(setup_symbol_manifest target)
endif ()
add_dependencies(${target} symgen)
# Reserve an ELF program-header entry when the linker supports it (mold).
# symgen can replace the PT_NULL entry without relocating the table, keeping later post-link tools safe.
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
include(CheckLinkerFlag)
check_linker_flag(CXX "LINKER:--spare-program-headers=1" _linker_supports_spare_program_headers)
if (_linker_supports_spare_program_headers)
target_link_options(${target} PRIVATE "LINKER:--spare-program-headers=1")
endif ()
endif ()
if (WIN32)
set(_input --pdb "$<TARGET_PDB_FILE:${target}>")
else ()
-71
View File
@@ -1,71 +0,0 @@
#pragma endian big
#include "std/sys.pat"
#include "type/magic.pat"
#include "std/array.pat"
/**
* Wrapper for a file-global pointer that allows it to be stored in an array.
*/
struct Offset<T> {
T* offset : u32 [[inline]];
};
struct ItemSoundEffect {
u8 mPriority;
u8 mVolume;
padding[2];
u32 mSwBit;
float mPitch;
};
struct ItemSequence {
u8 mPriority;
u8 mVolume;
u16 mResourceId;
};
struct ItemStream {
u8 mPriority;
u8 mVolume;
u16 mStreamPanParameters;
char* mStreamFilePath[] : u32;
};
struct SoundTableGroupEntry {
u8 mTypeId;
if (mTypeId == 0x51) {
ItemSoundEffect* mOffset : u24 [[inline]];
} else if (mTypeId == 0x60) {
ItemSequence* mOffset : u24 [[inline]];
} else if (mTypeId == 0x70 || mTypeId == 0x71) {
ItemStream* mOffset : u24 [[inline]];
} else {
u24 mOffset;
}
};
struct TGroup {
u32 mNumItems;
padding[4];
SoundTableGroupEntry mEntries[mNumItems];
};
struct TSection {
u32 mNumGroups;
Offset<TGroup> mGroupOffsets[mNumGroups];
};
struct Root {
u32 mSectionNumber;
Offset<TSection> mSectionOffsets[mSectionNumber];
};
struct THeader {
type::Magic<"BST "> mMagic;
padding[8];
Root* mRoot : u32;
};
THeader header @ 0x0;
-228
View File
@@ -1,228 +0,0 @@
#pragma endian big
#include "std/sys.pat"
#include "type/magic.pat"
#include "std/array.pat"
/*
WSYS file
The WSYS file contains roughly two sections: WBCT and WINF.
WBCT contains the mapping of Wave ID -> wave archives.
WINF are the wave archives themselves and their metadata.
*/
/**
* Wrapper for a file-global pointer that allows it to be stored in an array.
*/
struct Offset<T> {
T* offset : u32 [[inline]];
};
/**
* Format that audio data is in..
*/
enum WaveFormat : u8 {
/**
* 16-samples-per-9-bytes custom Nintendo ADPCM.
*/
ADPCM4 = 0,
/**
* 16-samples-per-5-bytes custom Nintendo ADPCM.
*/
ADPCM2 = 1,
/**
* 8-bit-per-sample PCM.
*/
PCM8 = 2,
/**
* 16-bit-per-sample PCM.
*/
PCM16 = 3,
};
/**
* Defines playback info for a single audio "wave".
* This data is stored per archive, making it duplicated (except for mAWOffsetStart)
*/
struct TWave {
padding[1]; // unknown
WaveFormat mWaveFormat;
/**
* Key (as in like, the musical term) this sample is in.
*/
u8 mBaseKey;
padding[1];
/**
* Sample rate of the audio in Hz.
*/
float mSampleRate;
/**
* Position where the sample data starts.
* This is in the .aw file for the archive containing this TWave.
*/
u32 mAWOffsetStart;
/**
* Byte length of the sample data.
*/
u32 mAWLength;
/**
* Indicates whether the sample should loop or not. All bits appear set if so.
*/
u32 mLoopFlags;
/**
* Audio sample at which the loop starts.
*/
u32 mLoopStartSample;
/**
* Audio sample at which the loop ends (and goes back to mLoopStartSample).
*/
u32 mLoopEndSample;
/**
* Total sample count in this wave.
*/
u32 mSampleCount;
/**
* Last sample for continuing ADPCM decode after loop.
*/
s16 mpLast;
/**
* Penult sample for continuing ADPCM decode after loop.
*/
s16 mpPenult;
};
/**
* A single wave archive on disk.
* These are paired 1:1 with TCtrlScene objects.
*/
struct TWaveArchive {
/**
* Filename of the raw sample data on disc. Relative to /Audiores/Waves/
*/
char mFileName[0x70];
/**
* Amount of waves in this archive.
* Matches the count in the paired TCtrl object.
*/
u32 mWaveCount;
/**
* Offsets to the wave metadata (not sample data) in the WSYS.
* These are paired 1:1 to the TCtrlWaves, and the TCtrlWave contains the actual
* "Wave ID" used by the game for lookups.
*/
Offset<TWave> waveOffsets[mWaveCount];
};
/**
* Header containing data for wave archives and their metadata.
*/
struct TWaveArchiveBank {
type::Magic<"WINF"> mMagic;
/**
* Amount of archives in this wave bank.
* Matches the value in TCtrlGroup.
*/
u32 mArchiveCounts;
Offset<TWaveArchive> mArchiveOffsets[mArchiveCounts];
};
/**
* Definition for a single wave in a control group.
*/
struct TCtrlWave {
/**
* Group ID matches the index of the control group this item is referenced by.
*/
u16 mGroupId;
/**
* Wave ID used by the game to look this wave up.
*/
u16 mWaveId;
};
/**
* Contains the actual data for a TCtrlScene.
* Why is this separate? Who knows.
*/
struct TCtrl {
// Other versions of this struct with different magic (C-EX and C-ST) also exist in the file.
// They aren't pointed to so we don't need to worry about them.
type::Magic<"C-DF"> mMagic;
/**
* Amount of waves in this group.
* Matches the value in TWaveArchive.
*/
u32 waveCount;
Offset<TCtrlWave> mWaveOffsets[waveCount];
};
/**
* A single scene or "group" of waves that are loaded at once.
*/
struct TCtrlScene {
type::Magic<"SCNE"> mMagic;
padding[8]; // unknown
TCtrl* mCtrlOffset : u32 [[inline]];
};
/**
* Contains the "control" section of the WSYS.
*/
struct TCtrlGroup {
type::Magic<"WBCT"> mMagic;
padding[4]; // unknown
u32 mGroupCount;
Offset<TCtrlScene> mCtrlSceneOffsets[mGroupCount];
};
struct THeader {
type::Magic<"WSYS"> mMagic;
/**
* Size of WSYS in bytes.
*/
u32 mSize;
/**
* ID of wave bank.
* This matches the value passed to the BAA load command.
* The game originally does not use this value itself, but Dusklight does rely on it.
*/
u32 mId;
/**
* Total amount of waves in this wave bank.
* (not groups! Waves!)
*/
u32 mWaveTableSize;
TWaveArchiveBank* archiveBankOffset : u32;
TCtrlGroup* ctrlGroupOffset : u32;
};
THeader header @ 0x0;
std::assert(
header.archiveBankOffset.mArchiveCounts == header.ctrlGroupOffset.mGroupCount,
"Control group and archive count does not match!");
-90
View File
@@ -1,90 +0,0 @@
# JAudio
**JAudio** is the name for the audio engine used by Twilight Princess (along with many other Nintendo games from the era). TP uses exclusively JAudio v2, while other games use v1 or a mix of v1 and v2 infrastructure. This document will primarily focus on TP's use case, but best efforts will be made to document where behavior is TP-specific.
## Common concepts
Audio is almost exclusively
### `JAISoundID`
A "sound", be that a _sound effect_ or music, is referenced in-code through the `JAISoundID` type. This is a `u32` that the game uses to look up the relevant sound. The actual value is bitpacked (BE) from the following fields:
| Type | Field | Description |
|-------|------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `u8` | Section ID | Section of the Sound Table this sound effect is located in. 0 for sound effects, 1 for sequenced music, 2 for streamed music.[^sectionids] |
| `u8` | Group ID | ID of group further used to organize inside the Sound Table's Section. Sound effects are grouped into things like "SYSTEM" and "ENEMY", other sections leave this at 0. |
| `u16` | "Wave ID" | Index inside the group to look up the sound at.<br/>**Note** that the term "wave" in code is extremely confusing[^waveterm]; it does **not** refer to audio samples ("waves") in the wave banks directly. |
[^sectionids]: JAudio itself can seemingly work outside this convention, however it is enforced by some TP-specific game code.
[^waveterm]: Possibly vestigial from JAudio v1, where I believe there were less layers of indirection.
## Disc files
All audio data is stored in `/Audiores` on the disc. Files are as follows:
### `/Audiores/Seqs/Z2SoundSeqs.arc`
Contains the BMS instructions for all BMS-based music and sound effects. Not all data is kept in memory at once.
### `/Audiores/Stream/*.ast`
Contains individual streamed music. Each file is a separate music track. See [this page](https://www.lumasworkshop.com/wiki/AST_(File_Format)) for file format description.
### `/Audiores/Waves/*.aw`
Contains audio sample data for sequenced music and sound effects. These files are pure meat, no bone: they are loaded directly into ARAM and all metadata is stored in the BAA WSYS sections.
Each file contains audio samples for one "scene", with factors like the current level determining what "scenes" are made resident in memory. There is tons of duplicate data between scenes, presumably to increase simplicity and loading performance.
### `/Audiores/Z2Sound.baa`
Contains all remaining metadata for the audio system. This is effectively a container for a bunch of different sub-sections. The file starts with a bunch of "commands" that indicate where other data in the file is. Each command has a 4-character identifier and depending on the command will be followed by some extra arguments before the next command.
The commands used by TP's BAA file are as follows (note that the decompiled code has support for more load commands, which are unused):
| Command/Argument | Value | Description |
|------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------|
| Command | `AA_<` | Start of BAA commands. Must be at the start of the file and only appear once. |
| Command | `>_AA` | End of BAA commands. |
| Command | `ws `[^spaces] | Wave bank/WSYS data. Defines where audio samples are located on disc. |
| Argument | u32 | Wave bank ID, max 255. In TP, 0 is sound effects, 1 is music samples. |
| Argument | u32 | File offset for start of `WSYS` data |
| Argument | u32 | Bit field selecting which groups (= `.aw` files) to load immediately. TP leaves this at zero.[^32ws] |
| Command | `bnk `[^spaces] | Instrument bank/IBNK |
| Argument | u32 | Target wave bank ID |
| Argument | u32 | File offset for start of `IBNK` data |
| Command | `bsc `[^spaces] | Sound effect sequence collection. |
| Argument | u32 | File offset for start of `SC` data. |
| Argument | u32 | File offset for end of `SC` data. |
| Command | `bst `[^spaces] | Sound table. Defines parameters for music and sound effects. |
| Argument | u32 | File offset for start of `BST `[^spaces] data. |
| Argument | u32 | File offset for end of `BST `[^spaces] data. |
| Command | `bstn` | Sound name table. Defines names of all music and sound effects. Present on disc, but loading is disabled on release versions of the game. |
| Argument | u32 | File offset for start of `BSTN` data. |
| Argument | u32 | File offset for end of `BSTN` data. |
| Command | `bfca` | Unknown, something related to initialization of DSP FX data. |
| Argument | u32 | File offset for start of `RARC` data. |
[^spaces]: Padded with spaces.
[^32ws]: Both of TP's wave banks have far more than 32 groups, and seemingly this mechanism would not be able to deal with that.
Following is data descriptions for the remaining data in the `.BAA`, as pointed to by the above commands.
### `WSYS` / Wave banks
`WSYS` / Wave bank data defines where a set of audio samples can be found on disc. Each wave bank is made of multiple "groups", where each group corresponds to one `.aw` file on disc. Each group has a set of "wave IDs" it contains, along with the metadata (e.g. sample rate) and data offset in the `.aw` file.
Multiple groups can contain the same wave ID, thus meaning the raw audio samples can be duplicated on disk.
For the actual binary layout of this data, check [the ImHex pattern](imhex/jaudio/wsys.hexpat)
*Relevant classes: `JASWSParser`, `JASBasicWaveBank`, `JASSimpleWaveBank`.*
## Further reading & credits
* https://www.lumasworkshop.com/wiki/SMR.szs (note that details like the exact layout of the BAA are not the same as TP)
* XAYRGA for doing much RE work and making [JAMTools](https://xayr.gay/tools/SoundModdingToolkit/)
* The decompiled source code, duh.
+11 -83
View File
@@ -54,7 +54,7 @@ include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchDusklight.cmake")
add_subdirectory("${DUSKLIGHT_DIR}/sdk" dusklight-sdk EXCLUDE_FROM_ALL)
add_mod(my_mod
FEATURES game fmt # remove game for service-only mods; add webgpu for GfxService
FEATURES game # remove for service/asset-only mods; add webgpu for GfxService
SOURCES src/mod.cpp
MOD_JSON mod.json
RES_DIR res # mod resources, including icon.png and banner.png
@@ -64,8 +64,6 @@ add_mod(my_mod
```
Available features:
- `fmt`: Provides the header-only `{fmt}` library and the formatted logging helpers in `mods/svc/log.hpp`.
- `game`: Allows calling into and hooking game code. Mods that **only** use services may omit it, providing a wider
range of compatibility with Dusklight versions and a slightly faster build process.
- `webgpu`: Allows importing the WebGPU API (`webgpu/webgpu.h`). Must be enabled when using
@@ -145,9 +143,6 @@ IMPORT_SERVICE_VERSION(LogService, svc_log, 0); // required, minimum minor ver
IMPORT_OPTIONAL_SERVICE(SomeService, svc_maybe); // may be null
```
A service must be imported in only **one** file (usually your `mod.cpp`). Other files may simply use `svc_log` or
`mods::log::` after including the appropriate header.
Each service is individually versioned, and there may be multiple major versions of a service provided at once,
allowing backwards compatibility with older mods while still changing services fundamentally if necessary. A **major**
bump is a breaking change, treated as a different service entirely. For **additive** changes, a service appends new
@@ -184,15 +179,7 @@ svc_log->write(mod_ctx, LOG_LEVEL_DEBUG, "verbose details");
```
Messages appear in the console prefixed with your mod ID. Messages are plain UTF-8 strings and are copied before the
call returns. C++ mods can enable `add_mod(... FEATURES fmt)` and use the formatted logging helpers in
`mods/svc/log.hpp`:
```cpp
#include <mods/svc/log.hpp>
mods::log::info("spawned actor {} at ({}, {})", actorName, x, y);
mods::log::warn("health is down to {:.1f}%", healthPercent);
```
call returns; use `snprintf` or `fmt::format` for formatting.
### ResourceService (`mods/svc/resource.h`)
@@ -249,7 +236,7 @@ every service dropped its state. For your own mod's teardown, use `mod_shutdown`
### HookService (`mods/svc/hook.h`)
Installs hooks on game functions and resolves symbols by name. You'll rarely call it directly; use the typed helpers in
`mods/svc/hook.hpp` described in [Hooking Game Functions](#hooking-game-functions).
`mods/hook.hpp` described in [Hooking Game Functions](#hooking-game-functions).
### OverlayService (`mods/svc/overlay.h`)
@@ -422,22 +409,6 @@ sets `keep_open`. A `keep_open` action can close it later (or immediately) with
`on_dismiss` if present and always closes. `dialog_set_body`, `dialog_set_icon`, and `dialog_add_action` mutate a live
dialog.
**Toasts:** `push_toast` enqueues a notification. Titles and bodies accept RML. The optional `type` is applied as an
RCSS class; `warning` uses the built-in warning appearance, and mods can define their own types. A duration of 0 uses
the default of 5 seconds.
Toasts have a `mod-id` attribute, so `UI_SCOPE_OVERLAY` styles can use selectors such as
`toast[mod-id="com.example.randomizer"].success`.
```cpp
UiToastDesc toast = UI_TOAST_DESC_INIT;
toast.type = "success";
toast.title_rml = "Randomizer";
toast.body_rml = "<span>Seed loaded successfully.</span>";
toast.duration_ms = 3000;
svc_ui->push_toast(mod_ctx, &toast);
```
**Menu bar tabs:** `register_menu_tab` adds a tab to the in-game menu bar. `on_selected` fires when the user activates
the tab: typically you'd push a window from it. The tab is removed by `unregister_menu_tab`, or automatically when the
mod is disabled.
@@ -449,26 +420,6 @@ existing documents restyle immediately, and future ones pick it up when created.
host styles and may override them. Scope selectors tightly (use `[mod-id="..."]`!), especially for `UI_SCOPE_WINDOW`,
unless changing host UI is intentional.
### WindowService (`mods/svc/window.h`)
Allows creating new windows that can be rendered to via `GfxService`.
```cpp
IMPORT_SERVICE(WindowService, svc_window);
WindowDesc desc = WINDOW_DESC_INIT;
desc.title = "My auxiliary view";
desc.on_event = on_window_event;
WindowHandle window = 0;
svc_window->create_window(mod_ctx, &desc, &window);
```
Window callbacks run on the game thread. A close event is only a request; call `destroy_window` when the mod is ready to
close it. A window attached to a GfxService present target cannot be destroyed until that target is unregistered. Only
one present target may be attached to a WindowService window at a time.
New windows are hidden by default so a mod can finish attaching graphics before calling `show_window`.
### GfxService (`mods/svc/gfx.h`)
**Requires `add_mod(... FEATURES webgpu)`**
@@ -500,30 +451,6 @@ registered with `register_compute_type` follow the same worker-thread rule and r
All WGPU handles from the service are borrowed. Resolved target views are valid for the current frame only. GPU objects
created by a mod are owned by that mod and should be released in `mod_shutdown`.
#### External presentation
GfxService supports external presentation ("present targets") backed by either a WindowService window (via
`register_window_present_target`) or a plain `WGPUSurface` (via `register_present_target`).
```cpp
GfxPresentTargetDesc target_desc = GFX_PRESENT_TARGET_DESC_INIT;
target_desc.render = render_auxiliary_view;
GfxPresentTargetHandle target = 0;
svc_gfx->register_window_present_target(mod_ctx, window, &target_desc, &target);
// From a stage callback:
svc_gfx->push_present(mod_ctx, target, &payload, sizeof(payload));
```
For WindowService windows, the surface is automatically reconfigured on window size changes.
For plain `WBPUSurface`s, `resize_present_target` must be used to resize.
To create a `WGPUSurface` manually, `GfxDeviceInfo` holds the `WGPUInstance` and `WGPUAdapter` which can be used with
`wgpuInstanceCreateSurface` and a chained `WGPUSurfaceSource*` struct.
`push_present` must be called every frame from a GfxService stage callback. If surface was lost, `push_present` returns
`MOD_ERROR`. Unregister and re-register the target before trying again.
### CameraService (`mods/svc/camera.h`)
Converts a game view provided by a render callback into WebGPU-convention camera data. Matrix fields are column-major
@@ -550,10 +477,11 @@ first in-game frame. Projection matrices match the renderer's WebGPU clip conven
**Requires `add_mod(... FEATURES game)`**
Mods may hook the vast majority of game functions, including file-local static, private and virtual functions.
`mods/svc/hook.hpp` provides typed helpers over the hook service:
`mods/hook.hpp` provides typed helpers over the hook service:
```cpp
#include "mods/svc/hook.hpp"
#include "mods/hook.hpp"
#include "mods/svc/hook.h"
IMPORT_SERVICE(HookService, svc_hook);
@@ -577,7 +505,7 @@ HookAction on_pos_move_pre(ModContext*, void* args, void* retval, void* userdata
return HOOK_CONTINUE;
}
mods::hook::add_pre<LinkPosMove>(on_pos_move_pre);
mods::hook_add_pre<LinkPosMove>(svc_hook, on_pos_move_pre);
```
### Post-hooks
@@ -588,7 +516,7 @@ if any.
```cpp
void on_pos_move_post(ModContext*, void* args, void* retval, void* userdata) { ... }
mods::hook::add_post<LinkPosMove>(on_pos_move_post);
mods::hook_add_post<LinkPosMove>(svc_hook, on_pos_move_post);
```
### Replace-hooks
@@ -603,7 +531,7 @@ void on_execute_replace(ModContext*, void* args, void* retval, void*) {
}
}
mods::hook::replace<LinkExecute>(on_execute_replace);
mods::hook_replace<LinkExecute>(svc_hook, on_execute_replace);
```
By default a second replace-hook on the same function is a conflict; `HookOptions` (`replace_policy`, `priority`,
@@ -619,7 +547,7 @@ symbol name instead. You must supply the signature along with the name.
DEFINE_HOOK_SYMBOL("daAlink_hookshotAtHitCallBack",
void(fopAc_ac_c*, dCcD_GObjInf*, fopAc_ac_c*, dCcD_GObjInf*), HookshotHit);
mods::hook::add_pre<HookshotHit>(on_hookshot_hit_pre);
mods::hook_add_pre<HookshotHit>(svc_hook, on_hookshot_hit_pre);
...
HookshotHit::g_orig(link, atObjInf, target, tgObjInf); // call through to the original
```
@@ -659,7 +587,7 @@ HookAction on_create_item_pre(ModContext*, void* args, void*, void*) {
return HOOK_CONTINUE;
}
mods::hook::add_pre<CreateItem>(on_create_item_pre);
mods::hook_add_pre<CreateItem>(svc_hook, on_create_item_pre);
```
For reference parameters (e.g. `const cXyz& pos`), `arg_ref<cXyz>` yields a direct reference.
+1 -1
+143 -7
View File
@@ -1458,6 +1458,8 @@ set(DUSK_FILES
src/dusk/imgui/ImGuiHeapOverlay.cpp
src/dusk/imgui/ImGuiMenuTools.cpp
src/dusk/imgui/ImGuiMenuTools.hpp
src/dusk/imgui/ImGuiMenuRandomizer.cpp
src/dusk/imgui/ImGuiMenuRandomizer.hpp
src/dusk/imgui/ImGuiProcessOverlay.cpp
src/dusk/imgui/ImGuiSaveEditor.cpp
src/dusk/imgui/ImGuiStateShare.cpp
@@ -1485,10 +1487,6 @@ set(DUSK_FILES
src/dusk/mods/log_buffer.hpp
src/dusk/mods/manifest.cpp
src/dusk/mods/manifest.hpp
src/dusk/mods/svc/audio_res/audio_res.hpp
src/dusk/mods/svc/audio_res/audio_res.cpp
src/dusk/mods/svc/audio_res/wave.cpp
src/dusk/mods/svc/audio_res/opus.cpp
src/dusk/mods/svc/camera.cpp
src/dusk/mods/svc/config.cpp
src/dusk/mods/svc/config.hpp
@@ -1504,8 +1502,6 @@ set(DUSK_FILES
src/dusk/mods/svc/texture.cpp
src/dusk/mods/svc/ui.cpp
src/dusk/mods/svc/ui.hpp
src/dusk/mods/svc/window.cpp
src/dusk/mods/svc/window.hpp
src/dusk/mouse.cpp
src/dusk/scope_guard.hpp
src/dusk/settings.cpp
@@ -1524,6 +1520,8 @@ set(DUSK_FILES
src/dusk/ui/component.hpp
src/dusk/ui/controller_config.cpp
src/dusk/ui/controller_config.hpp
src/dusk/ui/cosmetics.hpp
src/dusk/ui/cosmetics.cpp
src/dusk/ui/controls.hpp
src/dusk/ui/document.cpp
src/dusk/ui/document.hpp
@@ -1582,14 +1580,152 @@ set(DUSK_FILES
src/dusk/ui/warp.hpp
src/dusk/ui/window.cpp
src/dusk/ui/window.hpp
src/dusk/ui/rando_config.cpp
src/dusk/ui/rando_config.hpp
src/dusk/ui/rando_seed_generation.cpp
src/dusk/ui/rando_seed_generation.hpp
src/dusk/achievements.cpp
src/dusk/iso_validate.cpp
src/dusk/livesplit.cpp
src/dusk/OSContext.cpp
src/dusk/OSReport.cpp
src/dusk/OSThread.cpp
src/dusk/OSMutex.cpp
src/dusk/mods/log_buffer.cpp
src/dusk/mods/log_buffer.hpp
src/dusk/mods/manifest.cpp
src/dusk/mods/manifest.hpp
src/dusk/mods/loader/bundle_disk.cpp
src/dusk/mods/loader/bundle_zip.cpp
src/dusk/mods/loader/context.cpp
src/dusk/mods/loader/depgraph.cpp
src/dusk/mods/loader/depgraph.hpp
src/dusk/mods/loader/loader.cpp
src/dusk/mods/loader/loader.hpp
src/dusk/mods/loader/native_module.cpp
src/dusk/mods/loader/native_module.hpp
src/dusk/mods/svc/camera.cpp
src/dusk/mods/svc/config.cpp
src/dusk/mods/svc/config.hpp
src/dusk/mods/svc/game.cpp
src/dusk/mods/svc/gfx.cpp
src/dusk/mods/svc/hook.cpp
src/dusk/mods/svc/host.cpp
src/dusk/mods/svc/log.cpp
src/dusk/mods/svc/overlay.cpp
src/dusk/mods/svc/resource.cpp
src/dusk/mods/svc/texture.cpp
src/dusk/mods/svc/ui.cpp
src/dusk/mods/svc/ui.hpp
src/dusk/mods/svc/registry.cpp
src/dusk/mods/svc/registry.hpp
src/dusk/discord.cpp
src/dusk/discord.hpp
src/dusk/discord_presence.cpp
src/dusk/version.cpp
src/dusk/action_bindings.cpp
src/dusk/update_check.cpp
src/dusk/update_check.hpp
src/dusk/version.cpp
src/dusk/cosmetics/color_utils.hpp
src/dusk/cosmetics/color_utils.cpp
src/dusk/cosmetics/midna_hair_color.hpp
src/dusk/cosmetics/midna_hair_color.cpp
src/dusk/cosmetics/texture_utils.hpp
src/dusk/cosmetics/texture_utils.cpp
# Randomizer files
src/dusk/randomizer/game/custom_flow_ids.hpp
src/dusk/randomizer/game/flags.cpp
src/dusk/randomizer/game/flags.h
src/dusk/randomizer/game/messages.cpp
src/dusk/randomizer/game/messages.hpp
src/dusk/randomizer/game/stages.cpp
src/dusk/randomizer/game/stages.h
src/dusk/randomizer/game/tools.cpp
src/dusk/randomizer/game/tools.h
src/dusk/randomizer/game/verify_item_functions.cpp
src/dusk/randomizer/game/verify_item_functions.h
src/dusk/randomizer/game/randomizer_context.cpp
src/dusk/randomizer/game/randomizer_context.hpp
src/dusk/randomizer/generator/logic/area.cpp
src/dusk/randomizer/generator/logic/area.hpp
src/dusk/randomizer/generator/logic/dungeon.cpp
src/dusk/randomizer/generator/logic/dungeon.hpp
src/dusk/randomizer/generator/logic/entrance.cpp
src/dusk/randomizer/generator/logic/entrance.hpp
src/dusk/randomizer/generator/logic/entrance_shuffle.cpp
src/dusk/randomizer/generator/logic/entrance_shuffle.hpp
src/dusk/randomizer/generator/logic/fill.cpp
src/dusk/randomizer/generator/logic/fill.hpp
src/dusk/randomizer/generator/logic/flatten/bits.cpp
src/dusk/randomizer/generator/logic/flatten/bits.hpp
src/dusk/randomizer/generator/logic/flatten/flatten.cpp
src/dusk/randomizer/generator/logic/flatten/flatten.hpp
src/dusk/randomizer/generator/logic/flatten/simplify_algebraic.cpp
src/dusk/randomizer/generator/logic/flatten/simplify_algebraic.hpp
src/dusk/randomizer/generator/logic/hints.cpp
src/dusk/randomizer/generator/logic/hints.hpp
src/dusk/randomizer/generator/logic/item.cpp
src/dusk/randomizer/generator/logic/item.hpp
src/dusk/randomizer/generator/logic/item_pool.cpp
src/dusk/randomizer/generator/logic/item_pool.hpp
src/dusk/randomizer/generator/logic/location.cpp
src/dusk/randomizer/generator/logic/location.hpp
src/dusk/randomizer/generator/logic/plandomizer.cpp
src/dusk/randomizer/generator/logic/plandomizer.hpp
src/dusk/randomizer/generator/logic/requirement.cpp
src/dusk/randomizer/generator/logic/requirement.hpp
src/dusk/randomizer/generator/logic/search.cpp
src/dusk/randomizer/generator/logic/search.hpp
src/dusk/randomizer/generator/logic/spoiler_log.cpp
src/dusk/randomizer/generator/logic/spoiler_log.hpp
src/dusk/randomizer/generator/logic/world.cpp
src/dusk/randomizer/generator/logic/world.hpp
src/dusk/randomizer/generator/randomizer.cpp
src/dusk/randomizer/generator/randomizer.hpp
src/dusk/randomizer/generator/seedgen/config.cpp
src/dusk/randomizer/generator/seedgen/config.hpp
src/dusk/randomizer/generator/seedgen/packed_bits.hpp
src/dusk/randomizer/generator/seedgen/seed.cpp
src/dusk/randomizer/generator/seedgen/seed.hpp
src/dusk/randomizer/generator/seedgen/settings.cpp
src/dusk/randomizer/generator/seedgen/settings.hpp
src/dusk/randomizer/generator/test/test.cpp
src/dusk/randomizer/generator/test/test.hpp
src/dusk/randomizer/generator/utility/base64pp.hpp
src/dusk/randomizer/generator/utility/color.cpp
src/dusk/randomizer/generator/utility/color.hpp
src/dusk/randomizer/generator/utility/crc32.hpp
src/dusk/randomizer/generator/utility/common.cpp
src/dusk/randomizer/generator/utility/common.hpp
src/dusk/randomizer/generator/utility/container.hpp
src/dusk/randomizer/generator/utility/endian.cpp
src/dusk/randomizer/generator/utility/endian.hpp
src/dusk/randomizer/generator/utility/exception.hpp
src/dusk/randomizer/generator/utility/file.cpp
src/dusk/randomizer/generator/utility/file.hpp
src/dusk/randomizer/generator/utility/general.hpp
src/dusk/randomizer/generator/utility/log.cpp
src/dusk/randomizer/generator/utility/log.hpp
src/dusk/randomizer/generator/utility/math.hpp
src/dusk/randomizer/generator/utility/path.cpp
src/dusk/randomizer/generator/utility/path.hpp
src/dusk/randomizer/generator/utility/platform.cpp
src/dusk/randomizer/generator/utility/platform.hpp
src/dusk/randomizer/generator/utility/random.cpp
src/dusk/randomizer/generator/utility/random.hpp
src/dusk/randomizer/generator/utility/string.cpp
src/dusk/randomizer/generator/utility/string.hpp
src/dusk/randomizer/generator/utility/text.cpp
src/dusk/randomizer/generator/utility/text.hpp
src/dusk/randomizer/generator/utility/thread_local.hpp
src/dusk/randomizer/generator/utility/time.cpp
src/dusk/randomizer/generator/utility/time.hpp
src/dusk/randomizer/generator/utility/yaml.hpp
src/helpers/batch.cpp
src/helpers/endian.cpp
src/helpers/offset_ptr.cpp
src/helpers/string.cpp
src/helpers/cast.cpp
)
set(DUSK_HTTP_BACKEND_FILES
+27 -18
View File
@@ -2,7 +2,6 @@
description = "Dusklight native PC port of the Twilight Princess decompilation";
inputs.nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
inputs.self.submodules = true;
outputs =
{ self, nixpkgs }:
@@ -59,6 +58,21 @@
hasNodPrebuilt = nodPrebuiltInfo ? ${system};
aurora = builtins.pathExists "${self}/extern/aurora/CMakeLists.txt";
needSubmodules = ''
dusklight: The aurora submodule is not vendored. Add submodules=1 to build.
As a flake input:
dusklight.url = "git+https://github.com/TwilitRealm/dusklight?ref=main&submodules=1";
nix command:
nix run 'git+https://github.com/TwilitRealm/dusklight?submodules=1'
Local checkout:
nix run '.?submodules=1#dusklight'
'';
dawn = pkgs.fetchzip {
url = "https://github.com/encounter/dawn/releases/download/${dawnVersion}/dawn-${dawnInfo.${system}.triple}.tar.gz";
@@ -126,14 +140,6 @@
JSON = pkgs.nlohmann_json.src;
XXHASH = pkgs.xxhash.src;
ZSTD = pkgs.zstd.src;
MINIZ = pkgs.fetchzip {
url = "https://github.com/richgel999/miniz/releases/download/3.0.2/miniz-3.0.2.zip";
hash = "sha256-DXysXkQEmoDAMMg1F8KexkwpXNyiHNzLJqXR9SMEkxk=";
stripRoot = false;
};
FMT = pkgs.fetchzip {
url = "https://github.com/fmtlib/fmt/archive/refs/tags/12.1.0.tar.gz";
hash = "sha256-ZmI1Dv0ZabPlxa02OpERI47jp7zFfjpeWCy1WyuPYZ0=";
@@ -159,16 +165,19 @@
};
dusklight =
pkgs.stdenv.mkDerivation {
pname = "dusklight";
version = versionSuffix;
src = ./.;
if !aurora then
throw needSubmodules
else
pkgs.stdenv.mkDerivation {
pname = "dusklight";
version = versionSuffix;
src = ./.;
postUnpack = ''
chmod -R u+w "$sourceRoot"
substituteInPlace "$sourceRoot/extern/aurora/CMakeLists.txt" \
--replace-warn "add_subdirectory(tests)" ""
'';
postUnpack = ''
chmod -R u+w "$sourceRoot"
substituteInPlace "$sourceRoot/extern/aurora/CMakeLists.txt" \
--replace-warn "add_subdirectory(tests)" ""
'';
nativeBuildInputs = [
pkgs.cmake
+43 -86
View File
@@ -9,8 +9,6 @@
#include "JSystem/JAudio2/JAUAudibleParam.h"
#include "JSystem/TPosition3.h"
#define Z2_AUDIO_PLAYERS 1
struct Z2Audible;
struct Z2AudibleAbsPos {
@@ -51,14 +49,10 @@ struct Z2AudioCamera {
f32 getCamDist() const { return mCamDist; }
/* 0x00 */ JGeometry::TPosition3f32 mViewMatrix;
/* 0x00 */ JGeometry::TPosition3f32 field_0x0;
/* 0x30 */ JGeometry::TVec3<f32> mVel;
/* 0x3C */ JGeometry::TVec3<f32> mPos;
/**
*
*/
/* 0x48 */ JGeometry::TVec3<f32> mLastPos;
/* 0x48 */ JGeometry::TVec3<f32> field_0x48;
/* 0x54 */ f32 mFovySin;
/* 0x58 */ f32 mVolCenterZ;
/* 0x5C */ f32 mTargetVolume;
@@ -89,14 +83,14 @@ struct Z2SpotMic {
/* 0x04 */ f32 field_0x4;
/* 0x08 */ f32 field_0x8;
/* 0x0C */ f32 field_0xc;
/* 0x10 */ Z2AudioCamera* field_0x10[Z2_AUDIO_PLAYERS];
/* 0x10 */ Z2AudioCamera* field_0x10[1];
/* 0x14 */ Vec* mPosPtr;
/* 0x18 */ f32 field_0x18[Z2_AUDIO_PLAYERS];
/* 0x18 */ f32 field_0x18[1];
/* 0x1C */ f32 field_0x1c;
/* 0x20 */ f32 field_0x20[Z2_AUDIO_PLAYERS];
/* 0x20 */ f32 field_0x20[1];
/* 0x24 */ bool mIgnoreIfOut;
/* 0x25 */ bool mMicOn;
/* 0x26 */ bool field_0x26[Z2_AUDIO_PLAYERS];
/* 0x26 */ bool field_0x26[1];
}; // Size: 0x28
struct Z2Audience3DSetting {
@@ -108,99 +102,62 @@ struct Z2Audience3DSetting {
void updateDolbyDist(f32, f32);
void calcVolumeFactorAll() {
mDistanceMaxes[1] = 1.25f * mDistanceMaxes[0];
mDistanceMaxes[2] = 1.5f * mDistanceMaxes[0];
mDistanceMaxes[3] = 2.0f * mDistanceMaxes[0];
mDistanceMaxes[4] = 3.0f * mDistanceMaxes[0];
mDistanceMaxes[5] = 4.0f * mDistanceMaxes[0];
mDistanceMaxes[6] = 6.0f * mDistanceMaxes[0];
mDistanceMaxes[7] = 8.0f * mDistanceMaxes[0];
mDistanceMaxes[8] = 0.9f * mDistanceMaxes[0];
mDistanceMaxes[9] = 0.8f * mDistanceMaxes[0];
mDistanceMaxes[10] = 0.7f * mDistanceMaxes[0];
mDistanceMaxes[11] = 0.6f * mDistanceMaxes[0];
mDistanceMaxes[12] = 0.5f * mDistanceMaxes[0];
mDistanceMaxes[13] = 0.4f * mDistanceMaxes[0];
mDistanceMaxes[14] = 0.3f * mDistanceMaxes[0];
field_0x0[1] = 1.25f * field_0x0[0];
field_0x0[2] = 1.5f * field_0x0[0];
field_0x0[3] = 2.0f * field_0x0[0];
field_0x0[4] = 3.0f * field_0x0[0];
field_0x0[5] = 4.0f * field_0x0[0];
field_0x0[6] = 6.0f * field_0x0[0];
field_0x0[7] = 8.0f * field_0x0[0];
field_0x0[8] = 0.9f * field_0x0[0];
field_0x0[9] = 0.8f * field_0x0[0];
field_0x0[10] = 0.7f * field_0x0[0];
field_0x0[11] = 0.6f * field_0x0[0];
field_0x0[12] = 0.5f * field_0x0[0];
field_0x0[13] = 0.4f * field_0x0[0];
field_0x0[14] = 0.3f * field_0x0[0];
for (int i = 0; i < 15; i++) {
mVolumeFactor[i] = (mMinDistanceVolume - 1.0f) / (mDistanceMaxes[i] - mMaxVolumeDistance);
field_0x70[i] = (field_0x40 - 1.0f) / (field_0x0[i] - field_0x3c);
}
}
void calcPriorityFactorAll() {
for (int i = 0; i < 15; i++) {
mPriorityFactor[i] = mMaxDistancePriority / (mDistanceMaxes[i] - mMaxVolumeDistance);
field_0xac[i] = field_0x64 / (field_0x0[i] - field_0x3c);
}
}
void calcFxMixFactorAll() {
for (int i = 0; i < 15; i++) {
mFxMixFactor[i] = (mMaxDistanceFxMix - mMinDistanceFxMix) / (mDistanceMaxes[i] - mMaxVolumeDistance);
field_0xe8[i] = (field_0x54 - field_0x50) / (field_0x0[i] - field_0x3c);
}
}
/**
* Maximum distance a sound can reach before being "far away"
* Being far away affects stuff like culling, lowering its priority, forcibly stopping it, etc.
* Sounds select which entry they use based on their VolBits.
*/
/* 0x000 */ f32 mDistanceMaxes[15];
/**
* Distance at which the max volume of a sound is reached.
* i.e. sounds do *not* get louder if they get closer than this.
*/
/* 0x03C */ f32 mMaxVolumeDistance;
/**
* FX Mix value at maximum distance (@ref mDistanceMaxes)
*/
/* 0x040 */ f32 mMinDistanceVolume;
/* 0x044 */ f32 mDolbyFrontDistanceMax;
/* 0x048 */ f32 mDolbyBehindDistanceMax;
/* 0x04C */ f32 mDolbyCenterValue;
/**
* FX Mix value at minimum distance (@ref mMaxVolumeDistance)
*/
/* 0x050 */ f32 mMinDistanceFxMix;
/**
* FX Mix value at maximum distance (@ref mDistanceMaxes)
*/
/* 0x054 */ f32 mMaxDistanceFxMix;
/* 0x058 */ f32 mPanFactor;
/* 0x05C */ f32 mSonicSpeed; // Used for doppler effect calculations.
/* 0x000 */ f32 field_0x0[15];
/* 0x03C */ f32 field_0x3c;
/* 0x040 */ f32 field_0x40;
/* 0x044 */ f32 field_0x44;
/* 0x048 */ f32 field_0x48;
/* 0x04C */ f32 field_0x4c;
/* 0x050 */ f32 field_0x50;
/* 0x054 */ f32 field_0x54;
/* 0x058 */ f32 field_0x58;
/* 0x05C */ f32 field_0x5c;
/* 0x060 */ f32 field_0x60;
/**
* Priority that sounds receive when "far away".
* @see mDistanceMaxes
*/
/* 0x064 */ u32 mMaxDistancePriority;
/* 0x064 */ u32 field_0x64;
/* 0x068 */ f32 field_0x68;
/* 0x06C */ f32 field_0x6c;
/* 0x070 */ f32 mVolumeFactor[15];
/* 0x0AC */ f32 mPriorityFactor[15];
/* 0x0E8 */ f32 mFxMixFactor[15];
/* 0x070 */ f32 field_0x70[15];
/* 0x0AC */ f32 field_0xac[15];
/* 0x0E8 */ f32 field_0xe8[15];
/* 0x124 */ bool mVolumeDistInit;
/* 0x125 */ bool mDolbyDistInit;
}; // Size: 0x128
struct Z2AudibleRelPos {
/* 0x00 */ JGeometry::TVec3<f32> mCameraRelative;
/**
* Distance from mCameraRelative. This is from the object root and not the
* exact distance used for volume/priority calculations.
*/
/* 0x0C */ f32 mTrueDistance;
/**
* Distance from mCameraRelative but offset by mVolCenterZ.
* This presumably means the distance is more centered on the object than mTrueDistance.
*/
/* 0x10 */ f32 mCenterDistance;
/* 0x00 */ JGeometry::TVec3<f32> field_0x00;
/* 0x0C */ f32 field_0xC;
/* 0x10 */ f32 field_0x10;
};
struct Z2AudibleChannel {
@@ -214,7 +171,7 @@ struct Z2AudibleChannel {
}
/* 0x00 */ JASSoundParams mParams;
/* 0x14 */ Z2AudibleRelPos mRelPos;
/* 0x14 */ Z2AudibleRelPos field_0x14;
/* 0x28 */ f32 field_0x28;
/* 0x2c */ f32 mPan;
/* 0x30 */ f32 mDolby;
@@ -243,8 +200,8 @@ struct Z2Audible : public JAIAudible, public JASPoolAllocObject<Z2Audible> {
/* 0x10 */ JAUAudibleParam mParam;
/* 0x14 */ Z2AudibleAbsPos mAbsPos;
/* 0x2C */ Z2AudibleChannel mChannel[Z2_AUDIO_PLAYERS];
/* 0x64 */ f32 mMicDistances[Z2_AUDIO_PLAYERS];
/* 0x2C */ Z2AudibleChannel mChannel[1];
/* 0x64 */ f32 field_0x64[1];
};
struct Z2Audience : public JAIAudience, public JASGlobalInstance<Z2Audience> {
+5
View File
@@ -46,6 +46,11 @@ public:
s32 getSeLoadStatus(u32 wave) { return getWaveLoadStatus(wave, 0); }
s32 getBgmLoadStatus(u32 wave) { return getWaveLoadStatus(wave, 1); }
u8 getDemoSeWaveNum() { return loadedDemoWave; }
#if TARGET_PC
u8 getLoadedSeWave_1() { return loadedSeWave_1;}
u8 getLoadedSeWave_2() { return loadedSeWave_2;}
#endif
private:
/* 0x00 */ JAISoundID BGM_ID;
+14 -2
View File
@@ -3912,6 +3912,16 @@ public:
u16 getReadyItem() { return dComIfGp_getSelectItem(mSelectItemId); }
static u32 getOtherHeapSize() { return 0xF0A60; }
#if TARGET_PC
u16 getEventId() { return mMsgFlow.getEventId(); }
bool checkSwimming() {return checkModeFlg(MODE_SWIMMING);}
BE<short>** getDomeLockChromaTable() {
return &field_0x0724->mAnmCRegDataR;
}
#endif
static DUSK_GAME_DATA daAlink_BckData const m_mainBckShield[20];
static DUSK_GAME_DATA daAlink_BckData const m_mainBckSword[5];
@@ -6391,7 +6401,8 @@ public:
class daAlinkHIO_huLight_c0 {
public:
static DUSK_GAME_DATA daAlinkHIO_huLight_c1 const m;
static DUSK_GAME_DATA daAlinkHIO_huLight_c1 IF_NOT_DUSK(const) m;
IF_DUSK(static DUSK_GAME_DATA daAlinkHIO_huLight_c1 const original;)
};
class daAlinkHIO_wlLight_c1 {
@@ -6465,7 +6476,8 @@ public:
class daAlinkHIO_kandelaar_c0 {
public:
static DUSK_GAME_DATA daAlinkHIO_kandelaar_c1 const m;
static DUSK_GAME_DATA daAlinkHIO_kandelaar_c1 IF_NOT_DUSK(const) m;
IF_DUSK(static DUSK_GAME_DATA daAlinkHIO_kandelaar_c1 const original;)
};
class daAlinkHIO_kandelaar_c : public daAlinkHIO_data_c {
+4 -1
View File
@@ -120,7 +120,10 @@ public:
BOOL chkAction(actionFunc action) { return action == mAction; }
static DUSK_GAME_DATA eventFunc mEvtSeqList[1];
#if TARGET_PC
// Keep track of last given bug for rando
static DUSK_GAME_DATA u8 mGivenInsectId;
#endif
private:
/* 0xB48 */ Z2Creature mSound;
/* 0xBD8 */ J3DModel* mpUmbrellaModel;
+3
View File
@@ -64,6 +64,9 @@ public:
virtual int Delete();
virtual BOOL checkSmallTbox() { return true; }
#if TARGET_PC
u8 getTboxNo() { return fopAcM_GetParamBit(this, 16, 8);}
#endif
u8 getModelType() { return fopAcM_GetParamBit(this, 8, 4); }
u8 getItemNo() { return fopAcM_GetParamBit(this, 0, 8); }
+4
View File
@@ -114,6 +114,10 @@ public:
bool checkBoomWindTgTimer() { return mBoomWindTgTimer == 0; }
#if TARGET_PC
void setRandomizerItem(bool setFoolishItemModel = false);
#endif
static DUSK_GAME_DATA procFunc mFuncPtr[];
static DUSK_GAME_DATA const dCcD_SrcCyl m_cyl_src;
static DUSK_GAME_DATA s32 m_timer_max;
+5
View File
@@ -7,4 +7,9 @@ class fopAc_ac_c;
int CheckFieldItemCreateHeap(fopAc_ac_c* actor);
int CheckItemCreateHeap(fopAc_ac_c* i_this);
#if TARGET_PC
// Used for foolish items in rando. Foolish item model id is saved to home.angle.z
#define M_ITEMNO_MODEL_ITEM_ID (IF_DUSK(randomizer_IsActive() && m_itemNo == dItemNo_Randomizer_FOOLISH_ITEM_e && home.angle.z != 0 ? home.angle.z :) m_itemNo)
#endif
#endif /* D_A_D_A_ITEMBASE_STATIC_H */
+10
View File
@@ -74,7 +74,17 @@ public:
s16 getAngleY() const { return mAngleY; }
void setAngleY(s16 angle) { mAngleY = angle;}
#if TARGET_PC
BOOL isRandomized() const;
#endif
static DUSK_GAME_DATA ResourceData const mData[23];
#if TARGET_PC
static DUSK_GAME_DATA ResourceData mRandoData[23];
#define M_SHOP_DATA (isRandomized() ? mRandoData : mData)
#else
#define M_SHOP_DATA mData
#endif
static DUSK_GAME_DATA f32 const m_cullfar_max;
enum {
+68
View File
@@ -474,6 +474,9 @@ public:
s8 getNextStageRoomNo() { return mNextStage.getRoomNo(); }
s8 getNextStageLayer() { return mNextStage.getLayer(); }
BOOL isEnableNextStage() { return mNextStage.isEnable(); }
#if TARGET_PC
void setEnableNextStage() { return mNextStage.setEnable(); }
#endif
void offEnableNextStage() { mNextStage.offEnable(); }
s8 getNextStageWipe() { return mNextStage.getWipe(); }
u8 getNextStageWipeSpeed() { return mNextStage.getWipeSpeed(); }
@@ -1276,6 +1279,10 @@ int dComIfGd_setShadow(u32 param_0, s8 param_1, J3DModel* param_2, cXyz* param_3
f32 param_5, f32 param_6, f32 param_7, cBgS_PolyInfo& param_8,
dKy_tevstr_c* param_9, s16 param_10, f32 param_11, TGXTexObj* param_12);
#if TARGET_PC
void dComIfGs_setupRandomizerSave();
#endif
inline dSv_info_c* dComIfGs_getSaveInfo() {
return &g_dComIfG_gameInfo.info;
}
@@ -1336,9 +1343,13 @@ inline u8 dComIfGs_getSelectEquipShield() {
return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getSelectEquip(COLLECT_SHIELD);
}
#if TARGET_PC
u8 dComIfGs_getCollectSmell();
#else
inline u8 dComIfGs_getCollectSmell() {
return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().getSelectEquip(COLLECT_SMELL);
}
#endif
inline void dComIfGs_setCollectSmell(u8 smell) {
g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusA().setSelectEquip(COLLECT_SMELL, smell);
@@ -1428,6 +1439,12 @@ inline BOOL dComIfGs_isDarkClearLV(int i_no) {
return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().isDarkClearLV(i_no);
}
#if TARGET_PC
inline u8 dComIfGs_getDarkClearLV() {
return g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().getDarkClearLV();
}
#endif
inline void dComIfGs_onTransformLV(int i_no) {
g_dComIfG_gameInfo.info.getPlayer().getPlayerStatusB().onTransformLV(i_no);
}
@@ -1505,6 +1522,12 @@ inline void dComIfGs_onRegionBit(int i_region) {
g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().onRegionBit(i_region);
}
#if TARGET_PC
inline void dComIfGs_setRegionBit(u8 i_region) {
g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().setRegionBit(i_region);
}
#endif
inline void dComIfGs_setPlayerFieldLastStayInfo(const char* i_stage, cXyz& i_pos, s16 i_angle,
s8 i_point, u8 i_region) {
g_dComIfG_gameInfo.info.getPlayer().getPlayerFieldLastStayInfo().set(i_stage, i_pos, i_angle,
@@ -1656,6 +1679,16 @@ inline void dComIfGs_setPachinkoNum(u8 i_num) {
g_dComIfG_gameInfo.info.getPlayer().getItemRecord().setPachinkoNum(i_num);
}
#if TARGET_PC
inline u8 dComIfGs_getAncientDocumentNum() {
return g_dComIfG_gameInfo.info.getPlayer().getItemRecord().getAncientDocumentNum();
}
inline void dComIfGs_setAncientDocumentNum(u8 i_num) {
g_dComIfG_gameInfo.info.getPlayer().getItemRecord().setAncientDocumentNum(i_num);
}
#endif
inline u8 dComIfGs_getPachinkoMax() {
return 50;
}
@@ -1828,7 +1861,16 @@ inline u8 dComIfGs_getGetNumber(int i_no) {
inline void dComIfGs_setGetNumber(int i_no, u8 i_value) {
g_dComIfG_gameInfo.info.getPlayer().getLetterInfo().setGetNumber(i_no, i_value);
}
#if TARGET_PC
// For rando
inline void dComIfGs_setAllLetterGet() {
g_dComIfG_gameInfo.info.getPlayer().getLetterInfo().setAllLetterGet();
}
inline void dComIfGs_setAllLetterRead() {
g_dComIfG_gameInfo.info.getPlayer().getLetterInfo().setAllLetterRead();
}
#endif
inline void dComIfGs_addFishNum(u8 param_0) {
g_dComIfG_gameInfo.info.getPlayer().getFishingInfo().addFishCount(param_0);
}
@@ -1944,6 +1986,16 @@ inline u8 dComIfGs_getPalLanguage() {
return g_dComIfG_gameInfo.info.getPlayer().getConfig().getPalLanguage();
}
#if TARGET_PC
// Kinda hacky, but will do for now
inline void dComIfGs_onRegionFlag(int i_stageNo, int i_no) {
auto regionFlags = reinterpret_cast<u8*>(&g_dComIfG_gameInfo.info.getSavedata().getSave(i_stageNo).getBit());
const int offset = i_no / 8;
const int shift = i_no % 8;
regionFlags[offset] |= (0x80 >> shift);
}
#endif
inline BOOL dComIfGs_isSaveTbox(int i_stageNo, int i_no) {
return g_dComIfG_gameInfo.info.getSavedata().getSave(i_stageNo).getBit().isTbox(i_no);
}
@@ -2028,6 +2080,10 @@ inline void dComIfGs_setKeyNum(u8 i_keyNum) {
g_dComIfG_gameInfo.info.getMemory().getBit().setKeyNum(i_keyNum);
}
#if TARGET_PC
u8 dComIfGs_getKeyNum(int i_stageNo);
#endif
inline void dComIfGs_onDungeonItemMap() {
g_dComIfG_gameInfo.info.getMemory().getBit().onDungeonItemMap();
}
@@ -2460,6 +2516,12 @@ inline s8 dComIfGp_getStartStageRoomNo() {
return g_dComIfG_gameInfo.play.getStartStageRoomNo();
}
#if TARGET_PC
inline s8 dComIfGp_getLayerNo() {
return g_dComIfG_gameInfo.play.getLayerNo(0);
}
#endif
inline s8 dComIfGp_getStartStageLayer() {
return g_dComIfG_gameInfo.play.getStartStageLayer();
}
@@ -2504,6 +2566,12 @@ inline void dComIfGp_offEnableNextStage() {
g_dComIfG_gameInfo.play.offEnableNextStage();
}
#if TARGET_PC
inline void dComIfGp_setEnableNextStage() {
g_dComIfG_gameInfo.play.setEnableNextStage();
}
#endif
inline s8 dComIfGp_getNextStageWipe() {
return g_dComIfG_gameInfo.play.getNextStageWipe();
}
+13 -2
View File
@@ -203,6 +203,9 @@ public:
DATASELPROC_DATA_SELECT_MOVE_ANIME,
DATASELPROC_SELECT_DATA_OPEN_MOVE,
DATASELPROC_SELECT_DATA_NAME_MOVE,
#if TARGET_PC
DATASELPROC_SELECT_DATA_PLAY_MOVE, // Select between vanilla or randomizer play
#endif
DATASELPROC_SELECT_DATA_OPENERASE_MOVE,
DATASELPROC_MENU_SELECT,
DATASELPROC_MENU_SELECT_MOVE_ANM,
@@ -331,6 +334,9 @@ public:
void makeRecInfo(u8);
void selectDataOpenMove();
void selectDataNameMove();
#if TARGET_PC
void selectDataPlayTypeMove();
#endif
void selectDataOpenEraseMove();
void menuSelect();
void menuSelectStart();
@@ -732,7 +738,12 @@ public:
/* 0x2378 */ J2DPicture* mpFadePict;
#endif
#ifdef TARGET_PC
dDlst_FileSelFade_c mFadeDlst;
struct mDusk {
dDlst_FileSelFade_c mFadeDlst;
bool mStartNameAnm;
bool mBackToFileSelect;
int mPendingRmlCloseFrames{0};
} mDusk;
#endif
#if PLATFORM_WII || PLATFORM_SHIELD
@@ -743,7 +754,7 @@ public:
};
#ifdef TARGET_PC
STATIC_ASSERT(sizeof(dFile_select_c) == 0x237C + sizeof(dDlst_FileSelFade_c));
STATIC_ASSERT(sizeof(dFile_select_c) == 0x237C + sizeof(dFile_select_c::mDusk));
#else
STATIC_ASSERT(sizeof(dFile_select_c) == 0x237C);
#endif
+134
View File
@@ -32,6 +32,11 @@ void item_func_ARROW_20();
void item_func_ARROW_30();
void item_func_ARROW_1();
void item_func_PACHINKO_SHOT();
#if TARGET_PC
void item_func_FOOLISH_ITEM();
void item_func_ORDON_PORTAL();
void item_func_SOUTH_FARON_PORTAL();
#endif
void item_func_WATER_BOMB_5();
void item_func_WATER_BOMB_10();
void item_func_WATER_BOMB_20();
@@ -65,6 +70,12 @@ void item_func_DUNGEON_EXIT_2();
void item_func_WALLET_LV1();
void item_func_WALLET_LV2();
void item_func_WALLET_LV3();
#if TARGET_PC
void item_func_UPPER_ZORAS_RIVER_PORTAL();
void item_func_CASTLE_TOWN_PORTAL();
void item_func_GERUDO_DESERT_PORTAL();
void item_func_NORTH_FARON_PORTAL();
#endif
void item_func_ZORAS_JEWEL();
void item_func_HAWK_EYE();
void item_func_WOOD_STICK();
@@ -81,13 +92,23 @@ void item_func_LIGHT_SWORD();
void item_func_FISHING_ROD_1();
void item_func_PACHINKO();
void item_func_COPY_ROD_2();
#if TARGET_PC
void item_func_KAKARIKO_GORGE_PORTAL();
void item_func_KAKARIKO_VILLAGE_PORTAL();
#endif
void item_func_BOMB_BAG_LV2();
void item_func_BOMB_BAG_LV1();
void item_func_BOMB_IN_BAG();
#if TARGET_PC
void item_func_DEATH_MOUNTAIN_PORTAL();
#endif
void item_func_LIGHT_ARROW();
void item_func_ARROW_LV1();
void item_func_ARROW_LV2();
void item_func_ARROW_LV3();
#if TARGET_PC
void item_func_ZORAS_DOMAIN_PORTAL();
#endif
void item_func_LURE_ROD();
void item_func_BOMB_ARROW();
void item_func_HAWK_ARROW();
@@ -133,8 +154,33 @@ void item_func_BILL();
void item_func_WOOD_STATUE();
void item_func_IRIAS_PENDANT();
void item_func_HORSE_FLUTE();
#if TARGET_PC
void item_func_FOREST_SMALL_KEY();
void item_func_MINES_SMALL_KEY();
void item_func_LAKEBED_SMALL_KEY();
void item_func_ARBITERS_SMALL_KEY();
void item_func_SNOWPEAK_SMALL_KEY();
void item_func_TEMPLE_OF_TIME_SMALL_KEY();
void item_func_CITY_SMALL_KEY();
void item_func_PALACE_SMALL_KEY();
void item_func_HYRULE_SMALL_KEY();
void item_func_CAMP_SMALL_KEY();
void item_func_LAKE_HYLIA_PORTAL();
#endif
void item_func_RAFRELS_MEMO();
void item_func_ASHS_SCRIBBLING();
#if TARGET_PC
void item_func_FOREST_BOSS_KEY();
void item_func_LAKEBED_BOSS_KEY();
void item_func_ARBITERS_BOSS_KEY();
void item_func_TEMPLE_OF_TIME_BOSS_KEY();
void item_func_CITY_BOSS_KEY();
void item_func_PALACE_BOSS_KEY();
void item_func_HYRULE_BOSS_KEY();
void item_func_FOREST_COMPASS();
void item_func_MINES_COMPASS();
void item_func_LAKEBED_COMPASS();
#endif
void item_func_CHUCHU_YELLOW2();
void item_func_OIL_BOTTLE3();
void item_func_SHOP_BEE_CHILD();
@@ -147,12 +193,34 @@ void item_func_FILLED_CONTAINER();
void item_func_MIRROR_PIECE_2();
void item_func_MIRROR_PIECE_3();
void item_func_MIRROR_PIECE_4();
#if TARGET_PC
void item_func_ARBITERS_COMPASS();
void item_func_SNOWPEAK_COMPASS();
void item_func_TEMPLE_OF_TIME_COMPASS();
void item_func_CITY_COMPASS();
void item_func_PALACE_COMPASS();
void item_func_HYRULE_COMPASS();
void item_func_MIRROR_CHAMBER_PORTAL();
void item_func_SNOWPEAK_PORTAL();
#endif
void item_func_SMELL_YELIA_POUCH();
void item_func_SMELL_PUMPKIN();
void item_func_SMELL_POH();
void item_func_SMELL_FISH();
void item_func_SMELL_CHILDREN();
void item_func_SMELL_MEDICINE();
#if TARGET_PC
void item_func_FOREST_MAP();
void item_func_MINES_MAP();
void item_func_LAKEBED_MAP();
void item_func_ARBITERS_MAP();
void item_func_SNOWPEAK_MAP();
void item_func_TEMPLE_OF_TIME_MAP();
void item_func_CITY_MAP();
void item_func_PALACE_MAP();
void item_func_HYRULE_MAP();
void item_func_SACRED_GROVE_PORTAL();
#endif
void item_func_M_BEETLE();
void item_func_F_BEETLE();
void item_func_M_BUTTERFLY();
@@ -177,7 +245,23 @@ void item_func_M_ANT();
void item_func_F_ANT();
void item_func_M_MAYFLY();
void item_func_F_MAYFLY();
#if TARGET_PC
void item_func_FUSED_SHADOW_1();
void item_func_FUSED_SHADOW_2();
void item_func_FUSED_SHADOW_3();
void item_func_MIRROR_PIECE_1();
#endif
void item_func_POU_SPIRIT();
#if TARGET_PC
void item_func_ENDING_BLOW();
void item_func_SHIELD_ATTACK();
void item_func_BACK_SLICE();
void item_func_HELM_SPLITTER();
void item_func_MORTAL_DRAW();
void item_func_JUMP_STRIKE();
void item_func_GREAT_SPIN();
void item_func_ELDIN_BRIDGE_PORTAL();
#endif
void item_func_ANCIENT_DOCUMENT();
void item_func_AIR_LETTER();
void item_func_ANCIENT_DOCUMENT2();
@@ -221,6 +305,10 @@ int item_getcheck_func_ARROW_20();
int item_getcheck_func_ARROW_30();
int item_getcheck_func_ARROW_1();
int item_getcheck_func_PACHINKO_SHOT();
#if TARGET_PC
int item_getcheck_func_ORDON_PORTAL();
int item_getcheck_func_SOUTH_FARON_PORTAL();
#endif
int item_getcheck_func_WATER_BOMB_5();
int item_getcheck_func_WATER_BOMB_10();
int item_getcheck_func_WATER_BOMB_20();
@@ -254,6 +342,12 @@ int item_getcheck_func_DUNGEON_EXIT_2();
int item_getcheck_func_WALLET_LV1();
int item_getcheck_func_WALLET_LV2();
int item_getcheck_func_WALLET_LV3();
#if TARGET_PC
int item_getcheck_func_UPPER_ZORAS_RIVER_PORTAL();
int item_getcheck_func_CASTLE_TOWN_PORTAL();
int item_getcheck_func_GERUDO_DESERT_PORTAL();
int item_getcheck_func_NORTH_FARON_PORTAL();
#endif
int item_getcheck_func_ZORAS_JEWEL();
int item_getcheck_func_HAWK_EYE();
int item_getcheck_func_WOOD_STICK();
@@ -270,13 +364,23 @@ int item_getcheck_func_LIGHT_SWORD();
int item_getcheck_func_FISHING_ROD_1();
int item_getcheck_func_PACHINKO();
int item_getcheck_func_COPY_ROD_2();
#if TARGET_PC
int item_getcheck_func_KAKARIKO_GORGE_PORTAL();
int item_getcheck_func_KAKARIKO_VILLAGE_PORTAL();
#endif
int item_getcheck_func_BOMB_BAG_LV2();
int item_getcheck_func_BOMB_BAG_LV1();
int item_getcheck_func_BOMB_IN_BAG();
#if TARGET_PC
int item_getcheck_func_DEATH_MOUNTAIN_PORTAL();
#endif
int item_getcheck_func_LIGHT_ARROW();
int item_getcheck_func_ARROW_LV1();
int item_getcheck_func_ARROW_LV2();
int item_getcheck_func_ARROW_LV3();
#if TARGET_PC
int item_getcheck_func_ZORAS_DOMAIN_PORTAL();
#endif
int item_getcheck_func_LURE_ROD();
int item_getcheck_func_BOMB_ARROW();
int item_getcheck_func_HAWK_ARROW();
@@ -322,6 +426,10 @@ int item_getcheck_func_BILL();
int item_getcheck_func_WOOD_STATUE();
int item_getcheck_func_IRIAS_PENDANT();
int item_getcheck_func_HORSE_FLUTE();
#if TARGET_PC
int item_getcheck_func_CAMP_SMALL_KEY();
int item_getcheck_func_LAKE_HYLIA_PORTAL();
#endif
int item_getcheck_func_RAFRELS_MEMO();
int item_getcheck_func_ASHS_SCRIBBLING();
int item_getcheck_func_CHUCHU_YELLOW2();
@@ -336,12 +444,19 @@ int item_getcheck_func_FILLED_CONTAINER();
int item_getcheck_func_MIRROR_PIECE_2();
int item_getcheck_func_MIRROR_PIECE_3();
int item_getcheck_func_MIRROR_PIECE_4();
#if TARGET_PC
int item_getcheck_func_MIRROR_CHAMBER_PORTAL();
int item_getcheck_func_SNOWPEAK_PORTAL();
#endif
int item_getcheck_func_SMELL_YELIA_POUCH();
int item_getcheck_func_SMELL_PUMPKIN();
int item_getcheck_func_SMELL_POH();
int item_getcheck_func_SMELL_FISH();
int item_getcheck_func_SMELL_CHILDREN();
int item_getcheck_func_SMELL_MEDICINE();
#if TARGET_PC
int item_getcheck_func_SACRED_GROVE_PORTAL();
#endif
int item_getcheck_func_M_BEETLE();
int item_getcheck_func_F_BEETLE();
int item_getcheck_func_M_BUTTERFLY();
@@ -366,7 +481,23 @@ int item_getcheck_func_M_ANT();
int item_getcheck_func_F_ANT();
int item_getcheck_func_M_MAYFLY();
int item_getcheck_func_F_MAYFLY();
#if TARGET_PC
int item_getcheck_func_FUSED_SHADOW_1();
int item_getcheck_func_FUSED_SHADOW_2();
int item_getcheck_func_FUSED_SHADOW_3();
int item_getcheck_func_MIRROR_PIECE_1();
#endif
int item_getcheck_func_POU_SPIRIT();
#if TARGET_PC
int item_getcheck_func_ENDING_BLOW();
int item_getcheck_func_SHIELD_ATTACK();
int item_getcheck_func_BACK_SLICE();
int item_getcheck_func_HELM_SPLITTER();
int item_getcheck_func_MORTAL_DRAW();
int item_getcheck_func_JUMP_STRIKE();
int item_getcheck_func_GREAT_SPIN();
int item_getcheck_func_ELDIN_BRIDGE_PORTAL();
#endif
int item_getcheck_func_ANCIENT_DOCUMENT();
int item_getcheck_func_AIR_LETTER();
int item_getcheck_func_ANCIENT_DOCUMENT2();
@@ -395,6 +526,9 @@ int checkItemGet(u8, int);
BOOL isHeart(u8 item_no);
int isBomb(u8);
int isArrow(u8);
#if TARGET_PC
int isRupee(u8);
#endif
int addBombCount(u8, u8);
BOOL isBottleItem(u8 item_no);
u8 check_itemno(int i_itemNo);
+327
View File
@@ -35,7 +35,65 @@ struct dItem_fieldItemResource {
/* 0xC */ u16 mHeapSize;
}; // Size: 0x10
#if TARGET_PC
// Delcared helper functions since we can't include dComIfg_isRandomizer here
dItem_itemResource* dItem_data_getItemResource();
dItem_fieldItemResource* dItem_data_getFieldItemResource();
dItem_itemInfo* dItem_data_getItemInfo();
#endif
struct dItem_data {
#if TARGET_PC
static const char* getArcName(u8 index) { return dItem_data_getItemResource()[index].mArcName; }
static s16 getBtpName(u8 index) { return dItem_data_getItemResource()[index].mBtpName; }
static s16 getBrkName(u8 index) { return dItem_data_getItemResource()[index].mBrkName; }
static s16 getBxaName(u8 index) { return -1; }
static s16 getBckName(u8 index) { return dItem_data_getItemResource()[index].mBckName; }
static s16 getBpkName(u8 index) { return -1; }
static s16 getBtkName(u8 index) { return dItem_data_getItemResource()[index].mBtkName; }
static s16 getBmdName(u8 index) { return dItem_data_getItemResource()[index].mBmdName; }
static s8 getTevFrm(u8 index) { return dItem_data_getItemResource()[index].mTevFrm; }
static s8 getBtpFrm(u8 index) { return dItem_data_getItemResource()[index].mBtpFrm; }
static s16 getTexture(u8 index) { return dItem_data_getItemResource()[index].mTexture; }
static u8 getTexScale (u8 index) { return dItem_data_getItemResource()[index].mTexScale; }
static const char* getFieldArc(u8 index) { return dItem_data_getFieldItemResource()[index].mFieldArc; }
static s16 getItemBmdName(u8 index) { return dItem_data_getFieldItemResource()[index].mItemBmdName; }
static s16 getItemBtkName(u8 index) { return -1; }
static s16 getItemBpkName(u8 index) { return -1; }
static s16 getItemBckName(u8 index) { return dItem_data_getFieldItemResource()[index].mItemBckName; }
static s16 getItemBxaName(u8 index) { return -1; }
static s16 getItemBrkName(u8 index) { return dItem_data_getFieldItemResource()[index].mItemBrkName; }
static s16 getItemBtpName(u8 index) { return -1; }
static BOOL chkFlag(u8 index, int flag) { return dItem_data_getItemInfo()[index].mFlag & flag; }
static u8 getShadowSize(u8 index) { return dItem_data_getItemInfo()[index].mShadowSize; }
static const u8 getH(u8 index) { return dItem_data_getItemInfo()[index].mH; }
static const u8 getR(u8 index) { return dItem_data_getItemInfo()[index].mR; }
static u16 getFieldHeapSize(u8 index) { return dItem_data_getFieldItemResource()[index].mHeapSize; }
#else
static const char* getArcName(u8 index) { return item_resource[index].mArcName; }
static s16 getBtpName(u8 index) { return item_resource[index].mBtpName; }
@@ -85,10 +143,16 @@ struct dItem_data {
static const u8 getR(u8 index) { return item_info[index].mR; }
static u16 getFieldHeapSize(u8 index) { return field_item_res[index].mHeapSize; }
#endif
static DUSK_GAME_DATA dItem_itemResource item_resource[255];
static DUSK_GAME_DATA dItem_fieldItemResource field_item_res[255];
static DUSK_GAME_DATA dItem_itemInfo item_info[255];
#if TARGET_PC
static DUSK_GAME_DATA dItem_itemResource item_resource_randomizer[255];
static DUSK_GAME_DATA dItem_fieldItemResource field_item_res_randomizer[255];
static DUSK_GAME_DATA dItem_itemInfo item_info_randomizer[255];
#endif
};
enum {
@@ -350,4 +414,267 @@ enum {
/* 0xFF */ dItemNo_NONE_e,
};
#if TARGET_PC
// Randomizer item ids. Mostly the same, but we use most unused
// entries for custom portals and keys
enum {
/* 0x00 */ dItemNo_Randomizer_HEART_e,
/* 0x01 */ dItemNo_Randomizer_GREEN_RUPEE_e,
/* 0x02 */ dItemNo_Randomizer_BLUE_RUPEE_e,
/* 0x03 */ dItemNo_Randomizer_YELLOW_RUPEE_e,
/* 0x04 */ dItemNo_Randomizer_RED_RUPEE_e,
/* 0x05 */ dItemNo_Randomizer_PURPLE_RUPEE_e,
/* 0x06 */ dItemNo_Randomizer_ORANGE_RUPEE_e,
/* 0x07 */ dItemNo_Randomizer_SILVER_RUPEE_e,
/* 0x08 */ dItemNo_Randomizer_S_MAGIC_e,
/* 0x09 */ dItemNo_Randomizer_L_MAGIC_e,
/* 0x0A */ dItemNo_Randomizer_BOMB_5_e,
/* 0x0B */ dItemNo_Randomizer_BOMB_10_e,
/* 0x0C */ dItemNo_Randomizer_BOMB_20_e,
/* 0x0D */ dItemNo_Randomizer_BOMB_30_e,
/* 0x0E */ dItemNo_Randomizer_ARROW_10_e,
/* 0x0F */ dItemNo_Randomizer_ARROW_20_e,
/* 0x10 */ dItemNo_Randomizer_ARROW_30_e,
/* 0x11 */ dItemNo_Randomizer_ARROW_1_e,
/* 0x12 */ dItemNo_Randomizer_PACHINKO_SHOT_e,
/* 0x13 */ dItemNo_Randomizer_FOOLISH_ITEM_e,
/* 0x14 */ dItemNo_Randomizer_ORDON_PORTAL_e,
/* 0x15 */ dItemNo_Randomizer_SOUTH_FARON_PORTAL_e,
/* 0x16 */ dItemNo_Randomizer_WATER_BOMB_5_e,
/* 0x17 */ dItemNo_Randomizer_WATER_BOMB_10_e,
/* 0x18 */ dItemNo_Randomizer_WATER_BOMB_20_e,
/* 0x19 */ dItemNo_Randomizer_WATER_BOMB_30_e,
/* 0x1A */ dItemNo_Randomizer_BOMB_INSECT_5_e,
/* 0x1B */ dItemNo_Randomizer_BOMB_INSECT_10_e,
/* 0x1C */ dItemNo_Randomizer_BOMB_INSECT_20_e,
/* 0x1D */ dItemNo_Randomizer_BOMB_INSECT_30_e,
/* 0x1E */ dItemNo_Randomizer_RECOVERY_FAILY_e,
/* 0x1F */ dItemNo_Randomizer_TRIPLE_HEART_e,
/* 0x20 */ dItemNo_Randomizer_SMALL_KEY_e,
/* 0x21 */ dItemNo_Randomizer_KAKERA_HEART_e,
/* 0x22 */ dItemNo_Randomizer_UTAWA_HEART_e,
/* 0x23 */ dItemNo_Randomizer_MAP_e,
/* 0x24 */ dItemNo_Randomizer_COMPUS_e,
/* 0x25 */ dItemNo_Randomizer_DUNGEON_EXIT_e,
/* 0x26 */ dItemNo_Randomizer_BOSS_KEY_e,
/* 0x27 */ dItemNo_Randomizer_DUNGEON_BACK_e,
/* 0x28 */ dItemNo_Randomizer_SWORD_e,
/* 0x29 */ dItemNo_Randomizer_MASTER_SWORD_e,
/* 0x2A */ dItemNo_Randomizer_WOOD_SHIELD_e,
/* 0x2B */ dItemNo_Randomizer_SHIELD_e,
/* 0x2C */ dItemNo_Randomizer_HYLIA_SHIELD_e,
/* 0x2D */ dItemNo_Randomizer_TKS_LETTER_e,
/* 0x2E */ dItemNo_Randomizer_WEAR_CASUAL_e,
/* 0x2F */ dItemNo_Randomizer_WEAR_KOKIRI_e,
/* 0x30 */ dItemNo_Randomizer_ARMOR_e,
/* 0x31 */ dItemNo_Randomizer_WEAR_ZORA_e,
/* 0x32 */ dItemNo_Randomizer_MAGIC_LV1_e,
/* 0x33 */ dItemNo_Randomizer_DUNGEON_EXIT_2_e,
/* 0x34 */ dItemNo_Randomizer_WALLET_LV1_e,
/* 0x35 */ dItemNo_Randomizer_WALLET_LV2_e,
/* 0x36 */ dItemNo_Randomizer_WALLET_LV3_e,
/* 0x37 */ dItemNo_Randomizer_NOENTRY_55_e,
/* 0x38 */ dItemNo_Randomizer_NOENTRY_56_e,
/* 0x39 */ dItemNo_Randomizer_UPPER_ZORAS_RIVER_PORTAL_e,
/* 0x3A */ dItemNo_Randomizer_CASTLE_TOWN_PORTAL_e,
/* 0x3B */ dItemNo_Randomizer_GERUDO_DESERT_PORTAL_e,
/* 0x3C */ dItemNo_Randomizer_NORTH_FARON_PORTAL_e,
/* 0x3D */ dItemNo_Randomizer_ZORAS_JEWEL_e,
/* 0x3E */ dItemNo_Randomizer_HAWK_EYE_e,
/* 0x3F */ dItemNo_Randomizer_WOOD_STICK_e,
/* 0x40 */ dItemNo_Randomizer_BOOMERANG_e,
/* 0x41 */ dItemNo_Randomizer_SPINNER_e,
/* 0x42 */ dItemNo_Randomizer_IRONBALL_e,
/* 0x43 */ dItemNo_Randomizer_BOW_e,
/* 0x44 */ dItemNo_Randomizer_HOOKSHOT_e,
/* 0x45 */ dItemNo_Randomizer_HVY_BOOTS_e,
/* 0x46 */ dItemNo_Randomizer_COPY_ROD_e,
/* 0x47 */ dItemNo_Randomizer_W_HOOKSHOT_e,
/* 0x48 */ dItemNo_Randomizer_KANTERA_e,
/* 0x49 */ dItemNo_Randomizer_LIGHT_SWORD_e,
/* 0x4A */ dItemNo_Randomizer_FISHING_ROD_1_e,
/* 0x4B */ dItemNo_Randomizer_PACHINKO_e,
/* 0x4C */ dItemNo_Randomizer_COPY_ROD_2_e,
/* 0x4D */ dItemNo_Randomizer_KAKARIKO_GORGE_PORTAL_e,
/* 0x4E */ dItemNo_Randomizer_KAKARIKO_VILLAGE_PORTAL_e,
/* 0x4F */ dItemNo_Randomizer_BOMB_BAG_LV2_e,
/* 0x50 */ dItemNo_Randomizer_BOMB_BAG_LV1_e,
/* 0x51 */ dItemNo_Randomizer_BOMB_IN_BAG_e,
/* 0x52 */ dItemNo_Randomizer_DEATH_MOUNTAIN_PORTAL_e,
/* 0x53 */ dItemNo_Randomizer_LIGHT_ARROW_e,
/* 0x54 */ dItemNo_Randomizer_ARROW_LV1_e,
/* 0x55 */ dItemNo_Randomizer_ARROW_LV2_e,
/* 0x56 */ dItemNo_Randomizer_ARROW_LV3_e,
/* 0x57 */ dItemNo_Randomizer_ZORAS_DOMAIN_PORTAL_e,
/* 0x58 */ dItemNo_Randomizer_LURE_ROD_e,
/* 0x59 */ dItemNo_Randomizer_BOMB_ARROW_e,
/* 0x5A */ dItemNo_Randomizer_HAWK_ARROW_e,
/* 0x5B */ dItemNo_Randomizer_BEE_ROD_e,
/* 0x5C */ dItemNo_Randomizer_JEWEL_ROD_e,
/* 0x5D */ dItemNo_Randomizer_WORM_ROD_e,
/* 0x5E */ dItemNo_Randomizer_JEWEL_BEE_ROD_e,
/* 0x5F */ dItemNo_Randomizer_JEWEL_WORM_ROD_e,
/* 0x60 */ dItemNo_Randomizer_EMPTY_BOTTLE_e,
/* 0x61 */ dItemNo_Randomizer_RED_BOTTLE_e,
/* 0x62 */ dItemNo_Randomizer_GREEN_BOTTLE_e,
/* 0x63 */ dItemNo_Randomizer_BLUE_BOTTLE_e,
/* 0x64 */ dItemNo_Randomizer_MILK_BOTTLE_e,
/* 0x65 */ dItemNo_Randomizer_HALF_MILK_BOTTLE_e,
/* 0x66 */ dItemNo_Randomizer_OIL_BOTTLE_e,
/* 0x67 */ dItemNo_Randomizer_WATER_BOTTLE_e,
/* 0x68 */ dItemNo_Randomizer_OIL_BOTTLE_2_e,
/* 0x69 */ dItemNo_Randomizer_RED_BOTTLE_2_e,
/* 0x6A */ dItemNo_Randomizer_UGLY_SOUP_e,
/* 0x6B */ dItemNo_Randomizer_HOT_SPRING_e,
/* 0x6C */ dItemNo_Randomizer_FAIRY_e,
/* 0x6D */ dItemNo_Randomizer_HOT_SPRING_2_e,
/* 0x6E */ dItemNo_Randomizer_OIL2_e,
/* 0x6F */ dItemNo_Randomizer_OIL_e,
/* 0x70 */ dItemNo_Randomizer_NORMAL_BOMB_e,
/* 0x71 */ dItemNo_Randomizer_WATER_BOMB_e,
/* 0x72 */ dItemNo_Randomizer_POKE_BOMB_e,
/* 0x73 */ dItemNo_Randomizer_FAIRY_DROP_e,
/* 0x74 */ dItemNo_Randomizer_WORM_e,
/* 0x75 */ dItemNo_Randomizer_DROP_BOTTLE_e,
/* 0x76 */ dItemNo_Randomizer_BEE_CHILD_e,
/* 0x77 */ dItemNo_Randomizer_CHUCHU_RARE_e,
/* 0x78 */ dItemNo_Randomizer_CHUCHU_RED_e,
/* 0x79 */ dItemNo_Randomizer_CHUCHU_BLUE_e,
/* 0x7A */ dItemNo_Randomizer_CHUCHU_GREEN_e,
/* 0x7B */ dItemNo_Randomizer_CHUCHU_YELLOW_e,
/* 0x7C */ dItemNo_Randomizer_CHUCHU_PURPLE_e,
/* 0x7D */ dItemNo_Randomizer_LV1_SOUP_e,
/* 0x7E */ dItemNo_Randomizer_LV2_SOUP_e,
/* 0x7F */ dItemNo_Randomizer_LV3_SOUP_e,
/* 0x80 */ dItemNo_Randomizer_LETTER_e,
/* 0x81 */ dItemNo_Randomizer_BILL_e,
/* 0x82 */ dItemNo_Randomizer_WOOD_STATUE_e,
/* 0x83 */ dItemNo_Randomizer_IRIAS_PENDANT_e,
/* 0x84 */ dItemNo_Randomizer_HORSE_FLUTE_e,
/* 0x85 */ dItemNo_Randomizer_FOREST_SMALL_KEY_e,
/* 0x86 */ dItemNo_Randomizer_MINES_SMALL_KEY_e,
/* 0x87 */ dItemNo_Randomizer_LAKEBED_SMALL_KEY_e,
/* 0x88 */ dItemNo_Randomizer_ARBITERS_SMALL_KEY_e,
/* 0x89 */ dItemNo_Randomizer_SNOWPEAK_SMALL_KEY_e,
/* 0x8A */ dItemNo_Randomizer_TEMPLE_OF_TIME_SMALL_KEY_e,
/* 0x8B */ dItemNo_Randomizer_CITY_SMALL_KEY_e,
/* 0x8C */ dItemNo_Randomizer_PALACE_SMALL_KEY_e,
/* 0x8D */ dItemNo_Randomizer_HYRULE_SMALL_KEY_e,
/* 0x8E */ dItemNo_Randomizer_CAMP_SMALL_KEY_e,
/* 0x8F */ dItemNo_Randomizer_LAKE_HYLIA_PORTAL_e,
/* 0x90 */ dItemNo_Randomizer_RAFRELS_MEMO_e,
/* 0x91 */ dItemNo_Randomizer_ASHS_SCRIBBLING_e,
/* 0x92 */ dItemNo_Randomizer_FOREST_BOSS_KEY_e,
/* 0x93 */ dItemNo_Randomizer_LAKEBED_BOSS_KEY_e,
/* 0x94 */ dItemNo_Randomizer_ARBITERS_BOSS_KEY_e,
/* 0x95 */ dItemNo_Randomizer_TEMPLE_OF_TIME_BOSS_KEY_e,
/* 0x96 */ dItemNo_Randomizer_CITY_BOSS_KEY_e,
/* 0x97 */ dItemNo_Randomizer_PALACE_BOSS_KEY_e,
/* 0x98 */ dItemNo_Randomizer_HYRULE_BOSS_KEY_e,
/* 0x99 */ dItemNo_Randomizer_FOREST_COMPASS_e,
/* 0x9A */ dItemNo_Randomizer_MINES_COMPASS_e,
/* 0x9B */ dItemNo_Randomizer_LAKEBED_COMPASS_e,
/* 0x9C */ dItemNo_Randomizer_CHUCHU_YELLOW2_e,
/* 0x9D */ dItemNo_Randomizer_OIL_BOTTLE3_e,
/* 0x9E */ dItemNo_Randomizer_SHOP_BEE_CHILD_e,
/* 0x9F */ dItemNo_Randomizer_CHUCHU_BLACK_e,
/* 0xA0 */ dItemNo_Randomizer_LIGHT_DROP_e,
/* 0xA1 */ dItemNo_Randomizer_DROP_CONTAINER_e,
/* 0xA2 */ dItemNo_Randomizer_DROP_CONTAINER02_e,
/* 0xA3 */ dItemNo_Randomizer_DROP_CONTAINER03_e,
/* 0xA4 */ dItemNo_Randomizer_FILLED_CONTAINER_e,
/* 0xA5 */ dItemNo_Randomizer_MIRROR_PIECE_2_e,
/* 0xA6 */ dItemNo_Randomizer_MIRROR_PIECE_3_e,
/* 0xA7 */ dItemNo_Randomizer_MIRROR_PIECE_4_e,
/* 0xA8 */ dItemNo_Randomizer_ARBITERS_COMPASS_e,
/* 0xA9 */ dItemNo_Randomizer_SNOWPEAK_COMPASS_e,
/* 0xAA */ dItemNo_Randomizer_TEMPLE_OF_TIME_COMPASS_e,
/* 0xAB */ dItemNo_Randomizer_CITY_COMPASS_e,
/* 0xAC */ dItemNo_Randomizer_PALACE_COMPASS_e,
/* 0xAD */ dItemNo_Randomizer_HYRULE_COMPASS_e,
/* 0xAE */ dItemNo_Randomizer_MIRROR_CHAMBER_PORTAL_e,
/* 0xAF */ dItemNo_Randomizer_SNOWPEAK_PORTAL_e,
/* 0xB0 */ dItemNo_Randomizer_SMELL_YELIA_POUCH_e,
/* 0xB1 */ dItemNo_Randomizer_SMELL_PUMPKIN_e,
/* 0xB2 */ dItemNo_Randomizer_SMELL_POH_e,
/* 0xB3 */ dItemNo_Randomizer_SMELL_FISH_e,
/* 0xB4 */ dItemNo_Randomizer_SMELL_CHILDREN_e,
/* 0xB5 */ dItemNo_Randomizer_SMELL_MEDICINE_e,
/* 0xB6 */ dItemNo_Randomizer_FOREST_MAP_e,
/* 0xB7 */ dItemNo_Randomizer_MINES_MAP_e,
/* 0xB8 */ dItemNo_Randomizer_LAKEBED_MAP_e,
/* 0xB9 */ dItemNo_Randomizer_ARBITERS_MAP_e,
/* 0xBA */ dItemNo_Randomizer_SNOWPEAK_MAP_e,
/* 0xBB */ dItemNo_Randomizer_TEMPLE_OF_TIME_MAP_e,
/* 0xBC */ dItemNo_Randomizer_CITY_MAP_e,
/* 0xBD */ dItemNo_Randomizer_PALACE_MAP_e,
/* 0xBE */ dItemNo_Randomizer_HYRULE_MAP_e,
/* 0xBF */ dItemNo_Randomizer_SACRED_GROVE_PORTAL_e,
/* 0xC0 */ dItemNo_Randomizer_M_BEETLE_e,
/* 0xC1 */ dItemNo_Randomizer_F_BEETLE_e,
/* 0xC2 */ dItemNo_Randomizer_M_BUTTERFLY_e,
/* 0xC3 */ dItemNo_Randomizer_F_BUTTERFLY_e,
/* 0xC4 */ dItemNo_Randomizer_M_STAG_BEETLE_e,
/* 0xC5 */ dItemNo_Randomizer_F_STAG_BEETLE_e,
/* 0xC6 */ dItemNo_Randomizer_M_GRASSHOPPER_e,
/* 0xC7 */ dItemNo_Randomizer_F_GRASSHOPPER_e,
/* 0xC8 */ dItemNo_Randomizer_M_NANAFUSHI_e,
/* 0xC9 */ dItemNo_Randomizer_F_NANAFUSHI_e,
/* 0xCA */ dItemNo_Randomizer_M_DANGOMUSHI_e,
/* 0xCB */ dItemNo_Randomizer_F_DANGOMUSHI_e,
/* 0xCC */ dItemNo_Randomizer_M_MANTIS_e,
/* 0xCD */ dItemNo_Randomizer_F_MANTIS_e,
/* 0xCE */ dItemNo_Randomizer_M_LADYBUG_e,
/* 0xCF */ dItemNo_Randomizer_F_LADYBUG_e,
/* 0xD0 */ dItemNo_Randomizer_M_SNAIL_e,
/* 0xD1 */ dItemNo_Randomizer_F_SNAIL_e,
/* 0xD2 */ dItemNo_Randomizer_M_DRAGONFLY_e,
/* 0xD3 */ dItemNo_Randomizer_F_DRAGONFLY_e,
/* 0xD4 */ dItemNo_Randomizer_M_ANT_e,
/* 0xD5 */ dItemNo_Randomizer_F_ANT_e,
/* 0xD6 */ dItemNo_Randomizer_M_MAYFLY_e,
/* 0xD7 */ dItemNo_Randomizer_F_MAYFLY_e,
/* 0xD8 */ dItemNo_Randomizer_FUSED_SHADOW_1_e,
/* 0xD9 */ dItemNo_Randomizer_FUSED_SHADOW_2_e,
/* 0xDA */ dItemNo_Randomizer_FUSED_SHADOW_3_e,
/* 0xDB */ dItemNo_Randomizer_MIRROR_PIECE_1_e,
/* 0xDC */ dItemNo_Randomizer_NOENTRY_220_e,
/* 0xDD */ dItemNo_Randomizer_NOENTRY_221_e,
/* 0xDE */ dItemNo_Randomizer_NOENTRY_222_e,
/* 0xDF */ dItemNo_Randomizer_NOENTRY_223_e,
/* 0xE0 */ dItemNo_Randomizer_POU_SPIRIT_e,
/* 0xE1 */ dItemNo_Randomizer_ENDING_BLOW_e,
/* 0xE2 */ dItemNo_Randomizer_SHIELD_ATTACK_e,
/* 0xE3 */ dItemNo_Randomizer_BACK_SLICE_e,
/* 0xE4 */ dItemNo_Randomizer_HELM_SPLITTER_e,
/* 0xE5 */ dItemNo_Randomizer_MORTAL_DRAW_e,
/* 0xE6 */ dItemNo_Randomizer_JUMP_STRIKE_e,
/* 0xE7 */ dItemNo_Randomizer_GREAT_SPIN_e,
/* 0xE8 */ dItemNo_Randomizer_ELDIN_BRIDGE_PORTAL_e,
/* 0xE9 */ dItemNo_Randomizer_ANCIENT_DOCUMENT_e,
/* 0xEA */ dItemNo_Randomizer_AIR_LETTER_e,
/* 0xEB */ dItemNo_Randomizer_ANCIENT_DOCUMENT2_e,
/* 0xEC */ dItemNo_Randomizer_LV7_DUNGEON_EXIT_e,
/* 0xED */ dItemNo_Randomizer_LINKS_SAVINGS_e,
/* 0xEE */ dItemNo_Randomizer_SMALL_KEY2_e,
/* 0xEF */ dItemNo_Randomizer_POU_FIRE1_e,
/* 0xF0 */ dItemNo_Randomizer_POU_FIRE2_e,
/* 0xF1 */ dItemNo_Randomizer_POU_FIRE3_e,
/* 0xF2 */ dItemNo_Randomizer_POU_FIRE4_e,
/* 0xF3 */ dItemNo_Randomizer_BOSSRIDER_KEY_e,
/* 0xF4 */ dItemNo_Randomizer_TOMATO_PUREE_e,
/* 0xF5 */ dItemNo_Randomizer_TASTE_e,
/* 0xF6 */ dItemNo_Randomizer_LV5_BOSS_KEY_e,
/* 0xF7 */ dItemNo_Randomizer_SURFBOARD_e,
/* 0xF8 */ dItemNo_Randomizer_KANTERA2_e,
/* 0xF9 */ dItemNo_Randomizer_L2_KEY_PIECES1_e,
/* 0xFA */ dItemNo_Randomizer_L2_KEY_PIECES2_e,
/* 0xFB */ dItemNo_Randomizer_L2_KEY_PIECES3_e,
/* 0xFC */ dItemNo_Randomizer_KEY_OF_CARAVAN_e,
/* 0xFD */ dItemNo_Randomizer_LV2_BOSS_KEY_e,
/* 0xFE */ dItemNo_Randomizer_KEY_OF_FILONE_e,
/* 0xFF */ dItemNo_Randomizer_NONE_e,
};
#endif
#endif /* D_D_ITEM_DATA_H */
+2
View File
@@ -75,6 +75,7 @@ public:
bool dpdMove();
u8 openExplain(u8);
#if TARGET_PC
void updateSlotImage(u8 slot);
bool pointerMove();
#endif
@@ -219,6 +220,7 @@ private:
bool mCursorInterpCurrAngular;
bool mCursorInterpInit;
bool mPointerTouchPressHoveredCurrent;
J2DPicture* mDpadIcon;
#endif
};
+3 -1
View File
@@ -129,7 +129,9 @@ public:
bool getPlayerSubject();
bool isBButtonShow(bool);
s16 getButtonTimer();
#if TARGET_PC
f32 getZButtonAlpha() { return mButtonZAlpha;}
#endif
virtual ~dMeter2Draw_c();
J2DScreen* getMainScreenPtr() { return mpScreen; }
+23
View File
@@ -41,6 +41,26 @@ public:
/* 0x12 */ BE(u16) unk_0x12;
};
#if TARGET_PC
// Default attributes for custom text ids
static JMSMesgEntry_c defaultJMSMesgEntry{
.string_offset = 0,
.message_id = 0,
.event_label_id = 0,
.se_speaker = 0x24,
.fuki_kind = 0x00,
.output_type = 0x00,
.fuki_pos_type = 0x00,
.unk_0xc = 0xFF,
.unk_0xd = 0x00,
.se_mood = 0x00,
.camera_id = 0x00,
.base_anm_id = 0x02,
.face_anm_id = 0x03,
.unk_0x12 = 0x0400,
};
#endif
class JMSMesgInfo_c {
public:
/* 0x00 */ bmg_section_t header; // section header
@@ -48,6 +68,9 @@ public:
/* 0x0A */ BE(u16) entry_size; // size of an entry
/* 0x0C */ u8 padding[4]; // padding
/* 0x10 */ JMSMesgEntry_c entries[0];
#if TARGET_PC
JMSMesgEntry_c& getEntry(u16 index);
#endif
};
class COutFont_c;
+25 -2
View File
@@ -58,6 +58,9 @@ public:
int checkEventRender(int*, int*, int*, int*);
void remove();
u16 getEventId(int*);
#if TARGET_PC
u16 getEventId();
#endif
u32 getMsgNo();
u32 getNowMsgNo();
msg_class* getMsg();
@@ -128,6 +131,11 @@ public:
u16 query051(mesg_flow_node_branch*, fopAc_ac_c*, int);
u16 query052(mesg_flow_node_branch*, fopAc_ac_c*, int);
u16 query053(mesg_flow_node_branch*, fopAc_ac_c*, int);
#if TARGET_PC
u16 query054(mesg_flow_node_branch*, fopAc_ac_c*, int);
u16 query055(mesg_flow_node_branch*, fopAc_ac_c*, int);
u16 query056(mesg_flow_node_branch*, fopAc_ac_c*, int);
#endif
int event000(mesg_flow_node_event*, fopAc_ac_c*);
int event001(mesg_flow_node_event*, fopAc_ac_c*);
int event002(mesg_flow_node_event*, fopAc_ac_c*);
@@ -171,6 +179,12 @@ public:
int event040(mesg_flow_node_event*, fopAc_ac_c*);
int event041(mesg_flow_node_event*, fopAc_ac_c*);
int event042(mesg_flow_node_event*, fopAc_ac_c*);
#if TARGET_PC
// events for rando
int event043(mesg_flow_node_event*, fopAc_ac_c*);
int event044(mesg_flow_node_event*, fopAc_ac_c*);
int event045(mesg_flow_node_event*, fopAc_ac_c*);
#endif
void initWord(fopAc_ac_c*, const char*, u8, int, fopAc_ac_c**);
@@ -185,8 +199,17 @@ public:
void setMsg(u32 msg) { mMsg = msg; }
bool checkEndFlow() { return (u32)field_0x26 == 1; }
static DUSK_GAME_DATA queryFunc mQueryList[53];
static DUSK_GAME_DATA eventFunc mEventList[43];
static DUSK_GAME_DATA queryFunc mQueryList[DUSK_IF_ELSE(56, 53)];
static DUSK_GAME_DATA eventFunc mEventList[DUSK_IF_ELSE(46, 43)];
#if TARGET_PC
// patch funcs for rando
u32 getKeyForIndex(u16 nodeIdx);
void randoPatchNodeType(u8& type, u16 nodeIdx);
void randoPatchMessageNode(mesg_flow_node*& message_node, u16 nodeIdx);
void randoPatchBranchNode(mesg_flow_node_branch*& branch_node, u16 nodeIdx);
void randoPatchEventNode(mesg_flow_node_event*& event_node, u16 nodeIdx);
#endif
private:
/* 0x04 */ u8* mFlow_p;
+33
View File
@@ -10,6 +10,10 @@
#include "JSystem/JHostIO/JORReflexible.h"
#include "helpers/endian.h"
#if TARGET_PC
#include <unordered_map>
#endif
static const int DEFAULT_SELECT_ITEM_INDEX = 0;
static const int MAX_SELECT_ITEM = 4;
static const int SELECT_ITEM_NUM = 2;
@@ -199,6 +203,9 @@ public:
void setTime(f32 i_time) { mTime = i_time; }
u16 getDate() const { return mDate; }
void setDate(u16 i_date) { mDate = i_date; }
#if TARGET_PC
u8 getDarkClearLV() const { return mDarkClearLevelFlag; }
#endif
/* 0x00 */ BE(OSTime) mDateIpl;
/* 0x08 */ u8 mTransformLevelFlag;
@@ -272,6 +279,9 @@ public:
bool isFieldDataExistFlag() const { return mFieldDataExistFlag ? true : false; }
void offFieldDataExistFlag() { mFieldDataExistFlag = false; }
void onFieldDataExistFlag() { mFieldDataExistFlag = true; }
#if TARGET_PC
void setRegionBit(u8 region) { mRegion |= region;}
#endif
#if TARGET_PC
/* 0x00 */ BE(Vec) mPos;
@@ -376,12 +386,21 @@ public:
void setArrowNum(u8 i_num) { mArrowNum = i_num; }
u8 getPachinkoNum() const { return mPachinkoNum; }
void setPachinkoNum(u8 i_num) { mPachinkoNum = i_num; }
#if TARGET_PC
u8 getAncientDocumentNum() const { return mAncientDocumentNum; }
void setAncientDocumentNum(u8 i_num) { mAncientDocumentNum = i_num; }
#endif
/* 0x0 */ u8 mArrowNum;
/* 0x1 */ u8 mBombNum[3];
/* 0x4 */ u8 mBottleNum[4];
/* 0x8 */ u8 mPachinkoNum;
#if TARGET_PC
/* 0x9 */ u8 mAncientDocumentNum; // Custom Field for Randomizer
/* 0x9 */ u8 unk5[2];
#else
/* 0x9 */ u8 unk5[3];
#endif
}; // Size: 0xC
class dSv_player_item_max_c {
@@ -413,7 +432,11 @@ public:
u8 getPohNum() const { return mPohNum; }
void addPohNum() {
#if TARGET_PC
if (mPohNum < 0x3D) {
#else
if (mPohNum < 0xFF) {
#endif
mPohNum++;
}
}
@@ -458,6 +481,11 @@ public:
int isLetterReadFlag(int i_no) const;
u8 getGetNumber(int i_no) { return mGetNumber[i_no]; }
void setGetNumber(int i_no, u8 i_value) { mGetNumber[i_no] = i_value; }
#if TARGET_PC
// For rando
void setAllLetterGet() { mLetterGetFlags[0] |= 0xFFFF;}
void setAllLetterRead() { mLetterReadFlags[0] |= 0xFFFF;}
#endif
/* 0x00 */ BE(u32) mLetterGetFlags[2];
/* 0x08 */ BE(u32) mLetterReadFlags[2];
@@ -664,10 +692,14 @@ public:
void onDungeonItemBossKey() { onDungeonItem(BOSS_KEY); }
void offDungeonItemBossKey() { offDungeonItem(BOSS_KEY); }
s32 isDungeonItemBossKey() const { return isDungeonItem(BOSS_KEY); }
#if TARGET_PC
void onStageBossEnemy();
#else
void onStageBossEnemy() {
onDungeonItem(STAGE_BOSS_ENEMY);
onDungeonItem(OOCCOO_NOTE);
}
#endif
void offStageBossEnemy() { offDungeonItem(STAGE_BOSS_ENEMY); }
s32 isStageBossEnemy() const { return isDungeonItem(STAGE_BOSS_ENEMY); }
void onStageLife() { onDungeonItem(STAGE_LIFE); }
@@ -948,6 +980,7 @@ public:
/* 0x8 */ s8 m_no;
};
class dSv_info_c {
public:
void init();
+3
View File
@@ -1292,6 +1292,9 @@ public:
void set(const char*, s8, s16, s8, s8, u8);
void offEnable() { enabled = 0; }
BOOL isEnable() const { return enabled; }
#if TARGET_PC
void setEnable() { enabled |= 0x1; }
#endif
s8 getWipe() const { return wipe; }
u8 getWipeSpeed() const { return wipe_speed; }
dStage_startStage_c* getStartStage() { return this; }
-18
View File
@@ -1,18 +0,0 @@
#pragma once
namespace dusk::helpers::alignment {
/**
* Read data from an address that may not be aligned properly.
* @tparam T Type of data to read.
* @param ptr Address to read from.
* @return The copied value.
*/
template <typename T> requires std::is_trivially_copyable_v<T>
[[nodiscard]] constexpr T read_unaligned(u8 const* ptr) {
T copy;
memcpy(&copy, ptr, sizeof(T));
return copy;
}
}
-48
View File
@@ -1,48 +0,0 @@
#pragma once
#include <limits>
#include <utility>
#include <span>
/**
* Helper functions for performing casts.
*/
namespace dusk::helpers::cast {
/**
* Implementation details of dusk::helpers::cast.
*/
namespace _impl {
[[noreturn]] void overrun_high();
[[noreturn]] void overrun_low();
}
template <typename T>
concept IntCastable = std::is_integral_v<T> && std::is_trivially_copyable_v<T>;
/**
* Helper type that allows easily casting between integer types,
* that safely aborts if an overflow were to occur.
* Usage:
* @code
* size_t foobar = 20;
* int real = bounded_cast(foobar);
* @endcode
*/
template <IntCastable Source>
struct bounded_cast {
Source src;
template <IntCastable Target>
[[nodiscard]] constexpr operator Target() const {
if (std::cmp_greater(src, std::numeric_limits<Target>::max())) [[unlikely]] {
_impl::overrun_high();
}
if (std::cmp_less(src, std::numeric_limits<Target>::min())) [[unlikely]] {
_impl::overrun_low();
}
return static_cast<Target>(src);
}
};
}
-1
View File
@@ -285,7 +285,6 @@ inline void be_swap(Mtx& val) {
}
}
#define LE(T) T
#define BE(T) BE<T>
#define BE_HOST(T) (T.host())
#else
+3
View File
@@ -394,4 +394,7 @@ inline int mDoAud_monsSeStart(u32 i_soundId, const Vec* i_pos, u32 i_actorId, u3
0);
}
#if TARGET_PC
mDoAud_zelAudio_c& mDoAud_getZelAudio();
#endif
#endif /* M_DO_M_DO_AUDIO_H */
+4
View File
@@ -67,6 +67,10 @@ public:
JKRMemArchive* getArchive() const { return mArchive; }
JKRHeap* getHeap() const { return mHeap; }
#if TARGET_PC
s32 getEntryNumber() const { return mEntryNumber; }
#endif
private:
/* 0x14 */ u8 mMountDirection;
@@ -154,6 +154,18 @@ public:
return (J2DTextBoxHBinding)((mFlags >> 2) & 3);
}
#if TARGET_PC
void setVBinding(J2DTextBoxVBinding vBinding) {
mFlags &= 0b1100;
mFlags |= (vBinding & 3);
}
void setHBinding(J2DTextBoxHBinding hBinding) {
mFlags &= 0b0011;
mFlags |= ((hBinding & 3) << 2);
}
#endif
JUtility::TColor getCharColor() { return mCharColor; }
JUtility::TColor getGradColor() { return mGradientColor; }
u16 getStringAllocByte() const { return mStringLength; }
@@ -101,7 +101,7 @@ struct JAISoundStatus_ {
bool isMute() const { return field_0x0.flags.mute; }
bool isPaused() const { return field_0x0.flags.paused; }
void pauseWhenOut() {
field_0x1.flags.mPauseWhenOut = 1;
field_0x1.flags.flag3 = 1;
}
/* 0x0 */ union {
@@ -120,9 +120,9 @@ struct JAISoundStatus_ {
/* 0x1 */ union {
u8 value;
struct {
u8 mComesBack : 1;
u8 flag1 : 1;
u8 flag2 : 1;
u8 mPauseWhenOut : 1;
u8 flag3 : 1;
u8 flag4 : 1;
u8 flag5 : 1;
u8 flag6 : 1;
@@ -309,7 +309,7 @@ public:
bool hasLifeTime() const { return status_.field_0x1.flags.flag2; }
void removeLifeTime_() {
status_.field_0x1.flags.mComesBack = false;
status_.field_0x1.flags.flag1 = false;
status_.field_0x1.flags.flag2 = 0;
}
@@ -346,7 +346,7 @@ public:
void setComesBack(bool param_0) {
JUT_ASSERT(354, status_.state.flags.calcedOnce == 0);
status_.field_0x1.flags.mComesBack = 1;
status_.field_0x1.flags.flag1 = 1;
if (param_0) {
status_.pauseWhenOut();
}
@@ -9,14 +9,14 @@
*/
struct JAISoundParamsProperty {
void init() {
mVolume = 1.0f;
mFxMix = 0.0f;
mPitch = 1.0f;
field_0x0 = 1.0f;
field_0x4 = 0.0f;
field_0x8 = 1.0f;
}
/* 0x00 */ f32 mVolume;
/* 0x04 */ f32 mFxMix;
/* 0x08 */ f32 mPitch;
/* 0x00 */ f32 field_0x0;
/* 0x04 */ f32 field_0x4;
/* 0x08 */ f32 field_0x8;
}; // Size: 0xC
/**
@@ -12,27 +12,21 @@ struct JASBasicWaveBank : public JASWaveBank {
struct TWaveHandle : public JASWaveHandle {
TWaveHandle() { mHeap = NULL; }
virtual intptr_t getWavePtr() const;
virtual const JASWaveInfo* getWaveInfo() const { return &mWaveInfo; }
#if TARGET_PC
/**
* @see JASChannel::mAramBaseAddress
*/
[[nodiscard]] void const* getAramBaseAddress() const override { return nullptr; }
#endif
virtual const JASWaveInfo* getWaveInfo() const { return &field_0x4; }
bool compareHeap(JASHeap* heap) const { return mHeap == heap;}
/* 0x04 */ JASWaveInfo mWaveInfo;
/* 0x04 */ JASWaveInfo field_0x4;
/* 0x28 */ JASHeap* mHeap;
};
struct TGroupWaveInfo {
TGroupWaveInfo() {
waveId = 0xffff;
mOffsetStart = -1;
field_0x0 = 0xffff;
field_0x4 = -1;
}
/* 0x00 */ u16 waveId;
/* 0x04 */ int mOffsetStart;
/* 0x00 */ u16 field_0x0;
/* 0x04 */ int field_0x4;
};
struct TWaveGroup : JASWaveArc {
@@ -50,7 +44,7 @@ struct JASBasicWaveBank : public JASWaveBank {
u32 getWaveCount() const { return mWaveCount; }
};
JASBasicWaveBank(IF_DUSK(u32 bankId));
JASBasicWaveBank();
~JASBasicWaveBank();
TWaveGroup* getWaveGroup(u32);
void setGroupCount(u32, JKRHeap*);
@@ -62,7 +56,7 @@ struct JASBasicWaveBank : public JASWaveBank {
JASWaveArc* getWaveArc(u32 param_0) { return getWaveGroup(param_0); }
u32 getArcCount() const { return mGroupCount; }
/* 0x04 */ OSMutex mWaveTableMutex;
/* 0x04 */ OSMutex field_0x4;
/* 0x1C */ TWaveHandle* mWaveTable;
/* 0x20 */ TWaveGroup* mWaveGroupArray;
/* 0x24 */ u16 mHandleCount;
@@ -8,7 +8,6 @@
#include "JSystem/JAudio2/JASWaveInfo.h"
#include "JSystem/JAudio2/JASDSPInterface.h"
#include <os.h>
#include <memory>
struct JASDSPChannel;
@@ -16,20 +15,6 @@ namespace JASDsp {
struct TChannel;
}
#if TARGET_PC
/**
* An object to manage the lifetime of the sample data pointed to by JASChannel.
*
* JASChannel can (optionally) accept an unique_ptr to an object to this type,
* in which case it will be destroyed when the JASChannel is done.
*
* @see JASChannel::mSampleReference
*/
struct JASSampleDataReference {
virtual ~JASSampleDataReference() = default;
};
#endif
/**
* @ingroup jsystem-jaudio
*
@@ -181,23 +166,6 @@ public:
u32 field_0x104;
};
#if TARGET_PC
/**
* Memory address at which this sound effect should consider ARAM to start.
*
* By changing this, sound effects can effectively be played back from anywhere in memory,
* rather than just the emulated ARAM space.
*
* If nullptr, the regular emulated ARAM is used.
*/
void const* mAramBaseAddress;
/**
* @see JASSampleDataReference
*/
std::unique_ptr<JASSampleDataReference> mSampleReference;
#endif
static DUSK_GAME_DATA OSMessageQueue sBankDisposeMsgQ;
static DUSK_GAME_DATA OSMessage sBankDisposeMsg[16];
static DUSK_GAME_DATA OSMessage sBankDisposeList[16];
@@ -109,9 +109,7 @@ namespace JASDsp {
* Pitch shift via changing playback speed.
*/
/* 0x004 */ u16 mPitch;
#if !TARGET_PC
/* 0x006 */ short _unused1;
#endif
/**
* Set to 1 when playback starts, cleared by DSP later,
@@ -120,27 +118,19 @@ namespace JASDsp {
* (Corroborated by fields JASAramStream checks never being cleared explicitly by CPU.)
*/
/* 0x008 */ u16 mResetFlag;
#if !TARGET_PC
/* 0x00A */ u8 _unused2[0x00C - 0x00A];
#endif
/* 0x00C */ s16 mPauseFlag;
#if !TARGET_PC
/* 0x00E */ short _unused3;
#endif
/* 0x010 */ OutputChannelConfig mOutputChannels[DSP_OUTPUT_CHANNELS];
#if !TARGET_PC
/* 0x040 */ u8 _unused4[0x050 - 0x040];
#endif
/* 0x050 */ u16 mAutoMixerPanDolby; // pan is upper 8 bits, dolby lower 8.
/* 0x052 */ u16 mAutoMixerFxMix;
/* 0x054 */ u16 mAutoMixerInitVolume;
/* 0x056 */ u16 mAutoMixerVolume;
/* 0x058 */ u16 mAutoMixerBeenSet;
#if !TARGET_PC
/* 0x05A */ u8 _unused5[0x060 - 0x05A];
/* 0x060 */ short field_0x060; // Only cleared to zero, presumed used by DSP.
/* 0x062 */ u8 _unused6[0x064 - 0x062];
#endif
/**
* Samples per ADPCM frame for ADPCM audio. Seems just set to 1 for PCM formats.
@@ -149,9 +139,7 @@ namespace JASDsp {
/* 0x064 */ u16 mSamplesPerBlock;
/* 0x066 */ short field_0x066; // Only cleared to zero, presumed used by DSP.
/* 0x068 */ u32 mSamplePosition; // Only ever initialized by code, name is guess.
#if !TARGET_PC
/* 0x06C */ u8 _unused7[0x070 - 0x06C];
#endif
/**
* Current audio read position in ARAM. Updated by DSP.
@@ -163,13 +151,11 @@ namespace JASDsp {
* Gets written by DSP, but also CPU.
*/
/* 0x074 */ u32 mSamplesLeft; // Never directly cleared to zero. Seems sus. Cleared by DSP?
#if !TARGET_PC
/* 0x078 */ short field_0x078[4]; // Only cleared to zero, presumed used by DSP.
/* 0x080 */ short field_0x080[20]; // Only cleared to zero, presumed used by DSP.
/* 0x0A8 */ short field_0x0a8[4]; // Only cleared to zero, presumed used by DSP.
/* 0x0B0 */ u16 field_0x0b0[16]; // Only cleared to zero, presumed used by DSP.
/* 0x0D0 */ u8 _unused8[0x100 - 0x0D0];
#endif
/* 0x100 */ u16 mBytesPerBlock;
/* 0x102 */ u16 mLoopFlag;
@@ -190,26 +176,9 @@ namespace JASDsp {
/* 0x118 */ u32 mWaveAramAddress;
/* 0x11C */ int mSampleCount;
/* 0x120 */ s16 fir_filter_params[8];
#if !TARGET_PC
/* 0x130 */ u8 _unused9[0x148 - 0x130];
#endif
/* 0x148 */ s16 iir_filter_params[8];
#if !TARGET_PC
/* 0x158 */ u8 _unused10[0x180 - 0x158];
#endif
#if TARGET_PC
/**
* Memory address at which this sound effect should consider ARAM to start.
* This means fields like mWaveAramAddress will be relative to this pointer instead.
*
* By changing this, sound effects can effectively be played back from anywhere in memory,
* rather than just the emulated ARAM space.
*
* If nullptr, the regular emulated ARAM is used.
*/
void const* mAramBaseAddress;
#endif
};
void boot(void (*)(void*));
@@ -10,18 +10,12 @@ struct JASSimpleWaveBank : JASWaveBank, JASWaveArc {
intptr_t getWavePtr() const;
TWaveHandle();
const JASWaveInfo* getWaveInfo() const;
#if TARGET_PC
/**
* @see JASChannel::mAramBaseAddress
*/
[[nodiscard]] void const* getAramBaseAddress() const override { return nullptr; }
#endif
/* 0x04 */ JASWaveInfo mWaveInfo;
/* 0x28 */ JASHeap* mHeap;
};
JASSimpleWaveBank(IF_DUSK(u32 bankId));
JASSimpleWaveBank();
~JASSimpleWaveBank();
void setWaveTableSize(u32, JKRHeap*);
JASWaveHandle* getWaveHandle(u32) const;
@@ -26,9 +26,7 @@ public:
};
struct TCtrlWave {
// Wave ID in lower half.
// Upper bits appear to be group ID, which is unused by the game code.
/* 0x0 */ BE(u32) mWaveAndGroupId;
/* 0x0 */ BE(u32) _00;
};
struct TWave {
@@ -59,14 +57,13 @@ public:
};
struct TCtrl {
/* 0x0 */ BE(u32) mMagic; // 'C-DF'.
/* 0x0 */ u8 _00[4];
/* 0x4 */ BE(u32) mWaveCount;
/* 0x8 */ TOffset<TCtrlWave> mCtrlWaveOffsets[0];
};
struct TCtrlScene {
/* 0x0 */ BE(u32) mMagic; // 'SCNE'
/* 0x4 */ u8 _00[0x8];
/* 0x0 */ u8 _00[0xC];
/* 0xC */ TOffset<TCtrl> mCtrlOffset;
};
@@ -66,7 +66,7 @@ struct JASWaveArc : JASDisposer {
};
/* 0x04 */ mutable JASHeap mHeap;
/* 0x48 */ u32 mCurrentlyLoaded;
/* 0x48 */ u32 _48;
/* 0x4C */ volatile s32 mStatus;
/* 0x50 */ int mEntryNum;
/* 0x54 */ u32 mFileLength;
@@ -2,11 +2,6 @@
#define JASWAVEINFO_H
#include <types.h>
#include <memory>
#if TARGET_PC
struct JASSampleDataReference;
#endif
struct JASWaveArc;
@@ -22,7 +17,7 @@ struct JASWaveArc;
struct JASWaveInfo {
JASWaveInfo() {
mBaseKey = 0x3c;
mpLoaded = &one;
field_0x20 = &one;
}
/* 0x00 */ u8 mWaveFormat;
@@ -36,7 +31,7 @@ struct JASWaveInfo {
/* 0x18 */ int mSampleCount;
/* 0x1C */ s16 mpLast;
/* 0x1E */ s16 mpPenult;
/* 0x20 */ const u32* mpLoaded;
/* 0x20 */ const u32* field_0x20;
static DUSK_GAME_DATA u32 one;
};
@@ -50,17 +45,6 @@ public:
virtual ~JASWaveHandle() {}
virtual const JASWaveInfo* getWaveInfo() const = 0;
virtual intptr_t getWavePtr() const = 0;
#if TARGET_PC
/**
* @see JASChannel::mAramBaseAddress
*/
[[nodiscard]] virtual void const* getAramBaseAddress() const = 0;
/**
* Create a @ref JASSampleDataReference to keep the sample data for this wave alive.
*/
[[nodiscard]] virtual std::unique_ptr<JASSampleDataReference> getSampleReference() const { return nullptr; }
#endif
};
/**
@@ -69,12 +53,6 @@ public:
*/
class JASWaveBank {
public:
#if TARGET_PC
const u32 bankId;
JASWaveBank(u32 bankId) : bankId(bankId) { }
#endif
virtual ~JASWaveBank() {}
virtual JASWaveHandle* getWaveHandle(u32) const = 0;
virtual JASWaveArc* getWaveArc(u32) = 0;
@@ -10,7 +10,7 @@
*/
struct JAUAudibleParam {
f32 getDopplerPower() const {
return field_0x0.bytes.mDopplerPower * (1.0f / 15.0f);
return field_0x0.bytes.b0_0 * (1.0f / 15.0f);
}
union {
@@ -19,18 +19,14 @@ struct JAUAudibleParam {
BE(u16) f1;
} half;
struct {
u8 mDopplerPower : 4;
u8 mCalculatePriority : 1;
u8 mCalcDistanceVolume : 1;
u8 mCalcFxMix : 1;
u8 mCullAtMaxDistance : 1;
u8 mCalcPan : 1;
u8 mCalcDolby : 1;
/**
* Most bits in this field are unused, 8 indicates clamping of volume
* to ensure it doesn't go below 0.2 in mixChannelOut()
*/
u8 mClampMinVolume : 6;
u8 b0_0 : 4;
u8 b0_4 : 1;
u8 b0_5 : 1;
u8 b0_6 : 1;
u8 b0_7 : 1;
u8 b1_0 : 1;
u8 b1_1 : 1;
u8 b1_2_7 : 6;
u8 b2;
u8 b3;
} bytes;
@@ -5,162 +5,16 @@
#include "JSystem/JAudio2/JASGadget.h"
#include "helpers/endian.h"
// Constants for TypeIDs of JAUSoundTable entries.
/**
* Used as a test to see if the type ID is valid. All other type IDs contain this bit.
*/
#define SOUND_TYPEID_VALID 0x40
/**
* Sound is a sound effect.
*/
#define SOUND_TYPEID_SOUND_EFFECT 0x51
/**
* Sound is a music sequence.
*/
#define SOUND_TYPEID_SEQUENCE 0x60
/**
* Sound is a streamed music file.
*/
#define SOUND_TYPEID_STREAM 0x70
/**
* Sound is a streamed music file. Unsure of difference from SOUND_TYPEID_STREAM
*/
#define SOUND_TYPEID_STREAM_ALT 0x71
//
// Values for mSwBit on sound effect items.
//
/**
* Sound is always calculated as max priority (0).
*/
#define SOUND_SW_ALWAYS_MAX_PRIORITY 0x0000'0001
/**
* Don't calculate volume by distance.
*/
#define SOUND_SW_IGNORE_DISTANCE_VOL 0x0000'0002
/**
* Don't calculate FX mix (reverb) by distance.
*/
#define SOUND_SW_IGNORE_FX_MIX 0x0000'0004
/**
* Offset to shift to access @see SOUND_SW_RANDOM_PITCH_MASK
*/
#define SOUND_SW_RANDOM_PITCH_OFFSET 4
/**
* 4-bit value (0-15) to control the power of pitch randomization on sound playback.
* Code acts different for values above 8, not sure what the exact implication is.
*/
#define SOUND_SW_RANDOM_PITCH_MASK 0x0000'00F0
/**
* Offset to shift to access @see SOUND_SW_DOPPLER_POWER_MASK
*/
#define SOUND_SW_DOPPLER_POWER_OFFSET 8
/**
* 4-bit value (0-15) to scale the power of the Doppler effect for this sound.
*/
#define SOUND_SW_DOPPLER_POWER_MASK 0x0000'0F00
/**
* Don't calculate panning (left/right) values for this sound.
*/
#define SOUND_SW_IGNORE_PAN 0x0000'1000
/**
* Don't calculate Dolby (behind/front) values for this sound.
*/
#define SOUND_SW_IGNORE_DOLBY 0x0000'2000
/**
* 3-bit mask used to select a volume distance/falloff class for this sound.
*/
#define SOUND_SW_VOL_DIST_BIT_MASK 0x0007'0000
/**
* Limit minimum volume of this sound (after distance falloff) to 0.2.
*/
#define SOUND_SW_CLAMP_MIN_VOLUME 0x0008'0000
/**
* 3-bit mask used to select a *different* volume distance/falloff class for this sound.
* @see SOUND_SW_VOL_DIST_BIT_MASK must be zero for this to work.
*/
#define SOUND_SW_VOL_DIST_BIT_2_MASK 0x0070'0000
/**
* Mark sound as "far away" or "culled" when at max distance (selected by distance class).
* This affects a bunch of stuff like culling, automatic stopping, priorities, etc.
*/
#define SOUND_SW_CULL_AT_MAX_DISTANCE 0x0080'0000
/**
* Not sure what this does.
* Something causing volume/pan/dolby adjustment in Z2Audible::setOuterParams?
*/
#define SOUND_SW_VOL_SOMETHING_MASK 0x0F00'0000
/**
* Offset to shift to access @see SOUND_SW_RANDOM_VOLUME_MASK
*/
#define SOUND_SW_RANDOM_VOLUME_OFFSET 28
/**
* 4-bit value (0-15) to control the power of volume randomization on sound playback.
*/
#define SOUND_SW_RANDOM_VOLUME_MASK 0xF000'0000
#define SOUND_VOL_DIST_BIT_MASK_SHIFTED (SOUND_SW_VOL_DIST_BIT_MASK >> 16)
#define SOUND_VOL_DIST_BIT_2_MASK_SHIFTED (SOUND_SW_VOL_DIST_BIT_2_MASK >> 16)
#define SOUND_VOL_SOMETHING_MASK_SHIFTED (SOUND_SW_VOL_SOMETHING_MASK >> 16)
/**
* @ingroup jsystem-jaudio
* A single entry in the sound table.
* Fields are interpreted differently depending on the type ID of the entry,
* which is not stored in this struct.
*
*/
struct JAUSoundTableItem {
u8 mPriority;
u8 mVolume;
union {
/**
* For music sequences: the resource ID of the sequence.
*/
BE(u16) mResourceId;
/**
* For streamed music: bitpacked channel configuration.
*/
BE(u16) mStreamPanParameters;
};
union {
/**
* For sound effects: bitpacked field controlling a *bunch* of audio parameters.
*/
BE(u32) mSwBit;
/**
* For streamed music: offset (relative to start of BST)
* to null-terminated string containing music file path.
*/
BE(u32) mStreamFilePath;
};
/**
* For sound effects: pitch multiplier.
*/
BE(f32) mPitch;
u8 field_0x1;
BE(u16) mResourceId;
BE(u32) field_0x4;
BE(f32) field_0x8;
};
/**
@@ -170,25 +24,23 @@ struct JAUSoundTableItem {
template<typename Root, typename Section, typename Group, typename Typename_0>
struct JAUSoundTable_ {
JAUSoundTable_() {
mData = NULL;
mRoot = 0;
field_0x0 = NULL;
field_0x4 = 0;
}
void reset() {
mData = NULL;
mRoot = NULL;
field_0x0 = NULL;
field_0x4 = NULL;
}
void init(const void* dataStart) {
mData = dataStart;
void init(const void* param_0) {
field_0x0 = param_0;
// magic number is not in debug rom. I'm not sure what this comparison is (maybe some sort of '' number?)
// I also do not know how it is different between JAUSoundTable and JAUSoundNameTable
// Future person here: This is checking for either "BST " or "BSTN", with the second two letters in Root::magicNumber().
// Idk why the operations here are all weird but I can't use objdiff right now.
if (*(BE(u32)*)mData + 0xbdad0000 != Root::magicNumber()) {
mData = NULL;
if (*(BE(u32)*)field_0x0 + 0xbdad0000 != Root::magicNumber()) {
field_0x0 = NULL;
} else {
mRoot = (Root*)((u8*)mData + *((BE(u32)*)mData + 3));
field_0x4 = (Root*)((u8*)field_0x0 + *((BE(u32)*)field_0x0 + 3));
}
}
@@ -196,34 +48,34 @@ struct JAUSoundTable_ {
if (index < 0) {
return NULL;
}
if ((u32)index >= mRoot->mSectionNumber) {
if ((u32)index >= field_0x4->mSectionNumber) {
return NULL;
}
u32 offset = mRoot->mSectionOffsets[index];
u32 offset = field_0x4->mSectionOffsets[index];
if (offset == 0) {
return NULL;
}
return (Section*)((u8*)mData + offset);
return (Section*)((u8*)field_0x0 + offset);
}
Group* getGroup(Section* section, int index) const {
Group* getGroup(Section* param_1, int index) const {
int iVar1;
if (index < 0) {
return NULL;
}
if ((u32)index >= section->mNumGroups) {
if ((u32)index >= param_1->mNumGroups) {
return NULL;
}
u32 offset = section->getGroupOffset(index);
u32 offset = param_1->getGroupOffset(index);
if (offset == 0) {
return NULL;
}
return (Group*)((u8*)mData + offset);
return (Group*)((u8*)field_0x0 + offset);
}
const void* mData;
Root* mRoot;
const void* field_0x0;
Root* field_0x4;
};
/**
@@ -231,7 +83,7 @@ struct JAUSoundTable_ {
*
*/
struct JAUSoundTableRoot {
static inline u32 magicNumber() { return 'T '; } // Second half of "BST "
static inline u32 magicNumber() { return 0x5420; }
BE(u32) mSectionNumber;
BE(u32) mSectionOffsets[0];
};
@@ -282,7 +134,7 @@ struct JAUSoundTableGroup {
BE(u32) mNumItems;
BE(u32) field_0x4;
u8 mTypeIds[0]; // TODO: Should probably be BE(u32), but I can't objdiff rn.
u8 mTypeIds[0];
};
/**
@@ -290,7 +142,7 @@ struct JAUSoundTableGroup {
*
*/
struct JAUSoundTable : public JASGlobalInstance<JAUSoundTable> {
JAUSoundTable(bool setInstance) : JASGlobalInstance<JAUSoundTable>(setInstance) {
JAUSoundTable(bool param_0) : JASGlobalInstance<JAUSoundTable>(param_0) {
}
~JAUSoundTable() {}
@@ -305,11 +157,11 @@ struct JAUSoundTable : public JASGlobalInstance<JAUSoundTable> {
if (offset == 0) {
return NULL;
}
return (JAUSoundTableItem*)((u8*)field_0x0.mData + offset);
return (JAUSoundTableItem*)((u8*)field_0x0.field_0x0 + offset);
}
const void* getResource() const { return field_0x0.mData; }
bool isValid() const { return field_0x0.mData != NULL; }
const void* getResource() const { return field_0x0.field_0x0; }
bool isValid() const { return field_0x0.field_0x0 != NULL; }
JAUSoundTable_<JAUSoundTableRoot,JAUSoundTableSection,JAUSoundTableGroup,void> field_0x0;
};
@@ -319,7 +171,7 @@ struct JAUSoundTable : public JASGlobalInstance<JAUSoundTable> {
*
*/
struct JAUSoundNameTableRoot {
static inline u32 magicNumber() { return 'TN'; } // Second half of "BSTN"
static inline u32 magicNumber() { return 0x544e; }
BE(u32) mSectionNumber;
BE(u32) mSectionOffsets[0];
};
+3 -3
View File
@@ -70,7 +70,7 @@ void JAISe::JAISeCategoryMgr_mixOut_(bool param_0, const JASSoundParams& params,
if (inner_.field_0x26c) {
switch (inner_.track.getStatus()) {
case JASTrack::STATUS_STOPPED:
if (status_.field_0x1.flags.mComesBack) {
if (status_.field_0x1.flags.flag1) {
startTrack_(params);
} else {
stop_JAISound_();
@@ -84,8 +84,8 @@ void JAISe::JAISeCategoryMgr_mixOut_(bool param_0, const JASSoundParams& params,
startTrack_(params);
}
}
} else if (status_.field_0x1.flags.mComesBack) {
if (status_.field_0x1.flags.mPauseWhenOut) {
} else if (status_.field_0x1.flags.flag1) {
if (status_.field_0x1.flags.flag3) {
inner_.track.pause(true);
} else {
stopTrack_();
+11 -11
View File
@@ -167,7 +167,7 @@ JAISeMgr::JAISeMgr(bool setInstance) : JASGlobalInstance<JAISeMgr>(setInstance)
}
bool JAISeMgr::isUsingSeqData(const JAISeqDataRegion& seqDataRegion) {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
if (mCategoryMgrs[i].JAISeCategoryMgr::isUsingSeqData(seqDataRegion)) {
return true;
}
@@ -177,7 +177,7 @@ bool JAISeMgr::isUsingSeqData(const JAISeqDataRegion& seqDataRegion) {
int JAISeMgr::releaseSeqData(const JAISeqDataRegion& seqDataRegion) {
bool r30 = 0;
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
switch (mCategoryMgrs[i].JAISeCategoryMgr::releaseSeqData(seqDataRegion)) {
case 0:
return 0;
@@ -191,14 +191,14 @@ int JAISeMgr::releaseSeqData(const JAISeqDataRegion& seqDataRegion) {
}
void JAISeMgr::setCategoryArrangement(const JAISeCategoryArrangement& arrangement) {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].setMaxActiveSe(arrangement.mItems[i].mMaxActiveSe);
mCategoryMgrs[i].setMaxInactiveSe(arrangement.mItems[i].mMaxInactiveSe);
}
}
void JAISeMgr::getCategoryArrangement(JAISeCategoryArrangement* arrangement) {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
int active = mCategoryMgrs[i].getMaxActiveSe();
JUT_ASSERT(299, active <= 255);
arrangement->mItems[i].mMaxActiveSe = active;
@@ -209,19 +209,19 @@ void JAISeMgr::getCategoryArrangement(JAISeCategoryArrangement* arrangement) {
}
void JAISeMgr::stop() {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].stop();
}
}
void JAISeMgr::stopSoundID(JAISoundID id) {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].stopSoundID(id);
}
}
void JAISeMgr::initParams() {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].getParams()->init();
}
}
@@ -270,16 +270,16 @@ JAISe* JAISeMgr::newSe_(int category, u32 priority) {
void JAISeMgr::calc() {
mParams.calc();
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].JAISeMgr_calc_();
}
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].JAISeMgr_freeDeadSe_();
}
}
void JAISeMgr::mixOut() {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].JAISeMgr_mixOut_(mParams, mSoundActivity);
}
}
@@ -324,7 +324,7 @@ bool JAISeMgr::startSound(JAISoundID id, JAISoundHandle* handle, const JGeometry
int JAISeMgr::getNumActiveSe() const {
int num = 0;
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
num += mCategoryMgrs[i].getNumSe();
}
return num;
+4 -4
View File
@@ -54,9 +54,9 @@ s32 JAISoundStatus_::unlockIfLocked() {
}
void JAISoundParams::mixOutAll(const JASSoundParams& inParams, JASSoundParams* outParams, f32 param_2) {
outParams->mVolume = move_.params_.mVolume * (inParams.mVolume * property_.mVolume) * param_2;
outParams->mFxMix = move_.params_.mFxMix + (inParams.mFxMix + property_.mFxMix);
outParams->mPitch = move_.params_.mPitch * (inParams.mPitch * property_.mPitch);
outParams->mVolume = move_.params_.mVolume * (inParams.mVolume * property_.field_0x0) * param_2;
outParams->mFxMix = move_.params_.mFxMix + (inParams.mFxMix + property_.field_0x4);
outParams->mPitch = move_.params_.mPitch * (inParams.mPitch * property_.field_0x8);
outParams->mPan = (inParams.mPan + move_.params_.mPan) - 0.5f;
outParams->mDolby = inParams.mDolby + move_.params_.mDolby;
}
@@ -181,7 +181,7 @@ bool JAISound::calc_JAISound_() {
}
if (audience_ != NULL && audible_ != NULL) {
if ((priority_ = audience_->calcPriority(audible_)) == 0xFFFFFFFF && status_.field_0x1.flags.mComesBack == 0) {
if ((priority_ = audience_->calcPriority(audible_)) == 0xFFFFFFFF && status_.field_0x1.flags.flag1 == 0) {
stop_JAISound_();
}
} else {
+1 -1
View File
@@ -713,7 +713,7 @@ void JASAramStream::channelStart() {
wave_info.mpPenult = 0;
// probably a fake match, this should be set in the JASWaveInfo constructor
static u32 const one = 1;
wave_info.mpLoaded = &one;
wave_info.field_0x20 = &one;
JASChannel* jc = JKR_NEW JASChannel(channelCallback, this);
JUT_ASSERT(963, jc);
jc->setPriority(0x7f7f);
+1 -20
View File
@@ -1,15 +1,11 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JAudio2/JASBank.h"
#include "dusk/mods/svc/audio_res/audio_res.hpp"
#include "JSystem/JAudio2/JASAiCtrl.h"
#include "JSystem/JAudio2/JASBasicInst.h"
#include "JSystem/JAudio2/JASBasicWaveBank.h"
#include "JSystem/JAudio2/JASChannel.h"
using namespace dusk::mods::svc::audio_res;
// NONMATCHING JASPoolAllocObject_MultiThreaded<_> locations
JASChannel* JASBank::noteOn(JASBank const* param_0, int param_1, u8 param_2, u8 param_3, u16 param_4,
void (*param_5)(u32, JASChannel*, JASDsp::TChannel*, void*),
@@ -32,23 +28,12 @@ JASChannel* JASBank::noteOn(JASBank const* param_0, int param_1, u8 param_2, u8
if (!waveHandle) {
return NULL;
}
#if TARGET_PC
auto const key = AudioWaveKey(static_cast<AudioWaveBank>(waveBank->bankId), stack_60.field_0x1a);
std::lock_guard lock(s_replacements_mutex);
auto const found_replacement = s_replacements.find(key);
if (found_replacement != s_replacements.end()) {
waveHandle = &found_replacement->second;
}
auto const aramBase = waveHandle->getAramBaseAddress();
#endif
const JASWaveInfo* waveInfo = waveHandle->getWaveInfo();
if (!waveInfo) {
return NULL;
}
intptr_t wavePtr = waveHandle->getWavePtr();
if (!wavePtr IF_DUSK(&& !aramBase)) {
if (!wavePtr) {
return NULL;
}
@@ -59,10 +44,6 @@ JASChannel* JASBank::noteOn(JASBank const* param_0, int param_1, u8 param_2, u8
channel->setPriority(param_4);
channel->field_0xdc.mWaveInfo = *waveInfo;
channel->mWaveAramAddress = wavePtr;
#if TARGET_PC
channel->mAramBaseAddress = aramBase;
channel->mSampleReference = waveHandle->getSampleReference();
#endif
channel->field_0xdc.mChannelType = stack_60.field_0x1c;
channel->setBankDisposeID(param_0);
channel->setInitPitch(stack_60.mPitch * (waveInfo->mSampleRate / JASDriver::getDacRate()));
+16 -16
View File
@@ -6,12 +6,12 @@
#include "JSystem/JUtility/JUTAssert.h"
#include <stdint.h>
JASBasicWaveBank::JASBasicWaveBank(IF_DUSK(u32 bankId)) IF_DUSK(: JASWaveBank(bankId)) {
JASBasicWaveBank::JASBasicWaveBank() {
mWaveTable = NULL;
mWaveGroupArray = NULL;
mHandleCount = 0;
mGroupCount = 0;
OSInitMutex(&mWaveTableMutex);
OSInitMutex(&field_0x4);
}
JASBasicWaveBank::~JASBasicWaveBank() {
@@ -44,13 +44,13 @@ void JASBasicWaveBank::setWaveTableSize(u32 param_0, JKRHeap* param_1) {
}
void JASBasicWaveBank::incWaveTable(JASBasicWaveBank::TWaveGroup const* param_0) {
JASMutexLock lock(&mWaveTableMutex);
JASMutexLock lock(&field_0x4);
for (u32 i = 0; i < param_0->getWaveCount(); i++) {
TWaveHandle* handle = mWaveTable + param_0->getWaveID(i);
if (!handle->mHeap) {
handle->mHeap = &param_0->mHeap;
handle->mWaveInfo.mpLoaded = &param_0->mCurrentlyLoaded;
handle->mWaveInfo.mOffsetStart = param_0->mCtrlWaveArray[i].mOffsetStart;
handle->field_0x4.field_0x20 = &param_0->_48;
handle->field_0x4.mOffsetStart = param_0->mCtrlWaveArray[i].field_0x4;
}
}
}
@@ -58,13 +58,13 @@ void JASBasicWaveBank::incWaveTable(JASBasicWaveBank::TWaveGroup const* param_0)
DUSK_GAME_DATA u32 JASBasicWaveBank::mNoLoad;
void JASBasicWaveBank::decWaveTable(JASBasicWaveBank::TWaveGroup const* param_0) {
JASMutexLock lock(&mWaveTableMutex);
JASMutexLock lock(&field_0x4);
for (u32 i = 0; i < param_0->getWaveCount(); i++) {
TWaveHandle* handle = mWaveTable + param_0->getWaveID(i);
if (handle->mHeap == &param_0->mHeap) {
handle->mHeap = NULL;
handle->mWaveInfo.mpLoaded = &mNoLoad;
handle->mWaveInfo.mOffsetStart = -1;
handle->field_0x4.field_0x20 = &mNoLoad;
handle->field_0x4.mOffsetStart = -1;
}
}
}
@@ -80,15 +80,15 @@ JASWaveHandle* JASBasicWaveBank::getWaveHandle(u32 param_0) const {
}
void JASBasicWaveBank::setWaveInfo(JASBasicWaveBank::TWaveGroup* wgrp, int index,
u16 waveId, JASWaveInfo const& param_3) {
u16 param_2, JASWaveInfo const& param_3) {
JUT_ASSERT(204, wgrp);
JUT_ASSERT(205, index < wgrp->mWaveCount);
JUT_ASSERT(206, index >= 0);
mWaveTable[waveId].mWaveInfo = param_3;
mWaveTable[waveId].mWaveInfo.mpLoaded = &mNoLoad;
mWaveTable[waveId].mWaveInfo.mOffsetStart = -1;
wgrp->mCtrlWaveArray[index].waveId = waveId;
wgrp->mCtrlWaveArray[index].mOffsetStart = param_3.mOffsetStart;
mWaveTable[param_2].field_0x4 = param_3;
mWaveTable[param_2].field_0x4.field_0x20 = &mNoLoad;
mWaveTable[param_2].field_0x4.mOffsetStart = -1;
wgrp->mCtrlWaveArray[index].field_0x0 = param_2;
wgrp->mCtrlWaveArray[index].field_0x4 = param_3.mOffsetStart;
}
JASBasicWaveBank::TWaveGroup::TWaveGroup() {
@@ -122,7 +122,7 @@ void JASBasicWaveBank::TWaveGroup::onEraseDone() {
u32 JASBasicWaveBank::TWaveGroup::getWaveID(int index) const {
JUT_ASSERT(298, index < mWaveCount);
JUT_ASSERT(299, index >= 0);
return mCtrlWaveArray[index].waveId;
return mCtrlWaveArray[index].field_0x0;
}
intptr_t JASBasicWaveBank::TWaveHandle::getWavePtr() const {
@@ -131,5 +131,5 @@ intptr_t JASBasicWaveBank::TWaveHandle::getWavePtr() const {
if (base == 0) {
return 0;
}
return (intptr_t)base + mWaveInfo.mOffsetStart;
return (intptr_t)base + field_0x4.mOffsetStart;
}
+2 -8
View File
@@ -26,9 +26,6 @@ JASChannel::JASChannel(Callback i_callback, void* i_callbackData) :
mCallback(i_callback),
mCallbackData(i_callbackData),
mUpdateTimer(0),
#if TARGET_PC
mAramBaseAddress(nullptr),
#endif
mBankDisposeID(NULL),
mKey(0),
mVelocity(0x7f),
@@ -240,7 +237,7 @@ s32 JASChannel::initialUpdateDSPChannel(JASDsp::TChannel* i_channel) {
mCallback(CB_START, this, i_channel, mCallbackData);
}
if (field_0xdc.mWaveInfo.mpLoaded[0] == 0) {
if (field_0xdc.mWaveInfo.field_0x20[0] == 0) {
JUT_WARN_DEVICE(346, 2, "%s", "Lost wave data while playing");
mDspCh->free();
mDspCh = NULL;
@@ -259,9 +256,6 @@ s32 JASChannel::initialUpdateDSPChannel(JASDsp::TChannel* i_channel) {
switch (field_0xdc.mChannelType) {
case 0:
i_channel->setWaveInfo(field_0xdc.mWaveInfo, mWaveAramAddress, mSkipSamples);
#if TARGET_PC
i_channel->mAramBaseAddress = mAramBaseAddress;
#endif
break;
case 2:
i_channel->setOscInfo(mOscillatorSomething);
@@ -321,7 +315,7 @@ s32 JASChannel::updateDSPChannel(JASDsp::TChannel* i_channel) {
mCallback(CB_PLAY, this, i_channel, mCallbackData);
}
if (field_0xdc.mWaveInfo.mpLoaded[0] == 0) {
if (field_0xdc.mWaveInfo.field_0x20[0] == 0) {
JUT_WARN_DEVICE(456, 2, "%s","Lost wave data while playing");
mDspCh->free();
mDspCh = NULL;
@@ -523,12 +523,9 @@ void JASDsp::TChannel::init() {
void JASDsp::TChannel::playStart() {
JUT_ASSERT(508, dspMutex);
field_0x10c = 0;
#if !TARGET_PC
field_0x060 = 0;
#endif
mResetFlag = 1;
field_0x066 = 0;
#if !TARGET_PC
int i;
for (i = 0; i < 4; i++) {
field_0x078[i] = 0;
@@ -537,7 +534,6 @@ void JASDsp::TChannel::playStart() {
for (i = 0; i < 20; i++) {
field_0x080[i] = 0;
}
#endif
mIsActive = 1;
}
@@ -605,11 +601,9 @@ void JASDsp::TChannel::setWaveInfo(JASWaveInfo const& waveInfo, u32 aramAddress,
break;
}
}
#if !TARGET_PC
for (i = 0; i < 16; i++) {
field_0x0b0[i] = 0;
}
#endif
}
}
@@ -3,7 +3,7 @@
#include "JSystem/JAudio2/JASSimpleWaveBank.h"
#include <stdint.h>
JASSimpleWaveBank::JASSimpleWaveBank(IF_DUSK(u32 bankId)) IF_DUSK(: JASWaveBank(bankId)) {
JASSimpleWaveBank::JASSimpleWaveBank() {
mWaveTable = NULL;
mWaveTableSize = 0;
}
@@ -28,7 +28,7 @@ JASWaveHandle* JASSimpleWaveBank::getWaveHandle(u32 no) const {
void JASSimpleWaveBank::setWaveInfo(u32 no, JASWaveInfo const& waveInfo) {
mWaveTable[no].mWaveInfo = waveInfo;
mWaveTable[no].mWaveInfo.mpLoaded = &mCurrentlyLoaded;
mWaveTable[no].mWaveInfo.field_0x20 = &_48;
mWaveTable[no].mHeap = &mHeap;
}
+6 -6
View File
@@ -30,7 +30,7 @@ JASBasicWaveBank* JASWSParser::createBasicWaveBank(void const* stream, JKRHeap*
u32 free_size = heap->getFreeSize();
THeader* header = (THeader*)stream;
JASBasicWaveBank* wave_bank = JKR_NEW_ARGS (heap, 0) JASBasicWaveBank IF_DUSK((header->mId));
JASBasicWaveBank* wave_bank = JKR_NEW_ARGS (heap, 0) JASBasicWaveBank;
if (wave_bank == NULL) {
return NULL;
}
@@ -60,7 +60,7 @@ JASBasicWaveBank* JASWSParser::createBasicWaveBank(void const* stream, JKRHeap*
wave_info.mpLast = wave->mpLast;
wave_info.mpPenult = wave->mpPenult;
TCtrlWave* ctrl_wave = ctrl->mCtrlWaveOffsets[j].ptr(header);
u16 local_74 = JSULoHalf(ctrl_wave->mWaveAndGroupId);
u16 local_74 = JSULoHalf(ctrl_wave->_00);
wave_bank->setWaveInfo(wave_group, j, local_74, wave_info);
}
wave_group->setFileName(archive->mFileName);
@@ -82,7 +82,7 @@ JASSimpleWaveBank* JASWSParser::createSimpleWaveBank(void const* stream, JKRHeap
return NULL;
}
JASSimpleWaveBank* wave_bank = JKR_NEW_ARGS (heap, 0) JASSimpleWaveBank IF_DUSK((header->mId));
JASSimpleWaveBank* wave_bank = JKR_NEW_ARGS (heap, 0) JASSimpleWaveBank;
if (wave_bank == NULL) {
return NULL;
}
@@ -94,7 +94,7 @@ JASSimpleWaveBank* JASWSParser::createSimpleWaveBank(void const* stream, JKRHeap
TWaveArchive* archive = archiveBank->mArchiveOffsets[0].ptr(header);
for (int i = 0; i < ctrl->mWaveCount; i++) {
TCtrlWave* ctrlWave = ctrl->mCtrlWaveOffsets[i].ptr(header);
u32 tmp = JSULoHalf(ctrlWave->mWaveAndGroupId);
u32 tmp = JSULoHalf(ctrlWave->_00);
if (max < tmp) {
max = tmp;
}
@@ -116,8 +116,8 @@ JASSimpleWaveBank* JASWSParser::createSimpleWaveBank(void const* stream, JKRHeap
wave_info.mpLast = wave->mpLast;
wave_info.mpPenult = wave->mpPenult;
TCtrlWave* ctrl_wave = ctrl->mCtrlWaveOffsets[i].ptr(header);
u32 waveId = JSULoHalf(ctrl_wave->mWaveAndGroupId);
wave_bank->setWaveInfo(waveId, wave_info);
u32 tmp = JSULoHalf(ctrl_wave->_00);
wave_bank->setWaveInfo(tmp, wave_info);
}
wave_bank->setFileName(archive->mFileName);
@@ -38,7 +38,7 @@ char* JASWaveArcLoader::getCurrentDir() {
}
JASWaveArc::JASWaveArc() : mHeap(this) {
mCurrentlyLoaded = 0;
_48 = 0;
mStatus = 0;
mEntryNum = -1;
mFileLength = 0;
@@ -57,7 +57,7 @@ bool JASWaveArc::loadSetup(u32 param_0) {
if (mStatus != 1) {
return false;
}
mCurrentlyLoaded = 1;
_48 = 1;
mStatus = 2;
return true;
}
@@ -71,7 +71,7 @@ bool JASWaveArc::eraseSetup() {
mStatus = 0;
return false;
}
mCurrentlyLoaded = 0;
_48 = 0;
mStatus = 0;
return true;
}
@@ -91,7 +91,7 @@ void JASWaveArc::loadToAramCallback(void* this_) {
bool JASWaveArc::sendLoadCmd() {
JASMutexLock mutexLock(&mMutex);
mCurrentlyLoaded = 0;
_48 = 0;
mStatus = 1;
loadToAramCallbackParams commandInfo;
commandInfo.mWavArc = this;
+25
View File
@@ -7,6 +7,11 @@
#include "JSystem/JMessage/control.h"
#if TARGET_PC
#include "dusk/randomizer/game/custom_flow_ids.hpp"
#include "dusk/randomizer/game/messages.hpp"
#endif
JMessage::TControl::TControl()
: pSequenceProcessor_(NULL),
pRenderingProcessor_(NULL),
@@ -71,6 +76,12 @@ int JMessage::TControl::setMessageID(u32 uMsgID, u32 param_1, bool* pbValid) {
u32 uCode = pProcessor->toMessageCode_messageID(uMsgID, param_1, pbValid);
if (uCode == 0xFFFFFFFF) {
#if TARGET_PC
// If this is a custom text id
if (uMsgID >= BASE_CUSTOM_MSG_AND_FLOW_ID)
uCode = CUSTOM_BMG_GROUP << 16 | uMsgID;
else // return 0
#endif
return 0;
}
@@ -80,6 +91,16 @@ int JMessage::TControl::setMessageID(u32 uMsgID, u32 param_1, bool* pbValid) {
bool JMessage::TControl::setMessageCode_inSequence_(JMessage::TProcessor const* pProcessor, u16 u16GroupID, u16 u16Index) {
pEntry_ = pProcessor->getMessageEntry_messageCode(u16GroupID, u16Index);
if (pEntry_ == NULL) {
#if TARGET_PC
if (HandleCustomText(this, u16Index)) {
uMessageGroupID_ = u16GroupID;
uMessageID_ = u16Index;
pResourceCache_ = pProcessor->getResourceCache();
pMessageText_current_ = pMessageText_begin_;
oStack_renderingProcessor_.clear();
return true;
} else
#endif
return false;
}
@@ -90,6 +111,10 @@ bool JMessage::TControl::setMessageCode_inSequence_(JMessage::TProcessor const*
JUT_ASSERT(155, pResourceCache_!=NULL);
pMessageText_begin_ = pResourceCache_->getMessageText_messageEntry(pEntry_);
#if TARGET_PC
// Feels kinda hacky to have to hijack this deep into JSystem, but works for now
HandleTextOverrides(this, pProcessor, uMessageGroupID_, uMessageID_);
#endif
pMessageText_current_ = pMessageText_begin_;
oStack_renderingProcessor_.clear();
return true;
-19
View File
@@ -1,19 +0,0 @@
cmake_minimum_required(VERSION 3.25)
project(audio_mod CXX)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(DUSK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../.." CACHE PATH "Path to dusk source root")
option(DUSK_MOD_USE_FULL_TREE "Use full build instead of the minimal mod SDK" OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if (DUSK_MOD_USE_FULL_TREE)
add_subdirectory("${DUSK_DIR}" dusk EXCLUDE_FROM_ALL)
else ()
add_subdirectory("${DUSK_DIR}/sdk" dusk-sdk EXCLUDE_FROM_ALL)
endif ()
endif ()
add_mod(audio_mod
SOURCES src/mod.cpp
MOD_JSON mod.json
RES_DIR res
)
-7
View File
@@ -1,7 +0,0 @@
{
"id": "dev.twilitrealm.audio_mod",
"name": "[DEMO] Audio Mod",
"version": "1.0.0",
"author": "You, the listener",
"description": "An example Dusklight mod"
}
-1
View File
@@ -1 +0,0 @@
go.opus and go.wav are licensed CC0, from https://kenney.nl/assets/voiceover-pack
Binary file not shown.
Binary file not shown.
-39
View File
@@ -1,39 +0,0 @@
#include "mods/service.hpp"
#include "mods/svc/audio_res.h"
#include "mods/svc/log.h"
DEFINE_MOD();
IMPORT_SERVICE(LogService, svc_log);
IMPORT_SERVICE(AudioResService, svc_audio_res);
extern "C" {
MOD_EXPORT ModResult mod_initialize(ModError*) {
svc_log->info(mod_ctx, "template_mod initialized");
AudioWaveHandle handle;
svc_audio_res->replace_wave(
mod_ctx,
SoundEffects,
4238,
"res/go.opus",
nullptr,
&handle);
svc_audio_res->replace_wave(
mod_ctx,
SoundEffects,
4237,
"res/go.opus",
nullptr,
&handle);
return MOD_OK;
}
MOD_EXPORT ModResult mod_update(ModError*) {
return MOD_OK;
}
MOD_EXPORT ModResult mod_shutdown(ModError*) {
svc_log->info(mod_ctx, "template_mod unloaded");
return MOD_OK;
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "dev.twilitrealm.shadow_mod",
"name": "[Demo] Dynamic Shadows",
"version": "1.0.1",
"version": "1.0.0",
"author": "encounter",
"description": "Demo showcasing dynamic shadow maps: re-renders geometry from the sun (or moon) point of view and composites real-time shadows over the world, with screen-space contact shadows for fine detail."
}
+38 -276
View File
@@ -20,7 +20,7 @@
#include "dolphin/gx/GXPixel.h"
#include "dolphin/gx/GXTransform.h"
#include "m_Do/m_Do_mtx.h"
#include "mods/svc/hook.hpp"
#include "mods/hook.hpp"
#include "mods/service.hpp"
#include "mods/svc/camera.h"
#include "mods/svc/config.h"
@@ -29,7 +29,6 @@
#include "mods/svc/log.h"
#include "mods/svc/resource.h"
#include "mods/svc/ui.h"
#include "mods/svc/window.h"
#include <algorithm>
#include <cmath>
@@ -46,7 +45,6 @@ IMPORT_SERVICE(GfxService, svc_gfx);
IMPORT_SERVICE(CameraService, svc_camera);
IMPORT_SERVICE(HookService, svc_hook);
IMPORT_SERVICE(LogService, svc_log);
IMPORT_SERVICE(WindowService, svc_window);
namespace {
@@ -64,7 +62,6 @@ ConfigVarHandle g_cvarDebugView = 0;
GfxDrawTypeHandle g_drawType = 0;
GfxStageHookHandle g_sceneBeginHook = 0;
GfxStageHookHandle g_sceneAfterTerrainHook = 0;
GfxStageHookHandle g_sceneAfterOpaqueHook = 0;
GfxStageHookHandle g_frameBeforeHudHook = 0;
UiWindowHandle g_controlsWindow = 0;
ResourceBuffer g_shaderSource = RESOURCE_BUFFER_INIT;
@@ -73,11 +70,6 @@ WGPURenderPipeline g_compositePipeline = nullptr; // multiply blend
WGPURenderPipeline g_compositeDebugPipeline = nullptr; // no blend (debug views)
WGPUBindGroupLayout g_compositeLayout = nullptr;
WGPUBindGroupLayout g_compositeDebugLayout = nullptr;
WGPURenderPipeline g_debugPresentPipeline = nullptr;
WGPUBindGroupLayout g_debugPresentLayout = nullptr;
WGPUTextureFormat g_debugPresentFormat = WGPUTextureFormat_Undefined;
WindowHandle g_debugWindow = 0;
GfxPresentTargetHandle g_debugPresentTarget = 0;
struct MapPassOutput {
bool ready = false;
@@ -195,34 +187,6 @@ int64_t get_debug_mode() {
return std::clamp<int64_t>(get_int_option(g_cvarDebugView, 0), 0, 10);
}
bool debug_window_open() {
return g_debugWindow != 0 && g_debugPresentTarget != 0;
}
ModResult close_debug_window() {
if (g_debugPresentTarget != 0) {
const auto result = svc_gfx->unregister_present_target(mod_ctx, g_debugPresentTarget);
if (result != MOD_OK) {
return result;
}
g_debugPresentTarget = 0;
}
if (g_debugWindow != 0) {
const auto result = svc_window->destroy_window(mod_ctx, g_debugWindow);
if (result != MOD_OK) {
return result;
}
g_debugWindow = 0;
}
return MOD_OK;
}
void on_debug_window_event(ModContext*, WindowHandle, const WindowEvent* event, void*) {
if (event->type == WINDOW_EVENT_CLOSE_REQUESTED && close_debug_window() != MOD_OK) {
svc_log->error(mod_ctx, "failed to close shadow debug window");
}
}
bool matrix_ready(const Mtx m) {
float basis = 0.0f;
for (int r = 0; r < 3; ++r) {
@@ -431,90 +395,6 @@ bool build_composite_pipeline(
return outLayout != nullptr;
}
void release_debug_present_pipeline() {
if (g_debugPresentPipeline != nullptr) {
wgpuRenderPipelineRelease(g_debugPresentPipeline);
g_debugPresentPipeline = nullptr;
}
if (g_debugPresentLayout != nullptr) {
wgpuBindGroupLayoutRelease(g_debugPresentLayout);
g_debugPresentLayout = nullptr;
}
g_debugPresentFormat = WGPUTextureFormat_Undefined;
}
bool ensure_debug_present_pipeline(const GfxPresentContext& ctx) {
if (g_debugPresentPipeline != nullptr && g_debugPresentFormat == ctx.target_format) {
return true;
}
release_debug_present_pipeline();
WGPUShaderSourceWGSL wgsl = WGPU_SHADER_SOURCE_WGSL_INIT;
wgsl.code = {static_cast<const char*>(g_shaderSource.data), g_shaderSource.size};
WGPUShaderModuleDescriptor moduleDesc = WGPU_SHADER_MODULE_DESCRIPTOR_INIT;
moduleDesc.nextInChain = &wgsl.chain;
moduleDesc.label = {"shadow debug present", WGPU_STRLEN};
WGPUShaderModule module = wgpuDeviceCreateShaderModule(ctx.device, &moduleDesc);
if (module == nullptr) {
return false;
}
WGPUColorTargetState colorTarget = WGPU_COLOR_TARGET_STATE_INIT;
colorTarget.format = ctx.target_format;
WGPUFragmentState fragment = WGPU_FRAGMENT_STATE_INIT;
fragment.module = module;
fragment.entryPoint = {"fs_main", WGPU_STRLEN};
fragment.targetCount = 1;
fragment.targets = &colorTarget;
WGPURenderPipelineDescriptor pipelineDesc = WGPU_RENDER_PIPELINE_DESCRIPTOR_INIT;
pipelineDesc.label = {"shadow debug present", WGPU_STRLEN};
pipelineDesc.vertex.module = module;
pipelineDesc.vertex.entryPoint = {"vs_main", WGPU_STRLEN};
pipelineDesc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
pipelineDesc.multisample.count = 1;
pipelineDesc.fragment = &fragment;
g_debugPresentPipeline = wgpuDeviceCreateRenderPipeline(ctx.device, &pipelineDesc);
wgpuShaderModuleRelease(module);
if (g_debugPresentPipeline == nullptr) {
return false;
}
g_debugPresentLayout = wgpuRenderPipelineGetBindGroupLayout(g_debugPresentPipeline, 0);
if (g_debugPresentLayout == nullptr) {
release_debug_present_pipeline();
return false;
}
g_debugPresentFormat = ctx.target_format;
return true;
}
WGPUBindGroup create_composite_bind_group(WGPUDevice device, WGPUBindGroupLayout layout,
WGPUBuffer uniformBuffer, const DrawPayload& data) {
if (data.sceneDepth == nullptr || data.shadowMap == nullptr || data.lightColor == nullptr ||
layout == nullptr || uniformBuffer == nullptr)
{
return nullptr;
}
WGPUBindGroupEntry entries[4] = {WGPU_BIND_GROUP_ENTRY_INIT, WGPU_BIND_GROUP_ENTRY_INIT,
WGPU_BIND_GROUP_ENTRY_INIT, WGPU_BIND_GROUP_ENTRY_INIT};
entries[0].binding = 0;
entries[0].textureView = data.sceneDepth;
entries[1].binding = 1;
entries[1].textureView = data.shadowMap;
entries[2].binding = 2;
entries[2].buffer = uniformBuffer;
entries[2].offset = data.uniform_offset;
entries[2].size = data.uniform_size;
entries[3].binding = 3;
entries[3].textureView = data.lightColor;
WGPUBindGroupDescriptor bindGroupDesc = WGPU_BIND_GROUP_DESCRIPTOR_INIT;
bindGroupDesc.layout = layout;
bindGroupDesc.entryCount = 4;
bindGroupDesc.entries = entries;
return wgpuDeviceCreateBindGroup(device, &bindGroupDesc);
}
// Render worker thread: fullscreen deferred-shadow composite.
void on_draw(
ModContext*, const GfxDrawContext* ctx, const void* payload, size_t payloadSize, void*) {
@@ -527,12 +407,29 @@ void on_draw(
WGPURenderPipeline pipeline =
data.debug_mode != 0 ? g_compositeDebugPipeline : g_compositePipeline;
WGPUBindGroupLayout layout = data.debug_mode != 0 ? g_compositeDebugLayout : g_compositeLayout;
if (pipeline == nullptr) {
if (data.sceneDepth == nullptr || data.shadowMap == nullptr || data.lightColor == nullptr ||
pipeline == nullptr)
{
return;
}
WGPUBindGroup bindGroup =
create_composite_bind_group(ctx->device, layout, ctx->uniform_buffer, data);
WGPUBindGroupEntry entries[4] = {WGPU_BIND_GROUP_ENTRY_INIT, WGPU_BIND_GROUP_ENTRY_INIT,
WGPU_BIND_GROUP_ENTRY_INIT, WGPU_BIND_GROUP_ENTRY_INIT};
entries[0].binding = 0;
entries[0].textureView = data.sceneDepth;
entries[1].binding = 1;
entries[1].textureView = data.shadowMap;
entries[2].binding = 2;
entries[2].buffer = ctx->uniform_buffer;
entries[2].offset = data.uniform_offset;
entries[2].size = data.uniform_size;
entries[3].binding = 3;
entries[3].textureView = data.lightColor;
WGPUBindGroupDescriptor bindGroupDesc = WGPU_BIND_GROUP_DESCRIPTOR_INIT;
bindGroupDesc.layout = layout;
bindGroupDesc.entryCount = 4;
bindGroupDesc.entries = entries;
WGPUBindGroup bindGroup = wgpuDeviceCreateBindGroup(ctx->device, &bindGroupDesc);
if (bindGroup == nullptr) {
return;
}
@@ -543,81 +440,6 @@ void on_draw(
wgpuBindGroupRelease(bindGroup);
}
// Render worker thread: draw the selected diagnostic into the auxiliary surface.
void on_debug_present(
ModContext*, const GfxPresentContext* ctx, const void* payload, size_t payloadSize, void*) {
WGPUBindGroup bindGroup = nullptr;
if (payloadSize == sizeof(DrawPayload)) {
DrawPayload data;
std::memcpy(&data, payload, sizeof(data));
if (ensure_debug_present_pipeline(*ctx)) {
bindGroup = create_composite_bind_group(
ctx->device, g_debugPresentLayout, ctx->uniform_buffer, data);
}
}
WGPURenderPassColorAttachment colorAttachment = WGPU_RENDER_PASS_COLOR_ATTACHMENT_INIT;
colorAttachment.view = ctx->target_view;
colorAttachment.loadOp = WGPULoadOp_Clear;
colorAttachment.storeOp = WGPUStoreOp_Store;
colorAttachment.clearValue = WGPUColor{0.0, 0.0, 0.0, 1.0};
WGPURenderPassDescriptor passDesc = WGPU_RENDER_PASS_DESCRIPTOR_INIT;
passDesc.label = {"shadow debug present", WGPU_STRLEN};
passDesc.colorAttachmentCount = 1;
passDesc.colorAttachments = &colorAttachment;
WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(ctx->encoder, &passDesc);
if (bindGroup != nullptr) {
wgpuRenderPassEncoderSetPipeline(pass, g_debugPresentPipeline);
wgpuRenderPassEncoderSetBindGroup(pass, 0, bindGroup, 0, nullptr);
wgpuRenderPassEncoderDraw(pass, 3, 1, 0, 0);
wgpuBindGroupRelease(bindGroup);
}
wgpuRenderPassEncoderEnd(pass);
wgpuRenderPassEncoderRelease(pass);
}
ModResult open_debug_window() {
if (g_debugWindow != 0) {
return MOD_CONFLICT;
}
WindowDesc windowDesc = WINDOW_DESC_INIT;
windowDesc.title = "Shadow Debug View";
windowDesc.width = 720;
windowDesc.height = 480;
windowDesc.on_event = on_debug_window_event;
auto result = svc_window->create_window(mod_ctx, &windowDesc, &g_debugWindow);
if (result != MOD_OK) {
return result;
}
GfxPresentTargetDesc presentDesc = GFX_PRESENT_TARGET_DESC_INIT;
presentDesc.label = "Shadow debug surface";
presentDesc.render = on_debug_present;
result = svc_gfx->register_window_present_target(
mod_ctx, g_debugWindow, &presentDesc, &g_debugPresentTarget);
if (result != MOD_OK) {
close_debug_window();
return result;
}
result = svc_window->show_window(mod_ctx, g_debugWindow);
if (result != MOD_OK) {
close_debug_window();
}
return result;
}
void on_toggle_debug_window(ModContext*, void*) {
const auto result = debug_window_open() ? close_debug_window() : open_debug_window();
if (result != MOD_OK) {
svc_log->error(mod_ctx, debug_window_open() ? "failed to close shadow debug window" :
"failed to open shadow debug window");
}
}
// Picks the sun or moon (whichever is above the horizon) and returns the normalized
// world-space direction *toward* the light plus a horizon fade factor. False = no light.
bool compute_light(float outDirToLight[3], float& outFade) {
@@ -773,7 +595,7 @@ void restore_actual_light_debug() {
void on_scene_begin(ModContext*, const GfxStageContext* stageCtx, void*) {
restore_actual_light_debug();
capture_scene_camera(stageCtx);
if (!get_bool_option(g_cvarEnabled, true) || get_debug_mode() != 9 || debug_window_open()) {
if (!get_bool_option(g_cvarEnabled, true) || get_debug_mode() != 9) {
return;
}
@@ -831,7 +653,7 @@ void render_shadow_map(
return;
}
const int64_t debugMode = get_debug_mode();
if (debugMode == 9 && !debug_window_open()) {
if (debugMode == 9) {
return;
}
if (!matrix_ready(replayView)) {
@@ -927,30 +749,19 @@ void render_shadow_map(
g_mapPass.ready = true;
}
// Game thread, after opaque scene draws and before translucent/fog overlays: deferred composite.
void on_scene_after_opaque(ModContext*, const GfxStageContext*, void*) {
// Game thread, after the full 3D scene: deferred composite.
void on_frame_before_hud(ModContext*, const GfxStageContext*, void*) {
const int64_t debugMode = get_debug_mode();
const bool presentDebug = debug_window_open();
restore_actual_light_debug();
if (presentDebug && debugMode == 0) {
svc_gfx->push_present(mod_ctx, g_debugPresentTarget, nullptr, 0);
}
const MapPassOutput mapPass = std::exchange(g_mapPass, {});
if (debugMode == 9 && !debug_window_open()) {
if (debugMode == 9) {
return;
}
if (!mapPass.ready || mapPass.shadowMap == nullptr || mapPass.lightColor == nullptr) {
if (presentDebug && debugMode != 0) {
svc_gfx->push_present(mod_ctx, g_debugPresentTarget, nullptr, 0);
}
return;
}
if (!g_sceneCamera.valid) {
if (presentDebug && debugMode != 0) {
svc_gfx->push_present(mod_ctx, g_debugPresentTarget, nullptr, 0);
}
return;
}
const CameraInfo& camera = g_sceneCamera.info;
@@ -962,9 +773,6 @@ void on_scene_after_opaque(ModContext*, const GfxStageContext*, void*) {
if (svc_gfx->resolve_pass(mod_ctx, &resolveDesc, &resolved) != MOD_OK ||
resolved.depth == nullptr)
{
if (presentDebug && debugMode != 0) {
svc_gfx->push_present(mod_ctx, g_debugPresentTarget, nullptr, 0);
}
return;
}
@@ -989,7 +797,7 @@ void on_scene_after_opaque(ModContext*, const GfxStageContext*, void*) {
uniforms.inv_size[0] = 1.0f / uniforms.size[0];
uniforms.inv_size[1] = 1.0f / uniforms.size[1];
uniforms.edge_fade_width =
static_cast<float>(std::clamp<int64_t>(get_int_option(g_cvarEdgeFadeWidth, 32), 0, 256));
static_cast<float>(std::clamp<int64_t>(get_int_option(g_cvarEdgeFadeWidth, 32), 0, 128));
uniforms.strength =
mapPass.fade *
static_cast<float>(std::clamp<int64_t>(get_int_option(g_cvarStrength, 45), 0, 100)) /
@@ -998,36 +806,15 @@ void on_scene_after_opaque(ModContext*, const GfxStageContext*, void*) {
uniforms.contact_enabled = get_bool_option(g_cvarContactShadows, false) ? 1.0f : 0.0f;
uniforms.contact_thickness = 25.0f;
uniforms.contact_length = 60.0f;
// Camera Replay intentionally uses the gameplay-camera offscreen pass instead of the light
// shadow map, so it remains diagnostic on both windows. Other external diagnostics leave the
// main window on the normal shadow composite.
uniforms.debug_mode = presentDebug && debugMode != 10 ? 0u : static_cast<uint32_t>(debugMode);
uniforms.debug_mode = static_cast<uint32_t>(debugMode);
GfxRange uniformRange{0, 0};
if (svc_gfx->push_uniform(mod_ctx, &uniforms, sizeof(uniforms), &uniformRange) != MOD_OK) {
return;
}
const DrawPayload payload{resolved.depth, mapPass.shadowMap, mapPass.lightColor,
uniformRange.offset, uniformRange.size, uniforms.debug_mode};
uniformRange.offset, uniformRange.size, static_cast<uint32_t>(debugMode)};
svc_gfx->push_draw(mod_ctx, g_drawType, &payload, sizeof(payload));
if (presentDebug && debugMode != 0) {
uniforms.debug_mode = static_cast<uint32_t>(debugMode);
GfxRange debugUniformRange{0, 0};
if (svc_gfx->push_uniform(mod_ctx, &uniforms, sizeof(uniforms), &debugUniformRange) !=
MOD_OK)
{
return;
}
const DrawPayload debugPayload{resolved.depth, mapPass.shadowMap, mapPass.lightColor,
debugUniformRange.offset, debugUniformRange.size, uniforms.debug_mode};
svc_gfx->push_present(mod_ctx, g_debugPresentTarget, &debugPayload, sizeof(debugPayload));
}
}
// Frame tail hook: only needed to restore light-view debug camera state before HUD.
void on_frame_before_hud(ModContext*, const GfxStageContext*, void*) {
restore_actual_light_debug();
}
void add_control(UiElementHandle pane, const UiControlDesc& desc) {
@@ -1086,7 +873,7 @@ ModResult build_controls_tab(
"dynamic shadows. This can be expensive.");
add_number(left, "Coverage", g_cvarBoxRadius, 1000, 20000, 500, nullptr,
"Radius of the shadowed area around the camera, in world units. Smaller is sharper.");
add_number(left, "Fade Out", g_cvarEdgeFadeWidth, 0, 256, 32, " texels",
add_number(left, "Fade Out", g_cvarEdgeFadeWidth, 0, 128, 32, " texels",
"Fade out shadows gradually near the edge of the coverage area.");
svc_ui->pane_add_section(mod_ctx, left, "Appearance");
@@ -1112,14 +899,6 @@ ModResult build_controls_tab(
"Bounds: valid X in red, valid Y in green, and valid depth in blue<br/>Light View: "
"renders the game world directly from the light camera<br/>Camera Replay: "
"captures the same draw-list replay from the gameplay camera");
UiControlDesc debugWindowControl = UI_CONTROL_DESC_INIT;
debugWindowControl.kind = UI_CONTROL_BUTTON;
debugWindowControl.label = "Open / Close Debug Window";
debugWindowControl.help_rml =
"Shows the selected debug view in an auxiliary WebGPU window. Standard diagnostics leave "
"the main view on the normal shadow composite.";
debugWindowControl.on_pressed = on_toggle_debug_window;
add_control(left, debugWindowControl);
return MOD_OK;
}
@@ -1156,12 +935,6 @@ ModResult build_panel(ModContext*, UiElementHandle panel, void*, ModError*) {
control.label = "Open Controls";
control.on_pressed = on_open_controls;
add_control(panel, control);
control = UI_CONTROL_DESC_INIT;
control.kind = UI_CONTROL_BUTTON;
control.label = "Open / Close Debug Window";
control.on_pressed = on_toggle_debug_window;
add_control(panel, control);
return MOD_OK;
}
@@ -1227,7 +1000,7 @@ MOD_EXPORT ModResult mod_initialize(ModError* error) {
if (result != MOD_OK) {
return result;
}
result = register_int_option("edgeFadeWidth", 128, g_cvarEdgeFadeWidth, error);
result = register_int_option("edgeFadeWidth", 32, g_cvarEdgeFadeWidth, error);
if (result != MOD_OK) {
return result;
}
@@ -1268,12 +1041,6 @@ MOD_EXPORT ModResult mod_initialize(ModError* error) {
{
return mods::set_error(error, MOD_ERROR, "failed to register stage hook");
}
stageDesc.callback = on_scene_after_opaque;
if (svc_gfx->register_stage_hook(
mod_ctx, GFX_STAGE_SCENE_AFTER_OPAQUE, &stageDesc, &g_sceneAfterOpaqueHook) != MOD_OK)
{
return mods::set_error(error, MOD_ERROR, "failed to register stage hook");
}
stageDesc.callback = on_frame_before_hud;
if (svc_gfx->register_stage_hook(
mod_ctx, GFX_STAGE_FRAME_BEFORE_HUD, &stageDesc, &g_frameBeforeHudHook) != MOD_OK)
@@ -1284,18 +1051,18 @@ MOD_EXPORT ModResult mod_initialize(ModError* error) {
// Skip the game's own shadow rendering while the dynamic pass is active: the
// shadowControl pair covers the actor real/blob shadows, drawCloudShadow the weather
// cloud shadows.
if (mods::hook::add_pre<GameShadowImageDraw>(on_game_shadow_pre) != MOD_OK ||
mods::hook::add_pre<GameShadowDraw>(on_game_shadow_pre) != MOD_OK ||
mods::hook::add_pre<CloudShadowDraw>(on_game_shadow_pre) != MOD_OK)
if (mods::hook_add_pre<GameShadowImageDraw>(svc_hook, on_game_shadow_pre) != MOD_OK ||
mods::hook_add_pre<GameShadowDraw>(svc_hook, on_game_shadow_pre) != MOD_OK ||
mods::hook_add_pre<CloudShadowDraw>(svc_hook, on_game_shadow_pre) != MOD_OK)
{
return mods::set_error(error, MOD_ERROR, "failed to hook game shadow rendering");
}
if (mods::hook::add_pre<ClipperSphereClip>(on_frustum_clip_pre) != MOD_OK ||
mods::hook::add_pre<ClipperBoxClip>(on_frustum_clip_pre) != MOD_OK)
if (mods::hook_add_pre<ClipperSphereClip>(svc_hook, on_frustum_clip_pre) != MOD_OK ||
mods::hook_add_pre<ClipperBoxClip>(svc_hook, on_frustum_clip_pre) != MOD_OK)
{
return mods::set_error(error, MOD_ERROR, "failed to hook frustum clipping");
}
if (mods::hook::add_pre<CopyTex>(on_copy_tex_pre) != MOD_OK) {
if (mods::hook_add_pre<CopyTex>(svc_hook, on_copy_tex_pre) != MOD_OK) {
return mods::set_error(error, MOD_ERROR, "failed to hook GXCopyTex");
}
UiModsPanelDesc panelDesc = UI_MODS_PANEL_DESC_INIT;
@@ -1311,8 +1078,6 @@ MOD_EXPORT ModResult mod_update(ModError*) {
MOD_EXPORT ModResult mod_shutdown(ModError*) {
restore_actual_light_debug();
close_debug_window();
release_debug_present_pipeline();
svc_resource->free(mod_ctx, &g_shaderSource);
if (g_compositePipeline != nullptr) {
wgpuRenderPipelineRelease(g_compositePipeline);
@@ -1334,11 +1099,8 @@ MOD_EXPORT ModResult mod_shutdown(ModError*) {
g_cvarStrength = 0;
g_cvarPcf = g_cvarBias = g_cvarBoxRadius = g_cvarEdgeFadeWidth = g_cvarContactShadows =
g_cvarDebugView = 0;
g_drawType = g_sceneBeginHook = g_sceneAfterTerrainHook = g_sceneAfterOpaqueHook =
g_frameBeforeHudHook = 0;
g_drawType = g_sceneBeginHook = g_sceneAfterTerrainHook = g_frameBeforeHudHook = 0;
g_controlsWindow = 0;
g_debugWindow = 0;
g_debugPresentTarget = 0;
g_mapPass = {};
g_sceneCamera.valid = false;
g_sceneCamera.raw_valid = false;
-20
View File
@@ -1,20 +0,0 @@
cmake_minimum_required(VERSION 3.25)
project(window_demo CXX)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(DUSK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../.." CACHE PATH "Path to dusk source root")
option(DUSK_MOD_USE_FULL_TREE "Use full build instead of the minimal mod SDK" OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if (DUSK_MOD_USE_FULL_TREE)
add_subdirectory("${DUSK_DIR}" dusk EXCLUDE_FROM_ALL)
else ()
add_subdirectory("${DUSK_DIR}/sdk" dusk-sdk EXCLUDE_FROM_ALL)
endif ()
endif ()
add_mod(window_demo
FEATURES fmt webgpu
SOURCES src/logging.cpp src/mod.cpp
MOD_JSON mod.json
BUNDLE
)
-7
View File
@@ -1,7 +0,0 @@
{
"id": "dev.twilitrealm.window_demo",
"name": "[Demo] Extra Window",
"version": "1.0.0",
"author": "Twilit Realm",
"description": "Demonstrates creating an extra window through WindowService and rendering to it with GfxService."
}
-35
View File
@@ -1,35 +0,0 @@
#include "logging.hpp"
#include "mods/svc/log.hpp"
#include "mods/svc/window.h"
namespace {
const char* window_event_name(WindowEventType type) {
switch (type) {
case WINDOW_EVENT_CLOSE_REQUESTED:
return "close requested";
case WINDOW_EVENT_RESIZED:
return "resized";
case WINDOW_EVENT_MOVED:
return "moved";
case WINDOW_EVENT_FOCUS_GAINED:
return "focus gained";
case WINDOW_EVENT_FOCUS_LOST:
return "focus lost";
case WINDOW_EVENT_SHOWN:
return "shown";
case WINDOW_EVENT_HIDDEN:
return "hidden";
}
return "unknown";
}
} // namespace
void window_demo::log_window_event(const WindowEvent* event) {
mods::log::info(
"window event: {}; position=({}, {}), size={}x{}, pixels={}x{}, scale={:.2f}",
window_event_name(event->type), event->x, event->y, event->width, event->height,
event->pixel_width, event->pixel_height, event->display_scale);
}
-9
View File
@@ -1,9 +0,0 @@
#pragma once
struct WindowEvent;
namespace window_demo {
void log_window_event(const WindowEvent* event);
} // namespace window_demo
-229
View File
@@ -1,229 +0,0 @@
#include "logging.hpp"
#include "mods/service.hpp"
#include "mods/svc/gfx.h"
#include "mods/svc/log.hpp"
#include "mods/svc/ui.h"
#include "mods/svc/window.h"
#include <cmath>
#include <cstring>
#include <webgpu/webgpu.h>
DEFINE_MOD();
IMPORT_SERVICE(LogService, svc_log);
IMPORT_SERVICE(UiService, svc_ui);
IMPORT_SERVICE(WindowService, svc_window);
IMPORT_SERVICE(GfxService, svc_gfx);
namespace {
WindowHandle g_window = 0;
GfxPresentTargetHandle g_presentTarget = 0;
GfxStageHookHandle g_stageHook = 0;
uint32_t g_frame = 0;
bool g_recreatePresentTarget = false;
struct ClearPayload {
float red;
float green;
float blue;
float alpha;
};
static_assert(sizeof(ClearPayload) <= GFX_INLINE_DRAW_PAYLOAD_SIZE);
ModResult close_window() {
g_recreatePresentTarget = false;
if (g_presentTarget != 0) {
const auto result = svc_gfx->unregister_present_target(mod_ctx, g_presentTarget);
if (result != MOD_OK) {
return result;
}
g_presentTarget = 0;
}
if (g_window != 0) {
const auto result = svc_window->destroy_window(mod_ctx, g_window);
if (result != MOD_OK) {
return result;
}
g_window = 0;
}
return MOD_OK;
}
void on_window_event(ModContext*, WindowHandle, const WindowEvent* event, void*) {
window_demo::log_window_event(event);
if (event->type == WINDOW_EVENT_CLOSE_REQUESTED) {
if (close_window() != MOD_OK) {
mods::log::error("failed to close auxiliary window");
}
}
}
// Render worker thread: record a clear of the acquired auxiliary surface texture.
void on_present(
ModContext*, const GfxPresentContext* ctx, const void* payload, size_t payloadSize, void*) {
if (payloadSize != sizeof(ClearPayload)) {
return;
}
ClearPayload color;
std::memcpy(&color, payload, sizeof(color));
WGPURenderPassColorAttachment colorAttachment = WGPU_RENDER_PASS_COLOR_ATTACHMENT_INIT;
colorAttachment.view = ctx->target_view;
colorAttachment.loadOp = WGPULoadOp_Clear;
colorAttachment.storeOp = WGPUStoreOp_Store;
colorAttachment.clearValue = WGPUColor{
color.red,
color.green,
color.blue,
color.alpha,
};
WGPURenderPassDescriptor passDesc = WGPU_RENDER_PASS_DESCRIPTOR_INIT;
passDesc.label = {"Auxiliary window clear", WGPU_STRLEN};
passDesc.colorAttachmentCount = 1;
passDesc.colorAttachments = &colorAttachment;
WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(ctx->encoder, &passDesc);
wgpuRenderPassEncoderEnd(pass);
wgpuRenderPassEncoderRelease(pass);
}
ModResult register_present_target() {
if (g_window == 0 || g_presentTarget != 0) {
return MOD_CONFLICT;
}
GfxPresentTargetDesc presentDesc = GFX_PRESENT_TARGET_DESC_INIT;
presentDesc.label = "Auxiliary window surface";
presentDesc.render = on_present;
presentDesc.preferred_alpha_mode =
WGPUCompositeAlphaMode_Premultiplied; // For transparent window
return svc_gfx->register_window_present_target(
mod_ctx, g_window, &presentDesc, &g_presentTarget);
}
ModResult open_window() {
if (g_window != 0) {
return MOD_CONFLICT;
}
WindowDesc windowDesc = WINDOW_DESC_INIT;
windowDesc.title = "Mod window";
windowDesc.width = 640;
windowDesc.height = 480;
windowDesc.on_event = on_window_event;
windowDesc.flags |= WINDOW_FLAG_TRANSPARENT; // For transparent window
auto result = svc_window->create_window(mod_ctx, &windowDesc, &g_window);
if (result != MOD_OK) {
return result;
}
result = register_present_target();
if (result != MOD_OK) {
close_window();
return result;
}
result = svc_window->show_window(mod_ctx, g_window);
if (result != MOD_OK) {
close_window();
}
return result;
}
void on_frame_after_hud(ModContext*, const GfxStageContext*, void*) {
if (g_presentTarget == 0) {
return;
}
const float phase = static_cast<float>(g_frame++) * 0.015f;
const ClearPayload color{
.red = 0.08f + 0.06f * (std::sin(phase) + 1.0f),
.green = 0.10f + 0.06f * (std::sin(phase + 2.1f) + 1.0f),
.blue = 0.14f + 0.08f * (std::sin(phase + 4.2f) + 1.0f),
.alpha = 0.5f,
};
if (svc_gfx->push_present(mod_ctx, g_presentTarget, &color, sizeof(color)) == MOD_ERROR) {
g_recreatePresentTarget = true;
}
}
void on_toggle_window(ModContext*, void*) {
if (g_window != 0) {
if (close_window() != MOD_OK) {
mods::log::error("failed to close auxiliary window");
}
return;
}
if (open_window() != MOD_OK) {
mods::log::error("failed to open auxiliary window");
}
}
ModResult build_panel(ModContext*, UiElementHandle panel, void*, ModError*) {
UiControlDesc control = UI_CONTROL_DESC_INIT;
control.kind = UI_CONTROL_BUTTON;
control.label = "Open / Close Window";
control.on_pressed = on_toggle_window;
return svc_ui->pane_add_control(mod_ctx, panel, &control, nullptr);
}
} // namespace
extern "C" {
MOD_EXPORT ModResult mod_initialize(ModError* error) {
GfxStageHookDesc stageDesc = GFX_STAGE_HOOK_DESC_INIT;
stageDesc.callback = on_frame_after_hud;
if (svc_gfx->register_stage_hook(
mod_ctx, GFX_STAGE_FRAME_AFTER_HUD, &stageDesc, &g_stageHook) != MOD_OK)
{
return mods::set_error(error, MOD_ERROR, "failed to register presentation hook");
}
UiModsPanelDesc panelDesc = UI_MODS_PANEL_DESC_INIT;
panelDesc.build = build_panel;
if (svc_ui->register_mods_panel(mod_ctx, &panelDesc) != MOD_OK) {
svc_gfx->unregister_stage_hook(mod_ctx, g_stageHook);
g_stageHook = 0;
return mods::set_error(error, MOD_ERROR, "failed to register mod panel");
}
if (open_window() != MOD_OK) {
svc_gfx->unregister_stage_hook(mod_ctx, g_stageHook);
g_stageHook = 0;
return mods::set_error(error, MOD_ERROR, "failed to open auxiliary window");
}
mods::log::info("auxiliary WebGPU window ready");
return MOD_OK;
}
MOD_EXPORT ModResult mod_update(ModError* error) {
if (!g_recreatePresentTarget || g_window == 0) {
return MOD_OK;
}
g_recreatePresentTarget = false;
if (g_presentTarget != 0) {
const auto result = svc_gfx->unregister_present_target(mod_ctx, g_presentTarget);
if (result != MOD_OK) {
return mods::set_error(error, result, "failed to unregister lost present target");
}
g_presentTarget = 0;
}
const auto result = register_present_target();
if (result != MOD_OK) {
return mods::set_error(error, result, "failed to recreate present target");
}
return MOD_OK;
}
MOD_EXPORT ModResult mod_shutdown(ModError*) {
if (g_stageHook != 0) {
svc_gfx->unregister_stage_hook(mod_ctx, g_stageHook);
g_stageHook = 0;
}
close_window();
return MOD_OK;
}
}
+18 -1
View File
@@ -21,9 +21,26 @@ export JAVA_HOME="/usr/lib/jvm/java-17-openjdk"
```bash
cmake --preset android-arm64
cmake --build --preset android-arm64
cmake --preset android-x86_64
cmake --build --preset android-x86_64
```
This build produces `build/android-arm64/libmain.so`
These builds produce:
- `build/android-arm64/Binaries/libmain.so`
- `build/android-x86_64/Binaries/libmain.so`
## Stage Libraries Into APK Project
```bash
./android/scripts/stage-jni-libs.sh
```
This copies:
- `libmain.so` -> `android/app/src/main/jniLibs/arm64-v8a/`
- `libmain.so` -> `android/app/src/main/jniLibs/x86_64/`
## Refresh SDL Java Shim (Optional)
+11 -100
View File
@@ -6,107 +6,23 @@ def versionNameStr = (System.getenv("DUSK_VERSION") ?: "v0.1.0").replaceFirst("^
def versionCodeInt = (System.getenv("DUSK_VERSION_CODE") ?: "100000").toInteger()
def duskRepoDir = rootProject.projectDir.parentFile.parentFile
def androidNativeBuildDir = new File(duskRepoDir, 'build/android-arm64')
def nativeLibrary = new File(androidNativeBuildDir, 'libmain.so')
def stageStripValue = providers.gradleProperty('ANDROID_STAGE_STRIP')
.orElse(providers.gradleProperty('androidStageStrip'))
.orElse(providers.environmentVariable('ANDROID_STAGE_STRIP'))
.orElse('1')
def androidHome = {
def sdkPath = System.getenv('ANDROID_HOME')
if (!sdkPath) {
throw new GradleException('ANDROID_HOME is not available')
}
def sdkDir = new File(sdkPath)
if (!sdkDir.isDirectory()) {
throw new GradleException("ANDROID_HOME points to a missing directory: ${sdkDir}")
}
sdkDir
}.memoize()
def androidNdkVersion = {
def ndkVersion = System.getenv('ANDROID_NDK_VERSION')
if (!ndkVersion) {
throw new GradleException('ANDROID_NDK_VERSION is not available')
}
ndkVersion
}.memoize()
def androidNdkDir = {
def ndkDir = new File(androidHome(), "ndk/${androidNdkVersion()}")
if (!new File(ndkDir, 'build/cmake/android.toolchain.cmake').isFile()) {
throw new GradleException(
"Android NDK ${androidNdkVersion()} is missing or invalid at ${ndkDir}"
)
}
ndkDir
}.memoize()
def llvmPrebuiltDir = {
def prebuiltRoot = new File(androidNdkDir(), 'toolchains/llvm/prebuilt')
def prebuiltDir = (prebuiltRoot.listFiles()?.findAll { it.isDirectory() } ?: [])
.sort { it.name }
.find { candidate ->
new File(
candidate,
'sysroot/usr/lib/aarch64-linux-android/libc++_shared.so'
).isFile()
}
if (!prebuiltDir) {
throw new GradleException("Cannot find NDK libc++_shared.so under ${prebuiltRoot}")
}
prebuiltDir
}.memoize()
def stlLibrary = {
def library = new File(
llvmPrebuiltDir(),
'sysroot/usr/lib/aarch64-linux-android/libc++_shared.so'
)
if (!library.isFile()) {
throw new GradleException("libc++_shared.so is missing")
}
library
}.memoize()
def stagedJniLibsDir = layout.buildDirectory.dir('generated/jniLibs/dusklight')
def stageJniLibs = tasks.register('stageJniLibs', Sync) {
group = 'build'
from(nativeLibrary) {
rename { 'libmain.so' }
into 'arm64-v8a'
}
from(providers.provider { stlLibrary() }) {
rename { 'libc++_shared.so' }
into 'arm64-v8a'
}
into(stagedJniLibsDir)
doFirst {
if (!nativeLibrary.isFile()) {
throw new GradleException("Native library is missing")
}
}
}
def duskGeneratedAssetsDir = layout.buildDirectory.dir('generated/assets/dusklight')
def duskGeneratedAssetsDir = layout.buildDirectory.dir('generated/assets/dusklight').get().asFile
def syncDuskAssets = tasks.register('syncDuskAssets', Sync) {
from(new File(duskRepoDir, 'res')) {
into 'res'
exclude '**/.DS_Store'
}
from(new File(androidNativeBuildDir, 'bundled_mods')) {
// Staged by platforms/android/scripts/stage-jni-libs.sh
from(new File(projectDir, 'src/main/bundled_mods')) {
into 'mods'
include '*.dusk'
}
into(duskGeneratedAssetsDir)
into duskGeneratedAssetsDir
}
android {
namespace 'dev.twilitrealm.dusk'
compileSdk 36
ndkVersion androidNdkVersion()
defaultConfig {
applicationId 'dev.twilitrealm.dusk'
@@ -128,24 +44,16 @@ android {
sourceSets {
main {
jniLibs.srcDirs = [stagedJniLibsDir]
jniLibs.srcDirs = ['src/main/jniLibs']
assets.srcDirs = [duskGeneratedAssetsDir]
}
}
packaging {
jniLibs {
if (stageStripValue.get() == '0') {
keepDebugSymbols += '**/libmain.so'
}
}
}
splits {
abi {
enable true
reset()
include 'arm64-v8a'
include 'arm64-v8a', 'x86_64'
universalApk false
}
}
@@ -159,6 +67,9 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
tasks.named('preBuild').configure {
dependsOn(stageJniLibs, syncDuskAssets)
tasks.configureEach { task ->
if ((task.name.startsWith('merge') && task.name.endsWith('Assets')) ||
task.name.toLowerCase().contains('lint')) {
task.dependsOn(syncDuskAssets)
}
}
+115
View File
@@ -0,0 +1,115 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
APP_DIR="$ROOT_DIR/platforms/android/app/src/main/jniLibs"
ANDROID_HOME_DIR="${ANDROID_HOME:-$HOME/Android/Sdk}"
ANDROID_NDK_VER="${ANDROID_NDK_VERSION:-}"
ANDROID_STAGE_ABIS="${ANDROID_STAGE_ABIS:-arm64-v8a x86_64}"
ANDROID_STAGE_STRIP="${ANDROID_STAGE_STRIP:-1}"
STRIP_TOOL=""
if [[ -z "$ANDROID_NDK_VER" ]] && [[ -d "$ANDROID_HOME_DIR/ndk" ]]; then
ANDROID_NDK_VER="$(ls -1 "$ANDROID_HOME_DIR/ndk" | sort -V | tail -n 1)"
fi
if [[ -n "$ANDROID_NDK_VER" ]]; then
case "$(uname -s)" in
Darwin) HOST_TAG="darwin-x86_64" ;;
Linux) HOST_TAG="linux-x86_64" ;;
*) HOST_TAG="" ;;
esac
PREBUILT_DIR="$ANDROID_HOME_DIR/ndk/$ANDROID_NDK_VER/toolchains/llvm/prebuilt"
if [[ -n "$HOST_TAG" && -x "$PREBUILT_DIR/$HOST_TAG/bin/llvm-strip" ]]; then
STRIP_TOOL="$PREBUILT_DIR/$HOST_TAG/bin/llvm-strip"
else
for candidate in "$PREBUILT_DIR"/*/bin/llvm-strip; do
if [[ -x "$candidate" ]]; then
STRIP_TOOL="$candidate"
break
fi
done
fi
fi
copy_lib() {
local abi="$1"
local src="$2"
local dst_dir="$APP_DIR/$abi"
local dst="$dst_dir/libmain.so"
local tmp="$dst_dir/.libmain.so.$$"
if [[ ! -f "$src" ]]; then
echo "Missing native library for $abi: $src" >&2
exit 1
fi
mkdir -p "$dst_dir"
cp -f "$src" "$tmp"
if [[ "$ANDROID_STAGE_STRIP" != "0" ]] && [[ -n "$STRIP_TOOL" ]]; then
"$STRIP_TOOL" --strip-unneeded "$tmp"
mv -f "$tmp" "$dst"
echo "Stripped and staged $src -> $dst"
else
mv -f "$tmp" "$dst"
echo "Staged $src -> $dst (strip disabled or strip tool unavailable)"
fi
}
# Drop any previously staged ABI directories to avoid stale APK contents.
rm -rf "$APP_DIR/x86" "$APP_DIR/arm64-v8a" "$APP_DIR/x86_64"
for abi in $ANDROID_STAGE_ABIS; do
case "$abi" in
arm64-v8a)
src="$ROOT_DIR/build/android-arm64/libmain.so"
triple="aarch64-linux-android"
;;
x86_64)
src="$ROOT_DIR/build/android-x86_64/libmain.so"
triple="x86_64-linux-android"
;;
*)
echo "Unsupported ABI '$abi'. Supported ABIs: arm64-v8a x86_64" >&2
exit 1
;;
esac
copy_lib "$abi" "$src"
if [[ -n "$STRIP_TOOL" ]]; then
stl="$(dirname "$STRIP_TOOL")/../sysroot/usr/lib/$triple/libc++_shared.so"
if [[ -f "$stl" ]]; then
cp -f "$stl" "$APP_DIR/$abi/libc++_shared.so"
echo "Staged $stl -> $APP_DIR/$abi/libc++_shared.so"
else
echo "Missing libc++_shared.so for $abi at $stl" >&2
exit 1
fi
else
echo "Cannot stage libc++_shared.so for $abi (NDK not found)" >&2
exit 1
fi
done
# Stage bundled mod packages into the app's assets source dir.
MODS_STAGING_DIR="$ROOT_DIR/platforms/android/app/src/main/bundled_mods"
rm -rf "$MODS_STAGING_DIR"
mkdir -p "$MODS_STAGING_DIR"
for abi in $ANDROID_STAGE_ABIS; do
case "$abi" in
arm64-v8a) build_dir="$ROOT_DIR/build/android-arm64" ;;
x86_64) build_dir="$ROOT_DIR/build/android-x86_64" ;;
esac
[[ -d "$build_dir/bundled_mods" ]] || continue
for pkg in "$build_dir/bundled_mods"/*.dusk; do
[[ -f "$pkg" ]] || continue
name="$(basename "$pkg")"
if [[ ! -f "$MODS_STAGING_DIR/$name" ]]; then
cp -f "$pkg" "$MODS_STAGING_DIR/$name"
echo "Staged bundled mod $pkg"
else
stage_dir="$build_dir/mods/${name%.dusk}/${name%.dusk}_stage"
(cd "$stage_dir" && zip -q -r "$MODS_STAGING_DIR/$name" lib)
echo "Appended $abi libraries to bundled mod $name"
fi
done
done
+25
View File
@@ -105,6 +105,18 @@ window content pane > * {
flex: 0 0 auto;
}
pane.excluded-locations-pane {
display: flex;
flex-flow: column;
flex: 1 1 0;
min-width: 0;
min-height: 0;
gap: 8dp;
overflow-y: scroll;
font-size: 20dp;
border-top: 1dp #92875B;
}
window content pane:last-of-type > div {
line-height: 1.625;
}
@@ -478,6 +490,7 @@ window.modal.danger .modal-header icon {
font-size: 20dp;
color: #FFFFFF;
font-weight: normal;
word-break: break-word;
}
.modal-body span.tip {
@@ -519,3 +532,15 @@ progress.verification-progress-bar {
flex: 0 0 auto;
padding-top: 4dp;
}
.current-option-text {
padding-left: 5dp;
border: 2dp #C2A42D;
border-radius: 14dp;
}
.not-current-option-text {
padding-left: 5dp;
margin: 2dp; /*Used to mimic border*/
opacity: 0.5;
}
+1 -1
View File
@@ -5,7 +5,7 @@
#
# Usage (from a mod project):
# add_subdirectory(<dusk>/sdk dusk-sdk EXCLUDE_FROM_ALL)
# add_mod(my_mod FEATURES fmt game webgpu SOURCES ... MOD_JSON mod.json)
# add_mod(my_mod FEATURES game webgpu SOURCES ... MOD_JSON mod.json)
#
# On platforms where mods link against the game binary (Windows/Apple/Android), a
# version-independent link stub is downloaded automatically unless DUSK_GAME_EXE is set.
+1 -17
View File
@@ -20,23 +20,7 @@ extern "C" {
#ifdef __cplusplus
#define MOD_EXTERN_C extern "C"
#else
#define MOD_EXTERN_C extern
#endif
#ifdef __cplusplus
#define MOD_DECLARE_SERVICE( \
service_type, variable, service_id_value, major_value, minor_value) \
MOD_EXTERN_C const service_type* variable; \
template <> \
struct mods::ServiceTraits<service_type> { \
static constexpr const char* id = service_id_value; \
static constexpr uint16_t major_version = major_value; \
static constexpr uint16_t minor_version = minor_value; \
}
#else
#define MOD_DECLARE_SERVICE( \
service_type, variable, service_id_value, major_value, minor_value) \
MOD_EXTERN_C const service_type* variable
#define MOD_EXTERN_C
#endif
#define MOD_ABI_VERSION 1u
+179 -25
View File
@@ -1,56 +1,210 @@
#pragma once
#if defined(_MSC_VER)
#pragma message("warning: <mods/hook.hpp> is deprecated; include <mods/svc/hook.hpp> instead")
#else
#warning "<mods/hook.hpp> is deprecated; include <mods/svc/hook.hpp> instead"
#if !defined(DUSK_BUILDING_GAME) && !defined(DUSK_MOD_FEATURE_GAME)
#error "DEFINE_HOOK requires add_mod(... FEATURES game)"
#endif
#include <mods/svc/hook.hpp>
#include <mods/svc/hook.h>
#include <memory>
#include <type_traits>
namespace mods {
template <class Entry>
ModResult hook_install(const HookService* hooks) {
return hook::install<Entry>(hooks);
template <class T>
T arg(void* argsRaw, int n) noexcept {
void** args = static_cast<void**>(argsRaw);
return *static_cast<std::add_pointer_t<std::remove_reference_t<T>>>(args[n]);
}
template <class T>
std::remove_reference_t<T>& arg_ref(void* argsRaw, int n) noexcept {
void** args = static_cast<void**>(argsRaw);
return *static_cast<std::add_pointer_t<std::remove_reference_t<T>>>(args[n]);
}
/*
* Trampoline generator + per-target state. Tag makes each hooked target's statics distinct; the
* target address comes from the declaration's metadata record, resolved by the host at mod
* initialization.
*/
template <class Tag, class R, class... A>
struct HookImpl {
static inline R (*g_orig)(A...) = nullptr;
static inline const HookService* hooks = nullptr;
static inline void* target = nullptr;
static bool dispatch_pre(void* args, void* retval) {
if (hooks == nullptr) {
return false;
}
int skipOriginal = 0;
const ModResult result = hooks->dispatch_pre(mod_ctx, target, args, retval, &skipOriginal);
return result == MOD_OK && skipOriginal != 0;
}
static void dispatch_post(void* args, void* retval) {
if (hooks != nullptr) {
hooks->dispatch_post(mod_ctx, target, args, retval);
}
}
static R trampoline(A... args) {
if constexpr (sizeof...(A) == 0) {
if constexpr (std::is_void_v<R>) {
const bool skipOriginal = dispatch_pre(nullptr, nullptr);
if (!skipOriginal) {
g_orig(args...);
}
dispatch_post(nullptr, nullptr);
} else {
R result{};
const bool skipOriginal =
dispatch_pre(nullptr, static_cast<void*>(std::addressof(result)));
if (!skipOriginal) {
result = g_orig(args...);
}
dispatch_post(nullptr, static_cast<void*>(std::addressof(result)));
return result;
}
} else {
void* ptrs[] = {static_cast<void*>(std::addressof(args))...};
if constexpr (std::is_void_v<R>) {
const bool skipOriginal = dispatch_pre(static_cast<void*>(ptrs), nullptr);
if (!skipOriginal) {
g_orig(args...);
}
dispatch_post(static_cast<void*>(ptrs), nullptr);
} else {
R result{};
const bool skipOriginal = dispatch_pre(
static_cast<void*>(ptrs), static_cast<void*>(std::addressof(result)));
if (!skipOriginal) {
result = g_orig(args...);
}
dispatch_post(static_cast<void*>(ptrs), static_cast<void*>(std::addressof(result)));
return result;
}
}
}
};
namespace detail {
template <auto Target>
using TargetTag = std::integral_constant<decltype(Target), Target>;
template <FixedString Name>
struct NameTag {};
} // namespace detail
/*
* Typed base for a hook on a function named at compile time (&daAlink_c::execute, &free_fn).
* Instantiate through DEFINE_HOOK, which pairs it with the metadata record the host resolves.
*/
template <auto Target>
struct Hook;
template <class C, class R, class... A, R (C::*Target)(A...)>
struct Hook<Target> : HookImpl<detail::TargetTag<Target>, R, C*, A...> {};
template <class C, class R, class... A, R (C::*Target)(A...) const>
struct Hook<Target> : HookImpl<detail::TargetTag<Target>, R, const C*, A...> {};
template <class R, class... A, R (*Target)(A...)>
struct Hook<Target> : HookImpl<detail::TargetTag<Target>, R, A...> {};
/*
* Typed base for a hook on a function by its symbol name, for targets you can't name in C++:
* file-local statics, private members, or symbols without a header. The signature is written
* free-style with the receiver first and is *not* compiler-checked. Instantiate through
* DEFINE_HOOK_SYMBOL.
*/
template <FixedString Name, class Sig>
struct NamedHook;
template <FixedString Name, class R, class... A>
struct NamedHook<Name, R(A...)> : HookImpl<detail::NameTag<Name>, R, A...> {};
/*
* Declare a hook target. The declaration emits a metadata record that the host resolves at mod
* initialization. Every hook target must be declared.
*
* DEFINE_HOOK(&daAlink_c::execute, LinkExecute);
* DEFINE_HOOK_SYMBOL("daAlink_hookshotAtHitCallBack",
* void(fopAc_ac_c*, dCcD_GObjInf*, fopAc_ac_c*, dCcD_GObjInf*), HookshotHit);
*
* mods::hook_add_pre<LinkExecute>(svc_hook, on_link_execute);
*
* DEFINE_HOOK_SYMBOL names may be the platform mangled name (dlopen convention, no Mach-O
* leading underscore) or the demangled qualified display name; overloaded display names are
* ambiguous and need the mangled form.
*/
#define DEFINE_HOOK(target, alias) \
[[maybe_unused]] static const void* const mod_meta_hook_##alias = \
&::mods::detail::HookRecordFor<(target), ::mods::FixedString{#target}>::Holder::record; \
struct alias : ::mods::Hook<(target)> { \
static void* resolved_target() { \
return ::mods::detail::HookRecordFor<(target), \
::mods::FixedString{#target}>::Holder::record.resolved; \
} \
}
#define DEFINE_HOOK_SYMBOL(name, sig, alias) \
MOD_META_RECORD static constinit auto mod_meta_hook_##alias = \
::mods::detail::make_hook_name_record<::mods::FixedString{name}>(); \
struct alias : ::mods::NamedHook<::mods::FixedString{name}, sig> { \
static void* resolved_target() { return mod_meta_hook_##alias.resolved; } \
}
template <class Entry>
ModResult hook_install() {
return hook::install<Entry>();
ModResult hook_install(const HookService* hooks) {
if (hooks == nullptr) {
return MOD_UNAVAILABLE;
}
Entry::hooks = hooks;
if (Entry::target == nullptr) {
void* resolved = Entry::resolved_target();
if (resolved == nullptr) {
return MOD_UNAVAILABLE;
}
Entry::target = resolved;
}
return hooks->install(mod_ctx, Entry::target, reinterpret_cast<void*>(Entry::trampoline),
reinterpret_cast<void**>(&Entry::g_orig));
}
template <class Entry>
ModResult hook_add_pre(
const HookService* hooks, HookPreFn callback, const HookOptions* options = nullptr) {
return hook::add_pre<Entry>(hooks, callback, options);
}
const ModResult installed = hook_install<Entry>(hooks);
if (installed != MOD_OK) {
return installed;
}
template <class Entry>
ModResult hook_add_pre(HookPreFn callback, const HookOptions* options = nullptr) {
return hook::add_pre<Entry>(callback, options);
return hooks->add_pre(mod_ctx, Entry::target, callback, options);
}
template <class Entry>
ModResult hook_add_post(
const HookService* hooks, HookPostFn callback, const HookOptions* options = nullptr) {
return hook::add_post<Entry>(hooks, callback, options);
}
const ModResult installed = hook_install<Entry>(hooks);
if (installed != MOD_OK) {
return installed;
}
template <class Entry>
ModResult hook_add_post(HookPostFn callback, const HookOptions* options = nullptr) {
return hook::add_post<Entry>(callback, options);
return hooks->add_post(mod_ctx, Entry::target, callback, options);
}
template <class Entry>
ModResult hook_replace(
const HookService* hooks, HookReplaceFn callback, const HookOptions* options = nullptr) {
return hook::replace<Entry>(hooks, callback, options);
}
const ModResult installed = hook_install<Entry>(hooks);
if (installed != MOD_OK) {
return installed;
}
template <class Entry>
ModResult hook_replace(HookReplaceFn callback, const HookOptions* options = nullptr) {
return hook::replace<Entry>(callback, options);
return hooks->replace(mod_ctx, Entry::target, callback, options);
}
} // namespace mods
-42
View File
@@ -241,48 +241,6 @@ consteval auto make_hook_mem_names() {
return r;
}
#if defined(__GNUC__) && !defined(__clang__) && defined(__ELF__)
/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41091 prevents inline static template members from
* sharing an explicit ELF section with ordinary variables. GCC can instead constant-evaluate a
* file-local record at each DEFINE_HOOK. */
template <auto Target>
void materialize_hook_mem(unsigned char* outPmf) {
const auto target = Target;
std::memcpy(outPmf, &target, sizeof(target));
}
template <auto Target, FixedString Disp>
consteval auto make_local_hook_record() {
using F = decltype(Target);
if constexpr (std::is_member_function_pointer_v<F>) {
constexpr auto names = make_hook_mem_names<Target, Disp>();
static_assert(sizeof(F) <= MOD_META_HOOK_MEM_EXT_CAPACITY,
"unsupported pointer-to-member representation");
if constexpr (sizeof(F) > MOD_META_HOOK_MEM_CAPACITY) {
HookMemExtRecord<names.len> record = {
{sizeof(HookMemExtRecord<names.len>), MOD_META_HOOK_MEM_EXT, 0}, sizeof(F),
materialize_hook_mem<Target>, nullptr, {}};
for (size_t i = 0; i < names.len; ++i) {
record.names[i] = names.chars[i];
}
return record;
} else {
HookMemRecord<F, names.len> record = {
{sizeof(HookMemRecord<F, names.len>), MOD_META_HOOK_MEM, 0}, 0, {Target}, nullptr,
{}};
for (size_t i = 0; i < names.len; ++i) {
record.names[i] = names.chars[i];
}
return record;
}
} else {
static_assert(std::is_pointer_v<F> && std::is_function_v<std::remove_pointer_t<F>>,
"hook target must be a function or member function");
return HookFnRecord<F>{{sizeof(HookFnRecord<F>), MOD_META_HOOK_FN, 0}, 0, Target, nullptr};
}
}
#endif
/*
* MSVC constant-evaluates a compact pointer-to-member only when every other operand in the
* initializer is a literal: no consteval calls, constexpr-object copies, or default member
+2 -2
View File
@@ -40,13 +40,13 @@ inline ModResult set_error(ModError* outError, ModResult code, const char* messa
}; \
}
// Defines `const service_type* variable`, filled in by the host before mod_initialize.
// Declares `static const service_type* variable`, filled in by the host before mod_initialize.
// Required imports are guaranteed non-null (the mod fails to load otherwise); optional imports
// must be checked against nullptr before use. The unversioned macros use the latest minor version;
// set an explicit version to target an older minor version for backwards compatibility.
#define IMPORT_SERVICE_EX( \
service_type, variable, service_id_value, major_value, min_minor_value, flags_value) \
const service_type* variable = nullptr; \
static const service_type* variable = nullptr; \
MOD_META_RECORD static constinit ModMetaImport mod_meta_import_##variable = { \
{sizeof(ModMetaImport), MOD_META_IMPORT, static_cast<uint8_t>(flags_value)}, \
static_cast<uint16_t>(major_value), \
-67
View File
@@ -1,67 +0,0 @@
#pragma once
#include <mods/api.h>
#define AUDIO_RES_SERVICE_ID "dev.twilitrealm.dusklight.audio_res"
#define AUDIO_RES_SERVICE_MAJOR 1u
#define AUDIO_RES_SERVICE_MINOR 0u
#define AUDIO_RES_DEFAULT_KEY 0x3C;
typedef enum AudioWaveBank : uint8_t {
SoundEffects = 0,
MusicSamples = 1,
} AudioWaveBank;
typedef enum AudioWaveFormat : uint8_t {
Adpcm4 = 0,
Adpcm2 = 1,
Pcm8 = 2,
Pcm16 = 3,
} AudioWaveFormat;
typedef uint64_t AudioWaveHandle;
/**
*
*/
typedef struct AudioRawWave {
AudioWaveFormat format;
float sample_rate;
int16_t sample_value_last;
int16_t sample_value_penult;
} AudioRawWave;
typedef struct AudioWaveInfo {
uint8_t base_key;
bool loop;
uint32_t loop_start_sample;
uint32_t loop_end_sample;
AudioRawWave const* raw_wave;
} AudioWaveInfo;
typedef struct AudioResService {
ServiceHeader header;
ModResult (*replace_wave)(
ModContext* ctx,
AudioWaveBank bank,
uint16_t wave_id,
char const* file_name,
AudioWaveInfo const* wave_info,
AudioWaveHandle* out_handle);
ModResult (*remove_wave)(ModContext* ctx, AudioWaveHandle handle);
} AudioResService;
#ifdef __cplusplus
#include "mods/service.hpp"
template <>
struct mods::ServiceTraits<AudioResService> {
static constexpr const char* id = AUDIO_RES_SERVICE_ID;
static constexpr uint16_t major_version = AUDIO_RES_SERVICE_MAJOR;
static constexpr uint16_t minor_version = AUDIO_RES_SERVICE_MINOR;
};
#endif
+10 -6
View File
@@ -2,10 +2,6 @@
#include <mods/api.h>
#ifdef __cplusplus
#include <mods/service.hpp>
#endif
#define CAMERA_SERVICE_ID "dev.twilitrealm.dusklight.camera"
#define CAMERA_SERVICE_MAJOR 1u
#define CAMERA_SERVICE_MINOR 0u
@@ -57,5 +53,13 @@ typedef struct CameraService {
ModResult (*get_camera)(ModContext* ctx, const void* game_view, CameraInfo* out_info);
} CameraService;
MOD_DECLARE_SERVICE(
CameraService, svc_camera, CAMERA_SERVICE_ID, CAMERA_SERVICE_MAJOR, CAMERA_SERVICE_MINOR);
#ifdef __cplusplus
#include "mods/service.hpp"
template <>
struct mods::ServiceTraits<CameraService> {
static constexpr const char* id = CAMERA_SERVICE_ID;
static constexpr uint16_t major_version = CAMERA_SERVICE_MAJOR;
static constexpr uint16_t minor_version = CAMERA_SERVICE_MINOR;
};
#endif
+10 -6
View File
@@ -2,10 +2,6 @@
#include <mods/api.h>
#ifdef __cplusplus
#include <mods/service.hpp>
#endif
#define CONFIG_SERVICE_ID "dev.twilitrealm.dusklight.config"
#define CONFIG_SERVICE_MAJOR 1u
#define CONFIG_SERVICE_MINOR 0u
@@ -100,5 +96,13 @@ typedef struct ConfigService {
ModResult (*unsubscribe)(ModContext* ctx, ConfigSubscriptionHandle handle);
} ConfigService;
MOD_DECLARE_SERVICE(
ConfigService, svc_config, CONFIG_SERVICE_ID, CONFIG_SERVICE_MAJOR, CONFIG_SERVICE_MINOR);
#ifdef __cplusplus
#include "mods/service.hpp"
template <>
struct mods::ServiceTraits<ConfigService> {
static constexpr const char* id = CONFIG_SERVICE_ID;
static constexpr uint16_t major_version = CONFIG_SERVICE_MAJOR;
static constexpr uint16_t minor_version = CONFIG_SERVICE_MINOR;
};
#endif
+10 -5
View File
@@ -2,10 +2,6 @@
#include <mods/api.h>
#ifdef __cplusplus
#include <mods/service.hpp>
#endif
/*
* The mod SDK imports this service automatically for mods built with FEATURES game; service-only
* and asset-only mods do not require it.
@@ -23,4 +19,13 @@ typedef struct GameService {
ServiceHeader header;
} GameService;
MOD_DECLARE_SERVICE(GameService, svc_game, GAME_SERVICE_ID, GAME_SERVICE_MAJOR, GAME_SERVICE_MINOR);
#ifdef __cplusplus
#include <mods/service.hpp>
template <>
struct mods::ServiceTraits<GameService> {
static constexpr const char* id = GAME_SERVICE_ID;
static constexpr uint16_t major_version = GAME_SERVICE_MAJOR;
static constexpr uint16_t minor_version = GAME_SERVICE_MINOR;
};
#endif
+12 -72
View File
@@ -1,11 +1,6 @@
#pragma once
#include <mods/api.h>
#include <mods/svc/window.h>
#ifdef __cplusplus
#include <mods/service.hpp>
#endif
#if !defined(DUSK_BUILDING_GAME) && !defined(DUSK_MOD_FEATURE_WEBGPU)
#error "mods/svc/gfx.h requires add_mod(... FEATURES webgpu)"
@@ -33,7 +28,7 @@
#define GFX_SERVICE_ID "dev.twilitrealm.dusklight.gfx"
#define GFX_SERVICE_MAJOR 1u
#define GFX_SERVICE_MINOR 1u
#define GFX_SERVICE_MINOR 0u
/* Maximum size for push_draw payload */
#define GFX_INLINE_DRAW_PAYLOAD_SIZE 128u
@@ -42,7 +37,6 @@
typedef uint64_t GfxDrawTypeHandle;
typedef uint64_t GfxStageHookHandle;
typedef uint64_t GfxComputeTypeHandle;
typedef uint64_t GfxPresentTargetHandle;
/* A suballocation in one of the shared per-frame streaming buffers. */
typedef struct GfxRange {
@@ -62,13 +56,11 @@ typedef struct GfxDeviceInfo {
WGPUTextureFormat depth_format; /* scene depth target format */
uint32_t sample_count; /* scene pass MSAA sample count */
bool uses_reversed_z; /* true means depth 1.0 is near */
WGPUInstance instance; /* borrowed; added in GfxService 1.1 */
WGPUAdapter adapter; /* borrowed; added in GfxService 1.1 */
} GfxDeviceInfo;
#define GFX_DEVICE_INFO_INIT \
{sizeof(GfxDeviceInfo), NULL, NULL, WGPUTextureFormat_Undefined, WGPUTextureFormat_Undefined, \
1u, false, NULL, NULL}
1u, false}
/*
* Passed to GfxDrawFn on the render worker thread; valid only during the call. The pass pipeline,
@@ -176,48 +168,6 @@ typedef struct GfxComputeTypeDesc {
#define GFX_COMPUTE_TYPE_DESC_INIT {sizeof(GfxComputeTypeDesc), NULL, NULL, NULL}
/*
* Invoked on the render worker while the frame encoder is open. The target texture and view have
* been acquired by the host and are borrowed for the callback. Record all target work on encoder,
* leave no pass open, and do not finish, submit, or present it. The host submits the shared command
* buffer and presents the target after submission. The streaming buffers contain data appended on
* the game thread before push_present.
*/
typedef struct GfxPresentContext {
uint32_t struct_size;
WGPUDevice device;
WGPUQueue queue;
WGPUCommandEncoder encoder;
WGPUTexture target_texture;
WGPUTextureView target_view;
WGPUTextureFormat target_format;
uint32_t target_width;
uint32_t target_height;
WGPUBuffer vertex_buffer;
WGPUBuffer index_buffer;
WGPUBuffer uniform_buffer;
WGPUBuffer storage_buffer;
} GfxPresentContext;
typedef void (*GfxPresentFn)(ModContext* ctx, const GfxPresentContext* present_ctx,
const void* payload, size_t payload_size, void* user_data);
typedef struct GfxPresentTargetDesc {
uint32_t struct_size;
const char* label; /* optional debug label */
uint32_t width; /* required for raw surfaces; ignored for WindowService windows */
uint32_t height;
WGPUTextureUsage usage; /* 0 defaults to RenderAttachment */
WGPUTextureFormat preferred_format;
WGPUCompositeAlphaMode preferred_alpha_mode;
GfxPresentFn render;
void* user_data;
} GfxPresentTargetDesc;
#define GFX_PRESENT_TARGET_DESC_INIT \
{sizeof(GfxPresentTargetDesc), NULL, 0u, 0u, WGPUTextureUsage_None, \
WGPUTextureFormat_Undefined, WGPUCompositeAlphaMode_Auto, NULL, NULL}
typedef struct GfxService {
ServiceHeader header;
@@ -250,25 +200,15 @@ typedef struct GfxService {
ModResult (*resolve_pass)(
ModContext* ctx, const GfxResolveDesc* desc, GfxResolvedTargets* out_targets);
ModResult (*create_pass)(ModContext* ctx, uint32_t width, uint32_t height);
/* Minor version 1 */
ModResult (*register_present_target)(ModContext* ctx, WGPUSurface surface,
const GfxPresentTargetDesc* desc, GfxPresentTargetHandle* out_handle);
ModResult (*register_window_present_target)(ModContext* ctx, WindowHandle window,
const GfxPresentTargetDesc* desc, GfxPresentTargetHandle* out_handle);
/* Raw-surface targets only; WindowService target resizes are managed automatically. */
ModResult (*resize_present_target)(
ModContext* ctx, GfxPresentTargetHandle handle, uint32_t width, uint32_t height);
ModResult (*unregister_present_target)(ModContext* ctx, GfxPresentTargetHandle handle);
/*
* MOD_OK means the task was queued.
* MOD_UNAVAILABLE means no task could be queued now (for example, a window has no pixel size).
* MOD_ERROR means an earlier task found the surface lost or deterministically invalid;
* unregister and recreate the target before pushing again.
*/
ModResult (*push_present)(
ModContext* ctx, GfxPresentTargetHandle handle, const void* payload, size_t payload_size);
} GfxService;
MOD_DECLARE_SERVICE(GfxService, svc_gfx, GFX_SERVICE_ID, GFX_SERVICE_MAJOR, GFX_SERVICE_MINOR);
#ifdef __cplusplus
#include "mods/service.hpp"
template <>
struct mods::ServiceTraits<GfxService> {
static constexpr const char* id = GFX_SERVICE_ID;
static constexpr uint16_t major_version = GFX_SERVICE_MAJOR;
static constexpr uint16_t minor_version = GFX_SERVICE_MINOR;
};
#endif
+13 -8
View File
@@ -2,13 +2,9 @@
#include <mods/api.h>
#ifdef __cplusplus
#include <mods/service.hpp>
#endif
/*
* Intercept game functions by address. Prefer the typed helpers in mods/svc/hook.hpp
* (mods::hook::add_pre/add_post/replace over a &Class::method): they generate the
* Intercept game functions by address. Prefer the typed helpers in mods/hook.hpp
* (hook_add_pre/hook_add_post/hook_replace over a &Class::method): they generate the
* trampoline and hide install/dispatch, which are the low-level primitives those helpers
* build. resolve() maps a symbol name to an address for targets you can't name at compile time
* (file-local statics included).
@@ -50,7 +46,7 @@ typedef enum HookReplacePolicy {
/*
* Hook callbacks. `args` is an array of pointers to the call's arguments (index 0 is `this`
* for member functions); `retval` points at the return slot (NULL for void). Read and write
* them through mods::arg<T> / arg_ref<T> from mods/svc/hook.hpp. `userdata` is the pointer
* them through mods::arg<T> / arg_ref<T> from mods/hook.hpp. `userdata` is the pointer
* from HookOptions. All run on the game thread, in the hooked call's own stack frame.
*/
typedef HookAction (*HookPreFn)(ModContext* ctx, void* args, void* retval, void* userdata);
@@ -118,4 +114,13 @@ typedef struct HookService {
ModContext* ctx, const char* symbol, void** out_addr, HookSymbolFlags* out_flags);
} HookService;
MOD_DECLARE_SERVICE(HookService, svc_hook, HOOK_SERVICE_ID, HOOK_SERVICE_MAJOR, HOOK_SERVICE_MINOR);
#ifdef __cplusplus
#include "mods/service.hpp"
template <>
struct mods::ServiceTraits<HookService> {
static constexpr const char* id = HOOK_SERVICE_ID;
static constexpr uint16_t major_version = HOOK_SERVICE_MAJOR;
static constexpr uint16_t minor_version = HOOK_SERVICE_MINOR;
};
#endif
-242
View File
@@ -1,242 +0,0 @@
#pragma once
#if !defined(DUSK_BUILDING_GAME) && !defined(DUSK_MOD_FEATURE_GAME)
#error "DEFINE_HOOK requires add_mod(... FEATURES game)"
#endif
#include <mods/svc/hook.h>
#include <memory>
#include <type_traits>
namespace mods {
template <class T>
T arg(void* argsRaw, int n) noexcept {
void** args = static_cast<void**>(argsRaw);
return *static_cast<std::add_pointer_t<std::remove_reference_t<T>>>(args[n]);
}
template <class T>
std::remove_reference_t<T>& arg_ref(void* argsRaw, int n) noexcept {
void** args = static_cast<void**>(argsRaw);
return *static_cast<std::add_pointer_t<std::remove_reference_t<T>>>(args[n]);
}
/*
* Trampoline generator + per-target state. Tag makes each hooked target's statics distinct; the
* target address comes from the declaration's metadata record, resolved by the host at mod
* initialization.
*/
template <class Tag, class R, class... A>
struct HookImpl {
static inline R (*g_orig)(A...) = nullptr;
static inline const HookService* hooks = nullptr;
static inline void* target = nullptr;
static bool dispatch_pre(void* args, void* retval) {
if (hooks == nullptr) {
return false;
}
int skipOriginal = 0;
const ModResult result = hooks->dispatch_pre(mod_ctx, target, args, retval, &skipOriginal);
return result == MOD_OK && skipOriginal != 0;
}
static void dispatch_post(void* args, void* retval) {
if (hooks != nullptr) {
hooks->dispatch_post(mod_ctx, target, args, retval);
}
}
static R trampoline(A... args) {
if constexpr (sizeof...(A) == 0) {
if constexpr (std::is_void_v<R>) {
const bool skipOriginal = dispatch_pre(nullptr, nullptr);
if (!skipOriginal) {
g_orig(args...);
}
dispatch_post(nullptr, nullptr);
} else {
R result{};
const bool skipOriginal =
dispatch_pre(nullptr, static_cast<void*>(std::addressof(result)));
if (!skipOriginal) {
result = g_orig(args...);
}
dispatch_post(nullptr, static_cast<void*>(std::addressof(result)));
return result;
}
} else {
void* ptrs[] = {static_cast<void*>(std::addressof(args))...};
if constexpr (std::is_void_v<R>) {
const bool skipOriginal = dispatch_pre(static_cast<void*>(ptrs), nullptr);
if (!skipOriginal) {
g_orig(args...);
}
dispatch_post(static_cast<void*>(ptrs), nullptr);
} else {
R result{};
const bool skipOriginal = dispatch_pre(
static_cast<void*>(ptrs), static_cast<void*>(std::addressof(result)));
if (!skipOriginal) {
result = g_orig(args...);
}
dispatch_post(static_cast<void*>(ptrs), static_cast<void*>(std::addressof(result)));
return result;
}
}
}
};
namespace detail {
template <auto Target>
using TargetTag = std::integral_constant<decltype(Target), Target>;
template <FixedString Name>
struct NameTag {};
} // namespace detail
/*
* Typed base for a hook on a function named at compile time (&daAlink_c::execute, &free_fn).
* Instantiate through DEFINE_HOOK, which pairs it with the metadata record the host resolves.
*/
template <auto Target>
struct Hook;
template <class C, class R, class... A, R (C::*Target)(A...)>
struct Hook<Target> : HookImpl<detail::TargetTag<Target>, R, C*, A...> {};
template <class C, class R, class... A, R (C::*Target)(A...) const>
struct Hook<Target> : HookImpl<detail::TargetTag<Target>, R, const C*, A...> {};
template <class R, class... A, R (*Target)(A...)>
struct Hook<Target> : HookImpl<detail::TargetTag<Target>, R, A...> {};
/*
* Typed base for a hook on a function by its symbol name, for targets you can't name in C++:
* file-local statics, private members, or symbols without a header. The signature is written
* free-style with the receiver first and is *not* compiler-checked. Instantiate through
* DEFINE_HOOK_SYMBOL.
*/
template <FixedString Name, class Sig>
struct NamedHook;
template <FixedString Name, class R, class... A>
struct NamedHook<Name, R(A...)> : HookImpl<detail::NameTag<Name>, R, A...> {};
/*
* Declare a hook target. The declaration emits a metadata record that the host resolves at mod
* initialization. Every hook target must be declared.
*
* DEFINE_HOOK(&daAlink_c::execute, LinkExecute);
* DEFINE_HOOK_SYMBOL("daAlink_hookshotAtHitCallBack",
* void(fopAc_ac_c*, dCcD_GObjInf*, fopAc_ac_c*, dCcD_GObjInf*), HookshotHit);
*
* mods::hook::add_pre<LinkExecute>(on_link_execute);
*
* DEFINE_HOOK_SYMBOL names may be the platform mangled name (dlopen convention, no Mach-O
* leading underscore) or the demangled qualified display name; overloaded display names are
* ambiguous and need the mangled form.
*/
#if defined(__GNUC__) && !defined(__clang__) && defined(__ELF__)
#define DEFINE_HOOK(target, alias) \
MOD_META_RECORD static constinit auto mod_meta_hook_##alias = \
::mods::detail::make_local_hook_record<(target), ::mods::FixedString{#target}>(); \
struct alias : ::mods::Hook<(target)> { \
static void* resolved_target() { return mod_meta_hook_##alias.resolved; } \
}
#else
#define DEFINE_HOOK(target, alias) \
[[maybe_unused]] static const void* const mod_meta_hook_##alias = \
&::mods::detail::HookRecordFor<(target), ::mods::FixedString{#target}>::Holder::record; \
struct alias : ::mods::Hook<(target)> { \
static void* resolved_target() { \
return ::mods::detail::HookRecordFor<(target), \
::mods::FixedString{#target}>::Holder::record.resolved; \
} \
}
#endif
#define DEFINE_HOOK_SYMBOL(name, sig, alias) \
MOD_META_RECORD static constinit auto mod_meta_hook_##alias = \
::mods::detail::make_hook_name_record<::mods::FixedString{name}>(); \
struct alias : ::mods::NamedHook<::mods::FixedString{name}, sig> { \
static void* resolved_target() { return mod_meta_hook_##alias.resolved; } \
}
namespace hook {
template <class Entry>
ModResult install(const HookService* hooks) {
if (hooks == nullptr) {
return MOD_UNAVAILABLE;
}
Entry::hooks = hooks;
if (Entry::target == nullptr) {
void* resolved = Entry::resolved_target();
if (resolved == nullptr) {
return MOD_UNAVAILABLE;
}
Entry::target = resolved;
}
return hooks->install(mod_ctx, Entry::target, reinterpret_cast<void*>(Entry::trampoline),
reinterpret_cast<void**>(&Entry::g_orig));
}
template <class Entry>
ModResult install() {
return install<Entry>(svc_hook);
}
template <class Entry>
ModResult add_pre(
const HookService* hooks, HookPreFn callback, const HookOptions* options = nullptr) {
const ModResult installed = install<Entry>(hooks);
if (installed != MOD_OK) {
return installed;
}
return hooks->add_pre(mod_ctx, Entry::target, callback, options);
}
template <class Entry>
ModResult add_pre(HookPreFn callback, const HookOptions* options = nullptr) {
return add_pre<Entry>(svc_hook, callback, options);
}
template <class Entry>
ModResult add_post(
const HookService* hooks, HookPostFn callback, const HookOptions* options = nullptr) {
const ModResult installed = install<Entry>(hooks);
if (installed != MOD_OK) {
return installed;
}
return hooks->add_post(mod_ctx, Entry::target, callback, options);
}
template <class Entry>
ModResult add_post(HookPostFn callback, const HookOptions* options = nullptr) {
return add_post<Entry>(svc_hook, callback, options);
}
template <class Entry>
ModResult replace(
const HookService* hooks, HookReplaceFn callback, const HookOptions* options = nullptr) {
const ModResult installed = install<Entry>(hooks);
if (installed != MOD_OK) {
return installed;
}
return hooks->replace(mod_ctx, Entry::target, callback, options);
}
template <class Entry>
ModResult replace(HookReplaceFn callback, const HookOptions* options = nullptr) {
return replace<Entry>(svc_hook, callback, options);
}
} // namespace hook
} // namespace mods
+10 -5
View File
@@ -2,10 +2,6 @@
#include <mods/api.h>
#ifdef __cplusplus
#include <mods/service.hpp>
#endif
/*
* The host service: the calling mod's identity and its runtime interface to the loader.
* Always available; every other service can be reached from it.
@@ -107,4 +103,13 @@ typedef struct HostService {
const char* (*native_dir)(ModContext* ctx);
} HostService;
MOD_DECLARE_SERVICE(HostService, svc_host, HOST_SERVICE_ID, HOST_SERVICE_MAJOR, HOST_SERVICE_MINOR);
#ifdef __cplusplus
#include "mods/service.hpp"
template <>
struct mods::ServiceTraits<HostService> {
static constexpr const char* id = HOST_SERVICE_ID;
static constexpr uint16_t major_version = HOST_SERVICE_MAJOR;
static constexpr uint16_t minor_version = HOST_SERVICE_MINOR;
};
#endif
+10 -5
View File
@@ -2,10 +2,6 @@
#include <mods/api.h>
#ifdef __cplusplus
#include <mods/service.hpp>
#endif
/*
* Logging into the game's console and log files. Messages are attributed to the calling mod
* (prefixed with its ID).
@@ -40,4 +36,13 @@ typedef struct LogService {
void (*error)(ModContext* ctx, const char* message);
} LogService;
MOD_DECLARE_SERVICE(LogService, svc_log, LOG_SERVICE_ID, LOG_SERVICE_MAJOR, LOG_SERVICE_MINOR);
#ifdef __cplusplus
#include "mods/service.hpp"
template <>
struct mods::ServiceTraits<LogService> {
static constexpr const char* id = LOG_SERVICE_ID;
static constexpr uint16_t major_version = LOG_SERVICE_MAJOR;
static constexpr uint16_t minor_version = LOG_SERVICE_MINOR;
};
#endif
-46
View File
@@ -1,46 +0,0 @@
#pragma once
#if !defined(DUSK_BUILDING_GAME) && !defined(DUSK_MOD_FEATURE_FMT)
#error "mods/svc/log.hpp requires add_mod(... FEATURES fmt)"
#endif
#include <mods/svc/log.h>
#include <fmt/format.h>
#include <utility>
namespace mods::log {
template <typename... Args>
void write(LogLevel level, fmt::format_string<Args...> formatString, Args&&... args) {
const auto message = fmt::format(formatString, std::forward<Args>(args)...);
svc_log->write(mod_ctx, level, message.c_str());
}
template <typename... Args>
void trace(fmt::format_string<Args...> formatString, Args&&... args) {
write(LOG_LEVEL_TRACE, formatString, std::forward<Args>(args)...);
}
template <typename... Args>
void debug(fmt::format_string<Args...> formatString, Args&&... args) {
write(LOG_LEVEL_DEBUG, formatString, std::forward<Args>(args)...);
}
template <typename... Args>
void info(fmt::format_string<Args...> formatString, Args&&... args) {
write(LOG_LEVEL_INFO, formatString, std::forward<Args>(args)...);
}
template <typename... Args>
void warn(fmt::format_string<Args...> formatString, Args&&... args) {
write(LOG_LEVEL_WARN, formatString, std::forward<Args>(args)...);
}
template <typename... Args>
void error(fmt::format_string<Args...> formatString, Args&&... args) {
write(LOG_LEVEL_ERROR, formatString, std::forward<Args>(args)...);
}
} // namespace mods::log
+10 -6
View File
@@ -2,10 +2,6 @@
#include <mods/api.h>
#ifdef __cplusplus
#include <mods/service.hpp>
#endif
#define OVERLAY_SERVICE_ID "dev.twilitrealm.dusklight.overlay"
#define OVERLAY_SERVICE_MAJOR 1u
#define OVERLAY_SERVICE_MINOR 0u
@@ -50,5 +46,13 @@ typedef struct OverlayService {
ModResult (*remove)(ModContext* ctx, OverlayHandle handle);
} OverlayService;
MOD_DECLARE_SERVICE(
OverlayService, svc_overlay, OVERLAY_SERVICE_ID, OVERLAY_SERVICE_MAJOR, OVERLAY_SERVICE_MINOR);
#ifdef __cplusplus
#include "mods/service.hpp"
template <>
struct mods::ServiceTraits<OverlayService> {
static constexpr const char* id = OVERLAY_SERVICE_ID;
static constexpr uint16_t major_version = OVERLAY_SERVICE_MAJOR;
static constexpr uint16_t minor_version = OVERLAY_SERVICE_MINOR;
};
#endif
+10 -6
View File
@@ -2,10 +2,6 @@
#include <mods/api.h>
#ifdef __cplusplus
#include <mods/service.hpp>
#endif
/*
* Read-only access to the res/ tree of the calling mod's own bundle. Reload serves the new
* bundle's contents. For writable storage, use HostService::mod_dir.
@@ -45,5 +41,13 @@ typedef struct ResourceService {
void (*free)(ModContext* ctx, ResourceBuffer* buffer);
} ResourceService;
MOD_DECLARE_SERVICE(ResourceService, svc_resource, RESOURCE_SERVICE_ID, RESOURCE_SERVICE_MAJOR,
RESOURCE_SERVICE_MINOR);
#ifdef __cplusplus
#include "mods/service.hpp"
template <>
struct mods::ServiceTraits<ResourceService> {
static constexpr const char* id = RESOURCE_SERVICE_ID;
static constexpr uint16_t major_version = RESOURCE_SERVICE_MAJOR;
static constexpr uint16_t minor_version = RESOURCE_SERVICE_MINOR;
};
#endif
+12 -8
View File
@@ -2,10 +2,6 @@
#include <mods/api.h>
#ifdef __cplusplus
#include <mods/service.hpp>
#endif
#define TEXTURE_SERVICE_ID "dev.twilitrealm.dusklight.texture"
#define TEXTURE_SERVICE_MAJOR 1u
#define TEXTURE_SERVICE_MINOR 0u
@@ -74,12 +70,20 @@ typedef struct TextureService {
* "tex1_{w}x{h}_{hash}_{fmt}.dds"); "_mipN" sidecars next to it are picked up automatically.
* The file is decoded lazily on first use by the renderer.
*/
ModResult (*register_file)(
ModContext* ctx, const char* bundle_path, TextureReplacementHandle* out_handle);
ModResult (*register_file)(ModContext* ctx, const char* bundle_path,
TextureReplacementHandle* out_handle);
/* Remove a replacement previously registered by the calling mod. */
ModResult (*unregister)(ModContext* ctx, TextureReplacementHandle handle);
} TextureService;
MOD_DECLARE_SERVICE(
TextureService, svc_texture, TEXTURE_SERVICE_ID, TEXTURE_SERVICE_MAJOR, TEXTURE_SERVICE_MINOR);
#ifdef __cplusplus
#include "mods/service.hpp"
template <>
struct mods::ServiceTraits<TextureService> {
static constexpr const char* id = TEXTURE_SERVICE_ID;
static constexpr uint16_t major_version = TEXTURE_SERVICE_MAJOR;
static constexpr uint16_t minor_version = TEXTURE_SERVICE_MINOR;
};
#endif
+13 -24
View File
@@ -3,17 +3,13 @@
#include <mods/api.h>
#include <mods/svc/config.h>
#ifdef __cplusplus
#include <mods/service.hpp>
#endif
#define UI_SERVICE_ID "dev.twilitrealm.dusklight.ui"
#define UI_SERVICE_MAJOR 1u
#define UI_SERVICE_MINOR 1u
#define UI_SERVICE_MINOR 0u
/*
* UI primitives: a panel inside the host Mods window, mod-owned windows, dialogs, toasts,
* scoped RCSS stylesheets and menu bar tabs.
* UI primitives: a panel inside the host Mods window, mod-owned windows, dialogs, scoped
* RCSS stylesheets and menu bar tabs.
*
* All calls must be made on the game thread from mod callbacks (initialize, update, hooks, or UI
* callbacks). Handles are opaque, generation-checked ids; a stale or unknown handle fails with
@@ -212,19 +208,6 @@ typedef struct UiMenuTabDesc {
#define UI_MENU_TAB_DESC_INIT {sizeof(UiMenuTabDesc), NULL, NULL, NULL}
typedef struct UiToastDesc {
uint32_t struct_size;
/* Optional RCSS class, such as "warning" or a custom mod-defined type. */
const char* type;
/* Optional RML. At least one of title_rml or body_rml must be non-empty. */
const char* title_rml;
const char* body_rml;
/* How long the toast remains open; 0 uses the default of 5000 ms. */
uint32_t duration_ms;
} UiToastDesc;
#define UI_TOAST_DESC_INIT {sizeof(UiToastDesc), NULL, NULL, NULL, 0u}
typedef struct UiService {
ServiceHeader header;
@@ -288,9 +271,15 @@ typedef struct UiService {
ModResult (*register_menu_tab)(
ModContext* ctx, const UiMenuTabDesc* desc, UiMenuTabHandle* out_tab);
ModResult (*unregister_menu_tab)(ModContext* ctx, UiMenuTabHandle tab);
/* Enqueue a toast notification. */
ModResult (*push_toast)(ModContext* ctx, const UiToastDesc* desc);
} UiService;
MOD_DECLARE_SERVICE(UiService, svc_ui, UI_SERVICE_ID, UI_SERVICE_MAJOR, UI_SERVICE_MINOR);
#ifdef __cplusplus
#include "mods/service.hpp"
template <>
struct mods::ServiceTraits<UiService> {
static constexpr const char* id = UI_SERVICE_ID;
static constexpr uint16_t major_version = UI_SERVICE_MAJOR;
static constexpr uint16_t minor_version = UI_SERVICE_MINOR;
};
#endif
-103
View File
@@ -1,103 +0,0 @@
#pragma once
#include <mods/api.h>
#ifdef __cplusplus
#include <mods/service.hpp>
#endif
#include <limits.h>
#define WINDOW_SERVICE_ID "dev.twilitrealm.dusklight.window"
#define WINDOW_SERVICE_MAJOR 1u
#define WINDOW_SERVICE_MINOR 0u
#define WINDOW_POSITION_UNDEFINED INT32_MIN
typedef uint64_t WindowHandle;
typedef enum WindowFlags {
WINDOW_FLAG_NONE = 0u,
WINDOW_FLAG_RESIZABLE = 1u << 0u,
WINDOW_FLAG_HIDDEN = 1u << 1u,
WINDOW_FLAG_BORDERLESS = 1u << 2u,
WINDOW_FLAG_ALWAYS_ON_TOP = 1u << 3u,
WINDOW_FLAG_TRANSPARENT = 1u << 4u,
} WindowFlags;
typedef enum WindowEventType {
WINDOW_EVENT_CLOSE_REQUESTED = 0,
WINDOW_EVENT_RESIZED = 1,
WINDOW_EVENT_MOVED = 2,
WINDOW_EVENT_FOCUS_GAINED = 3,
WINDOW_EVENT_FOCUS_LOST = 4,
WINDOW_EVENT_SHOWN = 5,
WINDOW_EVENT_HIDDEN = 6,
} WindowEventType;
typedef struct WindowEvent {
uint32_t struct_size;
WindowEventType type;
int32_t x;
int32_t y;
uint32_t width;
uint32_t height;
uint32_t pixel_width;
uint32_t pixel_height;
float display_scale;
} WindowEvent;
typedef void (*WindowEventFn)(
ModContext* ctx, WindowHandle window, const WindowEvent* event, void* user_data);
typedef struct WindowDesc {
uint32_t struct_size;
const char* title;
uint32_t width;
uint32_t height;
int32_t x;
int32_t y;
uint32_t flags;
WindowEventFn on_event;
void* user_data;
} WindowDesc;
#define WINDOW_DESC_INIT \
{sizeof(WindowDesc), NULL, 640u, 480u, WINDOW_POSITION_UNDEFINED, WINDOW_POSITION_UNDEFINED, \
WINDOW_FLAG_RESIZABLE | WINDOW_FLAG_HIDDEN, NULL, NULL}
typedef struct WindowInfo {
uint32_t struct_size;
int32_t x;
int32_t y;
uint32_t width;
uint32_t height;
uint32_t pixel_width;
uint32_t pixel_height;
float display_scale;
bool visible;
bool focused;
} WindowInfo;
#define WINDOW_INFO_INIT {sizeof(WindowInfo), 0, 0, 0u, 0u, 0u, 0u, 1.0f, false, false}
/*
* Auxiliary native windows. All functions and callbacks run on the game thread. Window close
* events are requests; the window remains alive until destroy_window is called. Any graphics
* present target attached to a window must be unregistered before the window can be destroyed;
* at most one present target may be attached to a window at a time.
*/
typedef struct WindowService {
ServiceHeader header;
ModResult (*create_window)(ModContext* ctx, const WindowDesc* desc, WindowHandle* out_window);
ModResult (*destroy_window)(ModContext* ctx, WindowHandle window);
ModResult (*show_window)(ModContext* ctx, WindowHandle window);
ModResult (*hide_window)(ModContext* ctx, WindowHandle window);
ModResult (*set_title)(ModContext* ctx, WindowHandle window, const char* title);
ModResult (*set_size)(ModContext* ctx, WindowHandle window, uint32_t width, uint32_t height);
ModResult (*get_info)(ModContext* ctx, WindowHandle window, WindowInfo* out_info);
} WindowService;
MOD_DECLARE_SERVICE(
WindowService, svc_window, WINDOW_SERVICE_ID, WINDOW_SERVICE_MAJOR, WINDOW_SERVICE_MINOR);
+134 -134
View File
@@ -36,14 +36,14 @@ Z2Audible::Z2Audible(const JGeometry::TVec3<f32>& pos, const JGeometry::TVec3<f3
mParam.field_0x0.raw = 0xFFFFFFFF;
mAbsPos.init(&mPos, pos, param_1);
for (int i = 0; i < Z2_AUDIO_PLAYERS; i++) {
for (int i = 0; i < 1; i++) {
if ((channel & (1 << i)) == 0) {
mChannel[i].init();
}
}
for (int i = 0; i < Z2_AUDIO_PLAYERS; i = i + 1) {
mMicDistances[i] = 0.0f;
for (int i = 0; i < 1; i = i + 1) {
field_0x64[i] = 0.0f;
}
}
@@ -57,18 +57,18 @@ void Z2Audible::calc() {
JASSoundParams* Z2Audible::getOuterParams(int index) {
JUT_ASSERT(80, index >= 0);
JUT_ASSERT(81, index < 1); // Z2_AUDIO_PLAYERS
JUT_ASSERT(81, index < 1);
return &mChannel[index].mParams;
}
void Z2Audible::setOuterParams(const JASSoundParams& outParams, const JASSoundParams& inParams,
int index) {
JUT_ASSERT(89, index >= 0);
JUT_ASSERT(90, index < 1); // Z2_AUDIO_PLAYERS
JUT_ASSERT(90, index < 1);
Z2AudibleChannel* channel = &mChannel[index];
u8 volSomething = (mParam.field_0x0.half.f1 & SOUND_VOL_SOMETHING_MASK_SHIFTED) >> 8;
if (volSomething == 0) {
u8 iStack_94 = (mParam.field_0x0.half.f1 & 0xf00) >> 8;
if (iStack_94 == 0) {
channel->mParams.combine(outParams, inParams);
return;
}
@@ -91,7 +91,7 @@ void Z2Audible::setOuterParams(const JASSoundParams& outParams, const JASSoundPa
f32 dVar9 = inParams.mVolume * local_b8.length();
f32 dVar10 = 1.0f;
f32 dVar12 = Z2Calc::linearTransform(volSomething, 0.0f, 15.0f, 1.0f, 0.3f, true);
f32 dVar12 = Z2Calc::linearTransform(iStack_94, 0.0f, 15.0f, 1.0f, 0.3f, true);
if (inParams.mVolume > dVar12 && dVar9 > 0.001f) {
dVar10 = Z2Calc::getParamByExp(dVar9, 0.3f, 0.001f, 0.1f, dVar12, 1.0f,
Z2Calc::CURVE_POSITIVE);
@@ -141,18 +141,18 @@ void Z2Audible::setOuterParams(const JASSoundParams& outParams, const JASSoundPa
Z2AudibleChannel* Z2Audible::getChannel(int index) {
JUT_ASSERT(220, index >= 0);
JUT_ASSERT(221, index < 1); // Z2_AUDIO_PLAYERS
JUT_ASSERT(221, index < 1);
return &mChannel[index];
}
u32 Z2Audible::getDistVolBit() {
u16 uVar1 = getAudibleParam()->field_0x0.half.f1;
if (uVar1 != 0) {
if ((uVar1 & SOUND_VOL_DIST_BIT_MASK_SHIFTED) != 0) {
return uVar1 & SOUND_VOL_DIST_BIT_MASK_SHIFTED;
if ((uVar1 & 7) != 0) {
return uVar1 & 7;
}
if ((uVar1 & SOUND_VOL_DIST_BIT_2_MASK_SHIFTED) != 0) {
return ((int)(uVar1 & SOUND_VOL_DIST_BIT_2_MASK_SHIFTED) >> 4) + 7;
if ((uVar1 & 0x70) != 0) {
return ((int)(uVar1 & 0x70) >> 4) + 7;
}
}
@@ -166,15 +166,15 @@ Z2Audience3DSetting::Z2Audience3DSetting() {
}
void Z2Audience3DSetting::init() {
mMinDistanceVolume = Z2Param::MIN_DISTANCE_VOLUME;
mDolbyBehindDistanceMax = Z2Param::DOLBY_BEHIND_DISTANCE_MAX;
mDolbyFrontDistanceMax = Z2Param::DOLBY_FLONT_DISTANCE_MAX;
mMaxDistanceFxMix = Z2Param::DISTANCE_FX_PARAM;
mMinDistanceFxMix = 0.0f;
mDolbyCenterValue = Z2Param::DOLBY_CENTER_VALUE;
mPanFactor = 0.5f;
mMaxDistancePriority = 0xff;
mSonicSpeed = Z2Param::SONIC_SPEED;
field_0x40 = Z2Param::MIN_DISTANCE_VOLUME;
field_0x48 = Z2Param::DOLBY_BEHIND_DISTANCE_MAX;
field_0x44 = Z2Param::DOLBY_FLONT_DISTANCE_MAX;
field_0x54 = Z2Param::DISTANCE_FX_PARAM;
field_0x50 = 0.0f;
field_0x4c = Z2Param::DOLBY_CENTER_VALUE;
field_0x58 = 0.5f;
field_0x64 = 0xff;
field_0x5c = Z2Param::SONIC_SPEED;
field_0x60 = 1.5f;
initVolumeDist();
@@ -184,8 +184,8 @@ void Z2Audience3DSetting::init() {
void Z2Audience3DSetting::initVolumeDist() {
if (mVolumeDistInit) return;
mDistanceMaxes[0] = Z2Param::DISTANCE_MAX;
mMaxVolumeDistance = Z2Param::MAX_VOLUME_DISTANCE;
field_0x0[0] = Z2Param::DISTANCE_MAX;
field_0x3c = Z2Param::MAX_VOLUME_DISTANCE;
calcVolumeFactorAll();
calcPriorityFactorAll();
@@ -197,12 +197,12 @@ void Z2Audience3DSetting::initVolumeDist() {
static f32 cNearFarRatio = Z2Param::MAX_VOLUME_DISTANCE / Z2Param::DISTANCE_MAX;
void Z2Audience3DSetting::updateVolumeDist(f32 param_0) {
mDistanceMaxes[0] = param_0;
field_0x0[0] = param_0;
if (param_0 > Z2Param::DISTANCE_MAX) {
mMaxVolumeDistance = cNearFarRatio * param_0;
field_0x3c = cNearFarRatio * param_0;
} else {
mMaxVolumeDistance = Z2Param::MAX_VOLUME_DISTANCE;
field_0x3c = Z2Param::MAX_VOLUME_DISTANCE;
}
calcVolumeFactorAll();
@@ -214,29 +214,29 @@ void Z2Audience3DSetting::updateVolumeDist(f32 param_0) {
void Z2Audience3DSetting::initDolbyDist() {
if (!mDolbyDistInit) {
mDolbyFrontDistanceMax = Z2Param::DOLBY_FLONT_DISTANCE_MAX;
mDolbyBehindDistanceMax = Z2Param::DOLBY_BEHIND_DISTANCE_MAX;
field_0x68 = -mDolbyCenterValue / mDolbyFrontDistanceMax;
field_0x6c = (1.0f - mDolbyCenterValue) / mDolbyBehindDistanceMax;
field_0x44 = Z2Param::DOLBY_FLONT_DISTANCE_MAX;
field_0x48 = Z2Param::DOLBY_BEHIND_DISTANCE_MAX;
field_0x68 = -field_0x4c / field_0x44;
field_0x6c = (1.0f - field_0x4c) / field_0x48;
mDolbyDistInit = true;
}
}
void Z2Audience3DSetting::updateDolbyDist(f32 param_0, f32 param_1) {
if (param_0 > -1.0f * Z2Param::DOLBY_FLONT_DISTANCE_MAX) {
mDolbyFrontDistanceMax = -1.0f * param_0;
field_0x44 = -1.0f * param_0;
} else {
mDolbyFrontDistanceMax = Z2Param::DOLBY_FLONT_DISTANCE_MAX;
field_0x44 = Z2Param::DOLBY_FLONT_DISTANCE_MAX;
}
if (param_1 < 2.0f * mDolbyFrontDistanceMax) {
param_1 = 2.0f * mDolbyFrontDistanceMax;
if (param_1 < 2.0f * field_0x44) {
param_1 = 2.0f * field_0x44;
}
if (param_1 > Z2Param::DOLBY_BEHIND_DISTANCE_MAX) {
mDolbyBehindDistanceMax = param_1;
field_0x48 = param_1;
} else {
mDolbyBehindDistanceMax = Z2Param::DOLBY_BEHIND_DISTANCE_MAX;
field_0x48 = Z2Param::DOLBY_BEHIND_DISTANCE_MAX;
}
mDolbyDistInit = false;
@@ -254,28 +254,28 @@ Z2AudioCamera::Z2AudioCamera() {
}
void Z2AudioCamera::init() {
JGeometry::TPosition3f32 viewMatrix;
viewMatrix.identity();
JGeometry::TPosition3f32 aTStack_38;
aTStack_38.identity();
JGeometry::TVec3<f32> VStack_44;
VStack_44.set(100000.0f, 100000.0f, 100000.0f);
setCameraState(viewMatrix, *(Vec*)&VStack_44, true);
setCameraState(aTStack_38, *(Vec*)&VStack_44, true);
}
void Z2AudioCamera::setCameraState(f32 const (*viewMatrix)[4], Vec& pos, bool initial) {
mViewMatrix.set(viewMatrix);
if (initial) {
void Z2AudioCamera::setCameraState(f32 const (*param_0)[4], Vec& pos, bool param_2) {
field_0x0.set(param_0);
if (param_2) {
mPos.set(pos);
mLastPos.set(mPos);
field_0x48.set(mPos);
mVel.zero();
} else {
mLastPos.set(mPos);
field_0x48.set(mPos);
mPos.set(pos);
mVel.sub(mPos, mLastPos);
mVel.sub(mPos, field_0x48);
}
}
void Z2AudioCamera::setCameraState(f32 (*viewMatrix)[4], Vec& pos, Vec& param_2, f32 param_3,
f32 param_4, bool param_5, bool initial) {
void Z2AudioCamera::setCameraState(f32 (*param_0)[4], Vec& pos, Vec& param_2, f32 param_3,
f32 param_4, bool param_5, bool param_6) {
JGeometry::TVec3<f32> aTStack_c0;
VECSubtract(&param_2, &pos, (Vec*)&aTStack_c0);
mCamDist = aTStack_c0.length();
@@ -312,7 +312,7 @@ void Z2AudioCamera::setCameraState(f32 (*viewMatrix)[4], Vec& pos, Vec& param_2,
Z2GetAudience()->getSetting()->updateDolbyDist(mCamDist, mCamDist);
}
} else {
Vec aTStack_cc = {viewMatrix[0][0], viewMatrix[0][1], viewMatrix[0][2]};
Vec aTStack_cc = {param_0[0][0], param_0[0][1], param_0[0][2]};
Mtx rotMtx;
MTXRotAxisRad(rotMtx, &aTStack_cc, (M_PI / 180.0f) * (-1.0f * dVar10));
JGeometry::TVec3<f32> aTStack_d8;
@@ -324,7 +324,7 @@ void Z2AudioCamera::setCameraState(f32 (*viewMatrix)[4], Vec& pos, Vec& param_2,
}
}
setCameraState(viewMatrix, pos, initial);
setCameraState(param_0, pos, param_6);
}
void Z2AudioCamera::convertAbsToRel(Z2Audible* audible, int channelNum) {
@@ -337,17 +337,17 @@ void Z2AudioCamera::convertAbsToRel(Z2Audible* audible, int channelNum) {
return;
}
Z2AudibleRelPos* relPos = &channel->mRelPos;
MTXMultVec(mViewMatrix, (Vec*)&audible->getPos(), (Vec*)&relPos->mCameraRelative);
relPos->mTrueDistance = relPos->mCameraRelative.length();
Z2AudibleRelPos* relPos = &channel->field_0x14;
MTXMultVec(field_0x0, (Vec*)&audible->getPos(), (Vec*)&relPos->field_0x00);
relPos->field_0xC = relPos->field_0x00.length();
JGeometry::TVec3<f32> aTStack_38(relPos->mCameraRelative);
JGeometry::TVec3<f32> aTStack_38(relPos->field_0x00);
aTStack_38.z += mVolCenterZ;
relPos->mCenterDistance = aTStack_38.length();
relPos->field_0x10 = aTStack_38.length();
}
bool Z2AudioCamera::convertAbsToRel(Vec& src, Vec* dst) const {
MTXMultVec(mViewMatrix, &src, dst);
MTXMultVec(field_0x0, &src, dst);
return isInSight(*dst);
}
@@ -395,7 +395,7 @@ void Z2SpotMic::calcVolumeFactor(int camID) {
void Z2SpotMic::setMicState(Z2AudioCamera* camera, int camID) {
JUT_ASSERT(622, camID >= 0);
JUT_ASSERT(623, camID < 1); // Z2_AUDIO_PLAYERS
JUT_ASSERT(623, camID < 1);
if (mMicOn && mPosPtr != 0 && camera != NULL) {
clearMicState(camID);
@@ -406,8 +406,8 @@ void Z2SpotMic::setMicState(Z2AudioCamera* camera, int camID) {
aVStack_58.z += camera->getVolCenterZ();
f32 dVar10 = aVStack_58.length();
f32 dVar11 = Z2GetAudience()->getSetting()->mDistanceMaxes[0];
f32 dVar12 = Z2GetAudience()->getSetting()->mMaxVolumeDistance;
f32 dVar11 = Z2GetAudience()->getSetting()->field_0x0[0];
f32 dVar12 = Z2GetAudience()->getSetting()->field_0x3c;
if (dVar10 > dVar11) {
field_0x18[camID] = field_0xc;
} else {
@@ -443,21 +443,21 @@ f32 Z2SpotMic::calcMicDist(Z2Audible* audible) {
return aTStack_1c.length();
}
u32 Z2SpotMic::calcMicPriority(f32 micDistance) {
if (micDistance > field_0x4) {
return Z2GetAudience()->getSetting()->mMaxDistancePriority;
u32 Z2SpotMic::calcMicPriority(f32 param_0) {
if (param_0 > field_0x4) {
return Z2GetAudience()->getSetting()->field_0x64;
}
if (micDistance < field_0x0) {
if (param_0 < field_0x0) {
return 0;
}
return field_0x1c * (micDistance - field_0x0);
return field_0x1c * (param_0 - field_0x0);
}
f32 Z2SpotMic::calcMicVolume(f32 param_0, int camID, f32 param_2) {
JUT_ASSERT(687, camID >= 0);
JUT_ASSERT(688, camID < 1); // Z2_AUDIO_PLAYERS
JUT_ASSERT(688, camID < 1);
if (mMicOn == false) {
return param_2;
@@ -497,7 +497,7 @@ f32 Z2SpotMic::calcMicVolume(f32 param_0, int camID, f32 param_2) {
}
Z2Audience::Z2Audience() : JASGlobalInstance<Z2Audience>(true), field_0x4(1.0f), field_0x8(0x7f) {
mNumPlayers = Z2_AUDIO_PLAYERS;
mNumPlayers = 1;
mUsingOffMicVol = false;
mAudioCamera[0].init();
mAudioCamera[0].setMainCamera(true);
@@ -512,11 +512,11 @@ bool Z2Audience::isActive() const {
return Z2Audible::getTotalMemCount() != Z2Audible::getFreeMemCount();
}
void Z2Audience::setAudioCamera(f32 (*viewMatrix)[4], Vec& pos, Vec& param_2, f32 param_3,
f32 param_4, bool param_5, int camID, bool initial) {
void Z2Audience::setAudioCamera(f32 (*param_0)[4], Vec& pos, Vec& param_2, f32 param_3,
f32 param_4, bool param_5, int camID, bool param_7) {
JUT_ASSERT(687, camID >= 0);
JUT_ASSERT(688, camID < mNumPlayers);
mAudioCamera[camID].setCameraState(viewMatrix, pos, param_2, param_3, param_4, param_5, initial);
mAudioCamera[camID].setCameraState(param_0, pos, param_2, param_3, param_4, param_5, param_7);
mLinkMic->setMicState(&mAudioCamera[camID], camID);
}
@@ -529,7 +529,7 @@ JAIAudible* Z2Audience::newAudible(const JGeometry::TVec3<f32>& pos, JAISoundID
}
JAUAudibleParam params = Z2GetSoundInfo()->getAudibleSwFull(soundID);
bool x = params.field_0x0.bytes.mDopplerPower != 0;
bool x = params.field_0x0.bytes.b0_0 != 0;
Z2Audible* audible = JKR_NEW Z2Audible(pos, param_2, channelNum, x);
if (audible == NULL) {
@@ -543,13 +543,13 @@ JAIAudible* Z2Audience::newAudible(const JGeometry::TVec3<f32>& pos, JAISoundID
if (channel != NULL) {
u32 distVolBit = audible->getDistVolBit();
mAudioCamera[i].convertAbsToRel(audible, i);
calcDeltaPriority_(channel->mRelPos.mCenterDistance, distVolBit, false);
calcDeltaPriority_(channel->field_0x14.field_0x10, distVolBit, false);
}
}
for (int i = 0; i < Z2_AUDIO_PLAYERS; i++) {
for (int i = 0; i < 1; i++) {
if (mSpotMic[i].isOn()) {
audible->mMicDistances[i] = mSpotMic[i].calcMicDist(audible);
audible->field_0x64[i] = mSpotMic[i].calcMicDist(audible);
}
}
@@ -569,7 +569,7 @@ Z2Audible::~Z2Audible() {}
u32 Z2Audience::calcPriority(JAIAudible* audible) {
Z2Audible* Z2audible = (Z2Audible*)audible;
if (!Z2audible->getAudibleParam()->field_0x0.bytes.mCalculatePriority) {
if (!Z2audible->getAudibleParam()->field_0x0.bytes.b0_4) {
for (int i = 0; i < mNumPlayers; i++) {
mAudioCamera[i].convertAbsToRel(Z2audible, i);
}
@@ -584,17 +584,17 @@ u32 Z2Audience::calcPriority(JAIAudible* audible) {
mAudioCamera[i].convertAbsToRel(Z2audible, i);
u32 distvolBit = Z2audible->getDistVolBit();
const JAUAudibleParam* puVar1 = Z2audible->getAudibleParam();
deltaPriority[i] = calcDeltaPriority_(channel->mRelPos.mCenterDistance, distvolBit, puVar1->field_0x0.bytes.mCullAtMaxDistance);
deltaPriority[i] = calcDeltaPriority_(channel->field_0x14.field_0x10, distvolBit, puVar1->field_0x0.bytes.b0_7);
if (deltaPriority[i] < rv) {
rv = deltaPriority[i];
}
}
}
for (int i = 0; i < Z2_AUDIO_PLAYERS; i++) {
for (int i = 0; i < 1; i++) {
if (mSpotMic[i].isOn()) {
Z2audible->mMicDistances[i] = mSpotMic[i].calcMicDist(Z2audible);
u32 micPriority = mSpotMic[i].calcMicPriority(Z2audible->mMicDistances[i]);
Z2audible->field_0x64[i] = mSpotMic[i].calcMicDist(Z2audible);
u32 micPriority = mSpotMic[i].calcMicPriority(Z2audible->field_0x64[i]);
if (micPriority < rv) {
rv = micPriority;
}
@@ -619,31 +619,31 @@ void Z2Audience::mixChannelOut(const JASSoundParams& outParams, JAIAudible* audi
return;
}
JASSoundParams calcParams;
JASSoundParams local_60;
u32 distVolBit = Z2audible->getDistVolBit();
if (Z2audible->getAudibleParam()->field_0x0.bytes.mCalcDistanceVolume) {
calcParams.mVolume = calcVolume_(channel->mRelPos.mCenterDistance, distVolBit);
f32 dVar9 = mLinkMic->calcMicVolume(Z2audible->mMicDistances[0], channelNum, calcParams.mVolume);
if (Z2audible->getAudibleParam()->field_0x0.bytes.b0_5) {
local_60.mVolume = calcVolume_(channel->field_0x14.field_0x10, distVolBit);
f32 dVar9 = mLinkMic->calcMicVolume(Z2audible->field_0x64[0], channelNum, local_60.mVolume);
if (dVar9 < 0.0f) {
dVar9 = calcOffMicSound(calcParams.mVolume);
dVar9 = calcOffMicSound(local_60.mVolume);
}
calcParams.mVolume = dVar9;
local_60.mVolume = dVar9;
JAUAudibleParam* params = Z2audible->getAudibleParam();
if ((params->field_0x0.bytes.mClampMinVolume & 8) && (calcParams.mVolume <= 0.2f)) {
calcParams.mVolume = 0.2f;
if ((params->field_0x0.bytes.b1_2_7 & 8) && (local_60.mVolume <= 0.2f)) {
local_60.mVolume = 0.2f;
}
} else {
calcParams.mVolume = 1.0f;
local_60.mVolume = 1.0f;
}
if (Z2audible->getAudibleParam()->field_0x0.bytes.mCalcDolby && mNumPlayers == 1) {
calcParams.mDolby = calcRelPosDolby(*(Vec*)&channel->mRelPos.mCameraRelative, channelNum);
if (Z2audible->getAudibleParam()->field_0x0.bytes.b1_1 && mNumPlayers == 1) {
local_60.mDolby = calcRelPosDolby(*(Vec*)&channel->field_0x14.field_0x00, channelNum);
} else {
calcParams.mDolby = 0.5f;
local_60.mDolby = 0.5f;
}
if (Z2audible->getAudibleParam()->field_0x0.bytes.mCalcPan) {
if (Z2audible->getAudibleParam()->field_0x0.bytes.b1_0) {
if (mNumPlayers > 2) {
f32 fVar1;
if (channelNum & 1) {
@@ -651,24 +651,24 @@ void Z2Audience::mixChannelOut(const JASSoundParams& outParams, JAIAudible* audi
} else {
fVar1 = 0.0f;
}
calcParams.mPan = fVar1;
local_60.mPan = fVar1;
} else {
calcParams.mPan = calcRelPosPan(*(Vec*)&channel->mRelPos.mCameraRelative, channelNum);
local_60.mPan = calcRelPosPan(*(Vec*)&channel->field_0x14.field_0x00, channelNum);
}
} else {
calcParams.mPan = 0.5f;
local_60.mPan = 0.5f;
}
calcParams.mPitch = calcPitch_(channel, Z2audible, &mAudioCamera[channelNum]);
f32 fxMix;
if (Z2audible->getAudibleParam()->field_0x0.bytes.mCalcFxMix) {
fxMix = calcFxMix_(channel->mRelPos.mTrueDistance, distVolBit);
local_60.mPitch = calcPitch_(channel, Z2audible, &mAudioCamera[channelNum]);
f32 dVar9;
if (Z2audible->getAudibleParam()->field_0x0.bytes.b0_6) {
dVar9 = calcFxMix_(channel->field_0x14.field_0xC, distVolBit);
} else {
fxMix = 0.0f;
dVar9 = 0.0f;
}
calcParams.mFxMix = fxMix;
calcParams.clamp();
Z2audible->setOuterParams(outParams, calcParams, channelNum);
local_60.mFxMix = dVar9;
local_60.clamp();
Z2audible->setOuterParams(outParams, local_60, channelNum);
}
@@ -688,18 +688,18 @@ f32 Z2Audience::calcRelPosVolume(const Vec& param_0, f32 param_1, int camID) {
aTStack_3c.y *= 1.5f;
f32 len = aTStack_3c.length();
if (len > mSetting.mDistanceMaxes[0] * param_1) {
return mSetting.mMinDistanceVolume;
if (len > mSetting.field_0x0[0] * param_1) {
return mSetting.field_0x40;
}
if (len < mSetting.mMaxVolumeDistance) {
if (len < mSetting.field_0x3c) {
return 1.0f;
}
return JGeometry::TUtil<f32>::clamp(
1.0f + ((mSetting.mMinDistanceVolume - 1.0f) /
((mSetting.mDistanceMaxes[0] * param_1) - mSetting.mMaxVolumeDistance)) *
(len - mSetting.mMaxVolumeDistance),
1.0f + ((mSetting.field_0x40 - 1.0f) /
((mSetting.field_0x0[0] * param_1) - mSetting.field_0x3c)) *
(len - mSetting.field_0x3c),
0.0f, 1.0f);
}
@@ -717,7 +717,7 @@ f32 Z2Audience::calcRelPosPan(const Vec& param_0, int camID) {
return 0.5f;
}
dVar6 = (0.5f + mSetting.mPanFactor * (local_54.x / dVar6));
dVar6 = (0.5f + mSetting.field_0x58 * (local_54.x / dVar6));
if (local_54.z <= 0.0f) {
f32 fovySin = mAudioCamera[camID].getFovySin();
if (dVar6 < 0.5f) {
@@ -757,52 +757,52 @@ f32 Z2Audience::calcRelPosDolby(const Vec& param_0, int camID) {
return 0.5f - 0.5f * cosf(t * static_cast<f32>(M_PI));
}
#endif
if (fVar1 > mSetting.mDolbyBehindDistanceMax) {
if (fVar1 > mSetting.field_0x48) {
return 1.0f;
}
if (fVar1 < mSetting.mDolbyFrontDistanceMax) {
if (fVar1 < mSetting.field_0x44) {
return 0.0f;
}
if (fVar1 < 0.0f) {
return Z2Calc::getParamByExp(
fVar1, mSetting.mDolbyFrontDistanceMax, 0.0f,
fVar1, mSetting.field_0x44, 0.0f,
0.3f, 0.0f,
mSetting.mDolbyCenterValue, Z2Calc::CURVE_POSITIVE);
mSetting.field_0x4c, Z2Calc::CURVE_POSITIVE);
}
return Z2Calc::getParamByExp(
fVar1, 0.0f, mSetting.mDolbyBehindDistanceMax,
0.3f, mSetting.mDolbyCenterValue,
fVar1, 0.0f, mSetting.field_0x48,
0.3f, mSetting.field_0x4c,
1.0f, Z2Calc::CURVE_NEGATIVE);
}
f32 Z2Audience::calcVolume_(f32 param_0, int distVolBit) const {
if (param_0 > mSetting.mDistanceMaxes[distVolBit]) {
return mSetting.mMinDistanceVolume;
if (param_0 > mSetting.field_0x0[distVolBit]) {
return mSetting.field_0x40;
}
if (param_0 < mSetting.mMaxVolumeDistance) {
if (param_0 < mSetting.field_0x3c) {
return 1.0f;
}
return JGeometry::TUtil<f32>::clamp((mSetting.mVolumeFactor[distVolBit] * (param_0 - mSetting.mMaxVolumeDistance)) + 1.0f, 0.0f, 1.0f);
return JGeometry::TUtil<f32>::clamp((mSetting.field_0x70[distVolBit] * (param_0 - mSetting.field_0x3c)) + 1.0f, 0.0f, 1.0f);
}
u32 Z2Audience::calcDeltaPriority_(f32 distance, int distVolBit, bool cullMaxDistance) const {
if (distance > mSetting.mDistanceMaxes[distVolBit]) {
if (cullMaxDistance) {
u32 Z2Audience::calcDeltaPriority_(f32 param_0, int distVolBit, bool param_2) const {
if (param_0 > mSetting.field_0x0[distVolBit]) {
if (param_2) {
return -1;
}
return mSetting.mMaxDistancePriority;
return mSetting.field_0x64;
}
if (distance < mSetting.mMaxVolumeDistance) {
if (param_0 < mSetting.field_0x3c) {
return 0;
}
return mSetting.mPriorityFactor[distVolBit] * (distance - mSetting.mMaxVolumeDistance);
return mSetting.field_0xac[distVolBit] * (param_0 - mSetting.field_0x3c);
}
f32 Z2Audience::calcPitchDoppler_(const JGeometry::TVec3<f32>& param_0,
@@ -810,24 +810,24 @@ f32 Z2Audience::calcPitchDoppler_(const JGeometry::TVec3<f32>& param_0,
const JGeometry::TVec3<f32>& param_2, f32 param_3) const {
f32 dVar8 = param_0.dot(param_1);
f32 dVar7 = param_0.dot(param_2);
return (mSetting.mSonicSpeed + param_3 * dVar8) / (mSetting.mSonicSpeed + param_3 * dVar7);
return (mSetting.field_0x5c + param_3 * dVar8) / (mSetting.field_0x5c + param_3 * dVar7);
}
f32 Z2Audience::calcFxMix_(f32 distance, int distVolBit) const {
if (distance > mSetting.mDistanceMaxes[distVolBit]) {
return mSetting.mMaxDistanceFxMix;
f32 Z2Audience::calcFxMix_(f32 param_0, int distVolBit) const {
if (param_0 > mSetting.field_0x0[distVolBit]) {
return mSetting.field_0x54;
}
if (distance < mSetting.mMaxVolumeDistance) {
return mSetting.mMinDistanceFxMix;
if (param_0 < mSetting.field_0x3c) {
return mSetting.field_0x50;
}
return mSetting.mMinDistanceFxMix + mSetting.mFxMixFactor[distVolBit] * (distance - mSetting.mMaxVolumeDistance);
return mSetting.field_0x50 + mSetting.field_0xe8[distVolBit] * (param_0 - mSetting.field_0x3c);
}
f32 Z2Audience::calcPitch_(Z2AudibleChannel* channel, const Z2Audible* audible, const Z2AudioCamera* camera) const {
JAUAudibleParam audParam = *audible->getAudibleParam();
if (audParam.field_0x0.bytes.mDopplerPower) {
if (audParam.field_0x0.bytes.b0_0) {
JGeometry::TVec3<f32> aTStack_4c;
aTStack_4c.normalize(channel->mRelPos.mCameraRelative);
aTStack_4c.normalize(channel->field_0x14.field_0x00);
JAUAudibleParam audParam = *audible->getAudibleParam();
f32 doppler = audParam.getDopplerPower();
+15 -8
View File
@@ -14,6 +14,10 @@
#include <cstring>
#include "Z2AudioLib/SpotName.h"
#if TARGET_PC
#include "dusk/randomizer/game/randomizer_context.hpp"
#endif
Z2SceneMgr::Z2SceneMgr() : JASGlobalInstance<Z2SceneMgr>(true) {
sceneNum = -1;
BGM_ID = -1;
@@ -1230,7 +1234,8 @@ void Z2SceneMgr::setSceneName(char* spot, s32 room, s32 layer) {
bgm_id = Z2BGM_DUNGEON_FOREST;
bgm_wave1 = 0xa;
/* dSv_event_flag_c::M_022 - Forest Temple - Forest Temple clear (Midna creates warp hole) */
} else if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[55])) {
// In rando, check for boss defeated instead
} else if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[55]) IF_DUSK(&& (!randomizer_IsActive() || dComIfGs_isStageBossEnemy()))) {
bgm_id = 0x200005b;
} else {
bgm_wave1 = 0xc;
@@ -1290,11 +1295,13 @@ void Z2SceneMgr::setSceneName(char* spot, s32 room, s32 layer) {
break;
case Z2SCENE_LAKEBED_TEMPLE_BOSS:
se_wave1 = 9;
if (dComIfGs_isStageSwitch(4, 0xe)) {
// In rando, check for boss defeated instead
if (dComIfGs_isStageSwitch(4, 0xe) IF_DUSK(&& (!randomizer_IsActive() || dComIfGs_isStageBossEnemy()))) {
bgm_id = Z2BGM_DUNGEON_LV3;
bgm_wave1 = 0x15;
/* dSv_event_flag_c::M_045 - Lakebed Temple - Lakebed Temple clear */
} else if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[78])) {
// In rando, check for boss defeated instead
} else if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[78]) IF_DUSK(&& (!randomizer_IsActive() || dComIfGs_isStageBossEnemy()))) {
bgm_id = 0x200005b;
} else {
bgm_wave1 = 0x1e;
@@ -1324,11 +1331,11 @@ void Z2SceneMgr::setSceneName(char* spot, s32 room, s32 layer) {
break;
case Z2SCENE_ARBITERS_GROUNDS_BOSS:
se_wave1 = 0xd;
if (dComIfGs_isStageSwitch(0xa, 0xa)) {
if (dComIfGs_isStageSwitch(0xa, 0xa) IF_DUSK(&& (!randomizer_IsActive() || dComIfGs_isStageBossEnemy()))) {
bgm_id = Z2BGM_DUNGEON_LV4;
bgm_wave1 = 0x1a;
/* dSv_event_flag_c::F_0265 - Arbiter's Grounds - Arbiter's Grounds clear */
} else if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[265])) {
} else if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[265]) IF_DUSK(&& (!randomizer_IsActive() || dComIfGs_isStageBossEnemy()))) {
bgm_id = 0x200005b;
} else {
bgm_wave1 = 0x4c;
@@ -1389,11 +1396,11 @@ void Z2SceneMgr::setSceneName(char* spot, s32 room, s32 layer) {
break;
case Z2SCENE_TEMPLE_OF_TIME_BOSS:
se_wave1 = 0x15;
if (dComIfGs_isStageSwitch(7, 0x18)) {
if (dComIfGs_isStageSwitch(7, 0x18) IF_DUSK(&& (!randomizer_IsActive() || dComIfGs_isStageBossEnemy()))) {
bgm_id = Z2BGM_DUNGEON_LV6;
bgm_wave1 = 0x26;
/* dSv_event_flag_c::F_0267 - Temple of Time - Temple of Time clear */
} else if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[267])) {
} else if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[267]) IF_DUSK(&& (!randomizer_IsActive() || dComIfGs_isStageBossEnemy()))) {
bgm_id = 0x200005b;
} else {
bgm_wave1 = 0x4e;
@@ -1642,7 +1649,7 @@ void Z2SceneMgr::setSceneName(char* spot, s32 room, s32 layer) {
JSUList<JAIStream>* stream_list = Z2GetSoundMgr()->getStreamMgr()->getStreamList();
JSULink<JAIStream>* stream;
for (stream = stream_list->getFirst(); stream != NULL; stream = stream->getNext()) {
if (bVar2 || sound_table->getTypeID(stream->getObject()->getID()) != SOUND_TYPEID_STREAM) {
if (bVar2 || sound_table->getTypeID(stream->getObject()->getID()) != 0x71) {
stream->getObject()->stop(Z2Param::SCENE_CHANGE_BGM_FADEOUT_TIME);
}
}
+75 -75
View File
@@ -23,7 +23,7 @@ u16 Z2SoundInfo::getBgmSeqResourceID(JAISoundID soundID) const {
if (data != NULL) {
switch ((typeID & 0xf0)) {
case SOUND_TYPEID_SEQUENCE:
case 0x60:
return (u16)data->mResourceId;
}
}
@@ -53,7 +53,7 @@ u32 Z2SoundInfo::getPriority(JAISoundID soundID) const {
JAUSoundTableItem* data = JASGlobalInstance<JAUSoundTable>::getInstance()->getData(soundID);
u8 typeID = JASGlobalInstance<JAUSoundTable>::getInstance()->getTypeID(soundID);
if (data != NULL && (typeID & SOUND_TYPEID_VALID) != 0) {
if (data != NULL && (typeID & 0x40) != 0) {
return data->mPriority;
}
@@ -67,64 +67,64 @@ JAUAudibleParam Z2SoundInfo::getAudibleSwFull(JAISoundID soundID) {
u8 typeID = JASGlobalInstance<JAUSoundTable>::getInstance()->getTypeID(soundID);
switch (typeID) {
case SOUND_TYPEID_SOUND_EFFECT:
audibleParam.field_0x0.bytes.mDopplerPower = (u32)getSwBit(soundID) >> SOUND_SW_DOPPLER_POWER_OFFSET;
if ((getSwBit(soundID) & SOUND_SW_ALWAYS_MAX_PRIORITY) != 0) {
audibleParam.field_0x0.bytes.mCalculatePriority = 0;
case 81:
audibleParam.field_0x0.bytes.b0_0 = (u32)getSwBit(soundID) >> 8;
if ((getSwBit(soundID) & 1) != 0) {
audibleParam.field_0x0.bytes.b0_4 = 0;
} else {
audibleParam.field_0x0.bytes.mCalculatePriority = 1;
audibleParam.field_0x0.bytes.b0_4 = 1;
}
if ((getSwBit(soundID) & SOUND_SW_IGNORE_DISTANCE_VOL) != 0) {
audibleParam.field_0x0.bytes.mCalcDistanceVolume = 0;
if ((getSwBit(soundID) & 2) != 0) {
audibleParam.field_0x0.bytes.b0_5 = 0;
} else {
audibleParam.field_0x0.bytes.mCalcDistanceVolume = 1;
audibleParam.field_0x0.bytes.b0_5 = 1;
}
if ((getSwBit(soundID) & SOUND_SW_IGNORE_FX_MIX) != 0) {
audibleParam.field_0x0.bytes.mCalcFxMix = 0;
if ((getSwBit(soundID) & 4) != 0) {
audibleParam.field_0x0.bytes.b0_6 = 0;
} else {
audibleParam.field_0x0.bytes.mCalcFxMix = 1;
audibleParam.field_0x0.bytes.b0_6 = 1;
}
if ((getSwBit(soundID) & SOUND_SW_CULL_AT_MAX_DISTANCE) != 0) {
audibleParam.field_0x0.bytes.mCullAtMaxDistance = 1;
if ((getSwBit(soundID) & 0x800000) != 0) {
audibleParam.field_0x0.bytes.b0_7 = 1;
} else {
audibleParam.field_0x0.bytes.mCullAtMaxDistance = 0;
audibleParam.field_0x0.bytes.b0_7 = 0;
}
if ((getSwBit(soundID) & SOUND_SW_IGNORE_PAN) != 0) {
audibleParam.field_0x0.bytes.mCalcPan = 0;
if ((getSwBit(soundID) & 0x1000) != 0) {
audibleParam.field_0x0.bytes.b1_0 = 0;
} else {
audibleParam.field_0x0.bytes.mCalcPan = 1;
audibleParam.field_0x0.bytes.b1_0 = 1;
}
if ((getSwBit(soundID) & SOUND_SW_IGNORE_DOLBY) != 0) {
audibleParam.field_0x0.bytes.mCalcDolby = 0;
if ((getSwBit(soundID) & 0x2000) != 0) {
audibleParam.field_0x0.bytes.b1_1 = 0;
} else {
audibleParam.field_0x0.bytes.mCalcDolby = 1;
audibleParam.field_0x0.bytes.b1_1 = 1;
}
uVar7 = 0;
if ((getSwBit(soundID) & SOUND_SW_CLAMP_MIN_VOLUME) != 0) {
if ((getSwBit(soundID) & 0x80000) != 0) {
uVar7 = 8;
}
iVar1 = (getSwBit(soundID) >> 16) & SOUND_VOL_DIST_BIT_MASK_SHIFTED;
iVar1 += (getSwBit(soundID) >> 16) & SOUND_VOL_DIST_BIT_2_MASK_SHIFTED;
iVar1 += (getSwBit(soundID) >> 16) & SOUND_VOL_SOMETHING_MASK_SHIFTED;
audibleParam.field_0x0.bytes.mClampMinVolume = uVar7;
iVar1 = (getSwBit(soundID) >> 16) & 0x7;
iVar1 += (getSwBit(soundID) >> 16) & 0x70;
iVar1 += (getSwBit(soundID) >> 16) & 0xf00;
audibleParam.field_0x0.bytes.b1_2_7 = uVar7;
audibleParam.field_0x0.half.f1 = iVar1;
break;
default:
audibleParam.field_0x0.bytes.mDopplerPower = 0;
audibleParam.field_0x0.bytes.mCalculatePriority = 1;
audibleParam.field_0x0.bytes.mCalcDistanceVolume = 1;
audibleParam.field_0x0.bytes.mCalcFxMix = 1;
audibleParam.field_0x0.bytes.mCullAtMaxDistance = 0;
audibleParam.field_0x0.bytes.mCalcPan = 1;
audibleParam.field_0x0.bytes.mCalcDolby = 1;
audibleParam.field_0x0.bytes.mClampMinVolume = 0;
audibleParam.field_0x0.bytes.b0_0 = 0;
audibleParam.field_0x0.bytes.b0_4 = 1;
audibleParam.field_0x0.bytes.b0_5 = 1;
audibleParam.field_0x0.bytes.b0_6 = 1;
audibleParam.field_0x0.bytes.b0_7 = 0;
audibleParam.field_0x0.bytes.b1_0 = 1;
audibleParam.field_0x0.bytes.b1_1 = 1;
audibleParam.field_0x0.bytes.b1_2_7 = 0;
audibleParam.field_0x0.half.f1 = 0;
break;
}
@@ -139,53 +139,53 @@ u16 Z2SoundInfo::getAudibleSw(JAISoundID soundID) const {
u8 typeID = JASGlobalInstance<JAUSoundTable>::getInstance()->getTypeID(soundID);
switch (typeID) {
case SOUND_TYPEID_SOUND_EFFECT:
audibleParam.field_0x0.bytes.mDopplerPower = (u32)getSwBit(soundID) >> SOUND_SW_DOPPLER_POWER_OFFSET;
if ((getSwBit(soundID) & SOUND_SW_ALWAYS_MAX_PRIORITY) != 0) {
audibleParam.field_0x0.bytes.mCalculatePriority = 0;
case 81:
audibleParam.field_0x0.bytes.b0_0 = (u32)getSwBit(soundID) >> 8;
if ((getSwBit(soundID) & 1) != 0) {
audibleParam.field_0x0.bytes.b0_4 = 0;
} else {
audibleParam.field_0x0.bytes.mCalculatePriority = 1;
audibleParam.field_0x0.bytes.b0_4 = 1;
}
if ((getSwBit(soundID) & SOUND_SW_IGNORE_DISTANCE_VOL) != 0) {
audibleParam.field_0x0.bytes.mCalcDistanceVolume = 0;
if ((getSwBit(soundID) & 2) != 0) {
audibleParam.field_0x0.bytes.b0_5 = 0;
} else {
audibleParam.field_0x0.bytes.mCalcDistanceVolume = 1;
audibleParam.field_0x0.bytes.b0_5 = 1;
}
if ((getSwBit(soundID) & 4) != 0) {
audibleParam.field_0x0.bytes.mCalcFxMix = 0;
audibleParam.field_0x0.bytes.b0_6 = 0;
} else {
audibleParam.field_0x0.bytes.mCalcFxMix = 1;
audibleParam.field_0x0.bytes.b0_6 = 1;
}
if ((getSwBit(soundID) & SOUND_SW_CULL_AT_MAX_DISTANCE) != 0) {
audibleParam.field_0x0.bytes.mCullAtMaxDistance = 1;
if ((getSwBit(soundID) & 0x800000) != 0) {
audibleParam.field_0x0.bytes.b0_7 = 1;
} else {
audibleParam.field_0x0.bytes.mCullAtMaxDistance = 0;
audibleParam.field_0x0.bytes.b0_7 = 0;
}
if ((getSwBit(soundID) & SOUND_SW_IGNORE_PAN) != 0) {
audibleParam.field_0x0.bytes.mCalcPan = 0;
if ((getSwBit(soundID) & 0x1000) != 0) {
audibleParam.field_0x0.bytes.b1_0 = 0;
} else {
audibleParam.field_0x0.bytes.mCalcPan = 1;
audibleParam.field_0x0.bytes.b1_0 = 1;
}
if ((getSwBit(soundID) & SOUND_SW_IGNORE_DOLBY) != 0) {
audibleParam.field_0x0.bytes.mCalcDolby = 0;
if ((getSwBit(soundID) & 0x2000) != 0) {
audibleParam.field_0x0.bytes.b1_1 = 0;
} else {
audibleParam.field_0x0.bytes.mCalcDolby = 1;
audibleParam.field_0x0.bytes.b1_1 = 1;
}
uVar7 = 0;
if ((getSwBit(soundID) & SOUND_SW_CLAMP_MIN_VOLUME) != 0) {
if ((getSwBit(soundID) & 0x80000) != 0) {
uVar7 = 8;
}
iVar1 = (getSwBit(soundID) >> 16) & SOUND_VOL_DIST_BIT_MASK_SHIFTED;
iVar1 += (getSwBit(soundID) >> 16) & SOUND_VOL_DIST_BIT_2_MASK_SHIFTED;
iVar1 += (getSwBit(soundID) >> 16) & SOUND_VOL_SOMETHING_MASK_SHIFTED;
audibleParam.field_0x0.bytes.mClampMinVolume = uVar7;
iVar1 = (getSwBit(soundID) >> 16) & 0x7;
iVar1 += (getSwBit(soundID) >> 16) & 0x70;
iVar1 += (getSwBit(soundID) >> 16) & 0xf00;
audibleParam.field_0x0.bytes.b1_2_7 = uVar7;
audibleParam.field_0x0.half.f1 = iVar1;
break;
default:
@@ -208,19 +208,19 @@ void Z2SoundInfo::getSeInfo(JAISoundID soundID, JAISe* sePtr) const {
}
switch(typeID) {
case SOUND_TYPEID_SOUND_EFFECT:
sePtr->getProperty().mPitch *= data->mPitch;
u32 pitchParam = (getSwBit(soundID) & SOUND_SW_RANDOM_PITCH_MASK) >> SOUND_SW_RANDOM_PITCH_OFFSET;
if (pitchParam > 8) {
sePtr->getProperty().mPitch += Z2Calc::linearTransform(pitchParam, 8.0f, 15.0f, 16.0f, 24.0f, true) / 48.0f * Z2Calc::getRandom_0_1();
case 81:
sePtr->getProperty().field_0x8 *= data->field_0x8;
u32 uStack_6c = (getSwBit(soundID) & 0xf0) >> 4;
if (uStack_6c > 8) {
sePtr->getProperty().field_0x8 += Z2Calc::linearTransform(uStack_6c, 8.0f, 15.0f, 16.0f, 24.0f, true) / 48.0f * Z2Calc::getRandom_0_1();
} else {
sePtr->getProperty().mPitch += (pitchParam / 48.0f) * Z2Calc::getRandom_0_1();
sePtr->getProperty().field_0x8 += (uStack_6c / 48.0f) * Z2Calc::getRandom_0_1();
}
u32 uVar1 = (u32)getSwBit(soundID) >> SOUND_SW_RANDOM_VOLUME_OFFSET;
u32 uVar1 = (u32)getSwBit(soundID) >> 0x1c;
if (uVar1 != 0) {
f32 dVar18 = (uVar1 / 15.0f) * Z2Calc::getRandom_0_1();
sePtr->getProperty().mVolume -= dVar18 < 0.0f ? 0.0f : (dVar18 > 1.0f ? 1.0f : dVar18);
sePtr->getProperty().field_0x0 -= dVar18 < 0.0f ? 0.0f : (dVar18 > 1.0f ? 1.0f : dVar18);
}
break;
}
@@ -240,13 +240,13 @@ void Z2SoundInfo::getStreamInfo(JAISoundID soundID, JAIStream* streamPtr) const
u8 typeID = JASGlobalInstance<JAUSoundTable>::getInstance()->getTypeID(soundID);
switch (typeID & 0xf0) {
case SOUND_TYPEID_STREAM:
case 0x70:
u16 uVar1;
s32 iVar4;
data = JASGlobalInstance<JAUSoundTable>::getInstance()->getData(soundID);
JUT_ASSERT(356, data);
uVar1 = data->mStreamPanParameters;
uVar1 = data->mResourceId;
numChild = streamPtr->getNumChild();
iVar4 = 0;
for (; iVar4 < numChild && uVar1 != 0; uVar1 >>= JAUStdSoundTableType::STRM_CH_SHIFT, iVar4++) {
@@ -277,12 +277,12 @@ const char* Z2SoundInfo::getStreamFilePath(JAISoundID soundID) {
const void* resource;
switch (JASGlobalInstance<JAUSoundTable>::getInstance()->getTypeID(soundID) & 0xf0) {
case SOUND_TYPEID_STREAM:
case 0x70:
data = JASGlobalInstance<JAUSoundTable>::getInstance()->getData(soundID);
JUT_ASSERT(394, data);
resource = JASGlobalInstance<JAUSoundTable>::getInstance()->getResource();
JUT_ASSERT(398, resource);
return JAUStdSoundTableType::StringOffset::getString(resource, data->mStreamFilePath);
return JAUStdSoundTableType::StringOffset::getString(resource, data->field_0x4);
default:
return NULL;
}
@@ -300,8 +300,8 @@ int Z2SoundInfo::getSwBit(JAISoundID soundID) const {
u8 typeID = JASGlobalInstance<JAUSoundTable>::getInstance()->getTypeID(soundID);
if (data != NULL) {
switch(typeID) {
case SOUND_TYPEID_SOUND_EFFECT:
return data->mSwBit;
case 81:
return data->field_0x4;
}
}
@@ -313,7 +313,7 @@ void Z2SoundInfo::getSoundInfo_(JAISoundID soundID, JAISound* soundPtr) const {
JAUSoundTableItem* data = JASGlobalInstance<JAUSoundTable>::getInstance()->getData(soundID);
u8 typeID = JASGlobalInstance<JAUSoundTable>::getInstance()->getTypeID(soundID);
if (data != NULL && (typeID & SOUND_TYPEID_VALID) != 0) {
soundPtr->getProperty().mVolume = (1.0f / 127.0f) * data->mVolume;
if (data != NULL && (typeID & 0x40) != 0) {
soundPtr->getProperty().field_0x0 = (1.0f / 127.0f) * data->field_0x1;
}
}
+1 -1
View File
@@ -222,7 +222,7 @@ Z2SoundHandlePool* Z2SoundObjBase::startCollisionSE(u32 hitID, u32 mapinfo, Z2So
if (30 <= mapinfo && mapinfo <= 52) {
Z2Audible* audible = (Z2Audible*)(*handle)->getAudible();
if (audible != NULL) {
audible->getAudibleParam()->field_0x0.bytes.mClampMinVolume = 8;
audible->getAudibleParam()->field_0x0.bytes.b1_2_7 = 8;
}
}
}

Some files were not shown because too many files have changed in this diff Show More