Compare commits

..

580 Commits

Author SHA1 Message Date
CraftyBoss 589c6675fe fix inventory reset ignoring previously obtained items on inv fill, add heros clothes to reset inventory default 2026-07-02 00:50:07 -07:00
CraftyBoss 0be48db605 save archipelago connection info based on current save slot 2026-07-01 01:36:14 -07:00
CraftyBoss dbb9ce2c03 fix merge error 2026-07-01 00:51:29 -07:00
CraftyBoss cc808ab50c Merge remote-tracking branch 'origin/randomizer' into rando-archi
# Conflicts:
#	include/dusk/settings.h
#	src/dusk/settings.cpp
2026-07-01 00:42:52 -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
Luke Street 09f087656a Guard against null dMsgObject_getMsgObjectClass() in a few places 2026-06-30 15:19:30 -06:00
CraftyBoss 7682165478 Merge remote-tracking branch 'origin/randomizer' into rando-archi 2026-06-30 01:08:17 -07:00
Irastris fe15366912 Make Ganondorf cape tearing deterministic when using texture replacements (#2145)
* Make Ganondorf cape tearing deterministic when using texture replacements

* GXIsTexObjReplaced -> has_replacement

* Only check for a replacement once during creation

* Update Aurora
2026-06-28 22:44:26 -06:00
jdflyer cfadf7607a Various Mirror Mode Fixes (#2149)
* Various Mirror Mode Fixes

* Avoid mutating mArrowPos2DX

---------

Co-authored-by: Luke Street <luke@street.dev>
2026-06-28 22:42:52 -06:00
Luke Street f81d25b425 Add "Touch Targeting" option 2026-06-27 21:20:14 -06:00
qubitnano ebf6f31719 flake.nix: patchelf libvulkan (#2124)
Since aurora 7ccdae18077caa67acb0f61a525aa5a423cc3b2c, dusklight can't
find libvulkan.so on nix
2026-06-27 21:15:57 -06:00
Luke Street 590d209f76 Update README.md 2026-06-27 21:09:04 -06:00
Luke Street ed21cd4fd0 Update README.md 2026-06-27 20:35:17 -06: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
CraftyBoss 57019bea30 Merge remote-tracking branch 'origin/main' into rando-archi 2026-06-25 01:05:26 -07:00
CraftyBoss c590018059 trigger game complete on ganondorf kill
with this, in theory AP seeds should be beatable now, of course theres still a ton of work to do in terms of fleshing out some features
2026-06-25 01:05:15 -07:00
Luke Street 277538bb81 New pipeline progress UI 2026-06-24 22:03:58 -07:00
CraftyBoss e7eefbb0cb Merge remote-tracking branch 'origin/randomizer' into rando-archi 2026-06-24 03:22:56 -07:00
CraftyBoss 7ee39edee7 add death link support, add needed archipelago item messages to language yamls
Archipelago items will still be green rupees for now until we decide how we want to handle custom game assets
2026-06-24 03:22:42 -07:00
gymnast86 6592871fa2 add mirror chamber access setting 2026-06-23 09:16:39 -07:00
CraftyBoss 5a1368b355 cleanup settings parser, get settings directly from slot data instead of user YAML
loaded seeds should now have proper settings applied without needing to seperately parse the archi's player settings yaml.
2026-06-22 23:43:24 -07:00
CraftyBoss 6984ae83bf add UI to selecting/creating archipelago seed
Next step will be to associate connection info to each save slot instead of overwriting the same config values for every slot. With these changes though, it should be possible to connect to an archipelago lobby without needing to use the ImGui debug window.
2026-06-22 03:25:01 -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
CraftyBoss 93479100fc Merge remote-tracking branch 'origin/randomizer' into rando-archi 2026-06-21 14:36:49 -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
CraftyBoss 6366ab61d1 add inventory resetting on server connect, properly handle getting new items from locations, integrate some of archi into new rando ui stuff
For the most part, solo archipelago runs seem to work fine now using the original TP apworld, but im sure there are plenty of weird issues still that need to be handled.
2026-06-19 17:07:42 -07:00
CraftyBoss 7537f1c4a8 Merge remote-tracking branch 'origin/randomizer' into rando-archi 2026-06-19 17:01:52 -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
Luke Street 5418b1831d Update aurora & flake.nix versions 2026-06-17 23:12:49 -06:00
Luke Street 2d4e69466b Refine menu_pointer click events
Only short clicks/taps count & they must
not move between targets
2026-06-17 22:48:44 -06:00
Luke Street 427dcfab82 Show active Graphics Backend in Settings; not configured 2026-06-17 18:09:00 -06: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
Luke Street f5642f3073 UI: Split active/visible concepts & fix nav forwarding 2026-06-16 15:10:09 -06:00
Luke Street cc9c15de54 Hawkeye support in touch controls 2026-06-16 13:51:17 -06:00
Luke Street 1fd8a2ca3c More fixes for clawshot touch controls 2026-06-16 13:37:04 -06:00
Luke Street 0c9c8795ce Update aurora 2026-06-16 13:12:37 -06:00
Luke Street 9eb9acfa11 Move frame limiter after aurora_end_frame 2026-06-16 12:56:02 -06: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
Luke Street facbf35343 Update aurora 2026-06-16 01:53:04 -06:00
Luke Street 7a34830dc7 Update aurora 2026-06-16 01:40:00 -06:00
Luke Street e4557efb23 Disable PkgConfig on Windows 2026-06-16 01:39:54 -06:00
Luke Street 42e12eb5ab Update aurora & fix RCSS warning 2026-06-16 00:14:19 -06:00
Luke Street 16cc37ca10 Android: Call Surface.setFrameRate & update it 2026-06-15 23:39:36 -06:00
Luke Street 44cb2c84ba Update aurora 2026-06-15 23:07:00 -06:00
Luke Street 8e9d4d624a Fix hookshot hanging w/ touch controls 2026-06-15 22:55:30 -06:00
Luke Street db87b91954 Update aurora & redraw hearts guage on HUD scale change 2026-06-15 22:46:50 -06:00
Luke Street ad53af5c78 Touch controls (#2053)
* WIP touch controls

* Action icons

* Updates

* Don't mutate freeCamera config; allow switching between touch and controller cam

* Wow

* Fix build & add Skip button

* Fix build & add settings

* RCSS cleanup

* Dpad and fishing, might redo

* Add menu mouse controls

* More pointer & fix icons

* Optimizations & introduce layout system

* Update aurora

* Implement touch controls layout editor

* Cleanup & fixes

* Allow disabling mouse/touch in menus

* More fixes
2026-06-15 12:48:04 -06:00
qubitnano a6e5160c71 flake.nix: xxHash -> xxhash (#2058)
warning: 'xxHash' has been renamed to 'xxhash'
2026-06-15 12:47:40 -06:00
doop 38a0a7be0b Always create a save file if one doesn't exist (#2028)
* Always create a save file if one doesn't exist

* Fix MSVC build

* Re-add accidentally deleted line

* Integrate into d_file_select state machine & put behind instantSaves

---------

Co-authored-by: Luke Street <luke@street.dev>
2026-06-15 12:47:23 -06: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
Luke Street 02fdde3768 Scale map rendering with IR (#2056)
* Scale map rendering with IR + scale config

* Remove config option
2026-06-14 22:41:33 -06:00
Luke Street 33e13d508b Use Aurora-provided FPS for overlay 2026-06-14 11:28:19 -06:00
Luke Street afc3376aec Update aurora 2026-06-14 01:11:14 -06:00
matthewdavidrichardanderson b07fb50128 monkey crash fix (#2034)
* monkey fix 🐒

* wrap saru_p clear in target_pc

* Clear monkey leader pointer on delete

---------

Co-authored-by: matthewdavidrichardanderson <matthewdavidrichardanderson@mfb.com>
Co-authored-by: Luke Street <luke@street.dev>
2026-06-13 22:39:30 -06:00
Kyrio d0894853d7 Add setting to memorize window size (#2025)
* Add "Memorize Window Size" setting

* Code review #2025

* memorize -> remember, helpText revision

---------

Co-authored-by: Irastris <irastris15@gmail.com>
2026-06-13 22:47:18 -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
Luke Street cacb768725 Updatea aurora & set DOWNLOAD_EXTRACT_TIMESTAMP FALSE 2026-06-13 10:44:51 -06:00
Luke Street 00707024bb Update aurora & flower/grass draw batching 2026-06-13 10:40:57 -06:00
gymnast86 544964c1a5 properly implement no logic 2026-06-13 07:56:51 -04:00
CraftyBoss 59b76f7aae Merge remote-tracking branch 'origin/randomizer' into rando-archi 2026-06-12 23:29:45 -07: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
CraftyBoss 4466442cfb add location IDs to yaml db, get started on translating received ap data to rando data
the idea is to use the existing randomizer systems (like World, RandomizerContext, etc) in order to generate necessary data for in-game modifications such as text replacements, model swaps, etc. to do this we need to get the apworld's current settings, which atm will require loading the configured ap yaml file before connecting to archipelago.
2026-06-12 02:47:52 -07:00
CraftyBoss d6f741947a Merge remote-tracking branch 'origin/randomizer' into rando-archi 2026-06-10 22:59:44 -07:00
gymnast86 d855efe513 remove instances of double actors 2026-06-10 23:05:25 -06:00
CraftyBoss 51a25206c2 Merge remote-tracking branch 'origin/randomizer' into rando-archi
# Conflicts:
#	include/dusk/settings.h
#	src/dusk/settings.cpp
2026-06-10 21:02:31 -07: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
Luke Street 7c5ed6a0e1 Fix OSWaitCond implementation 2026-06-10 00:18:14 -06:00
Luke Street 131a09f317 Implement JPA particle batching 2026-06-09 23:47:45 -06:00
Luke Street a58f9c7b43 Update Android shell to SDL 3.4.10 2026-06-09 22:51:23 -06:00
CraftyBoss f6b86d3f38 actually get some ap functionality going
getting items from the server works now mostly, for now we're ignoring inventory fills as its going to require a bit of work to reset the inventory on connection.
2026-06-09 01:23:05 -07:00
CraftyBoss b118fa19e1 Merge remote-tracking branch 'origin/randomizer' into rando-archi 2026-06-09 01:14:16 -07:00
Luke Street 7290649bb8 Prune old logs & dawn_cache.db entries 2026-06-09 00:58:17 -06: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 34e1e740ab Update aurora 2026-06-08 23:14:51 -06:00
Luke Street a58f64ed80 Update aurora 2026-06-08 22:49:28 -06:00
Luke Street 5851954ca1 Revert "Move RegisteredConfigVars to function-local static"
This reverts commit ea09dd73c6.
2026-06-08 22:16:10 -06:00
Luke Street 28a37f6b4f Check for sNoUseDrawMtxPtr in J3DModel::entry 2026-06-08 22:14:34 -06:00
Luke Street 285691cd19 Add -debug-asan presets with AddressSanitizer 2026-06-08 22:14: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
CraftyBoss efbf82d4c7 Merge remote-tracking branch 'origin/randomizer' into rando-archi 2026-06-08 16:44:48 -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
Luke Street 93e33ecf1a Cap map resolution multiplier
Resolves #1058
Resolves #1422
Resolves #1668
2026-06-08 00:08:00 -06:00
Reilly Brogan e26fab71d6 Add DUSK_PACKAGE_INSTALL (#1966)
Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>
2026-06-07 23:33:49 -06:00
Luke Street 824389f871 Remove embedded gamecontrollerdb.txt (#2018)
But still load from the data dir if
it exists there (for user overrides)
2026-06-07 22:30:07 -06:00
Luke Street aa42265041 Fix Impaz expression animation OOB read (#2017)
Resolves #1152
2026-06-07 22:29:52 -06:00
BoLThompson 8b7ed4b5da Interpolation fixes (fishing rod, key door chains, hookshot chain) (#2008)
* fishing rod line (item and minigame) interpolated

* small key, big key door chains interpolated

* hookshot chain interpolated
2026-06-08 00:28:48 -04:00
gymnast86 dccded964b fix hang on swim spawn with no water 2026-06-07 21:09:31 -07:00
SuperDude88 f33746f373 Alternate Config Variable Migration Method (#1577)
* Use Explicit Template Specialization

- Move migration of FrameInterpMode to use a unique specialization of loadFromJson

This avoids coding special cases into the main template, which I think is more sustainable in the long-run if we need to migrate other settings ever

* Error for Default Migration

- Add error message in the config log for default migration

Not a fatal, just a clear signal that you should handle your enum cases explicitly to make sure they're right
2026-06-07 21:39:02 -06:00
Nathan Mena 18c1d11335 Fix mirror mode sign arrows (#1704)
* Manually defined specific Wii messages to be returned when mirror mode is enabled

* Fixed random hanging on some messages
2026-06-07 21:18:58 -06:00
SuperDude88 710f252d53 Fix Respawning in Final Zant Phase (#2013)
Zant was trying to get the player's position before the player was even created

Based on the fix for camera/peahat load order
2026-06-07 21:18:45 -06:00
SuperDude88 2a92a67b87 Fix Mirror Mode Poe Counter (#1997)
Fixes #1817
2026-06-07 21:18:33 -06:00
SuperDude88 0d05f9b75b More Magic Armor Options (#1691)
* More Magic Armor Options

- Add a 3rd option to lose rupees only on damage

* More Choices

- Add cosmetic and double defense options

These both have been requested a couple times

* Shorten Description

The description was very, very long before

* Web Editor Got Me

Fix my syntax
2026-06-07 21:18:23 -06:00
ZipoLabs e27cce0e3c Add Green Chu merging functionality to "Restore Wii 1.0 Glitches" setting (#2000) 2026-06-07 21:18:10 -06:00
SuperDude88 511721f4d5 Fix Ganondorf's Cape Texture (#2016)
* Cape Texture Fix

- Load pos/norm/texcoord data directly from the REL

Before the hardcoded array was LE but being treated as BE, now we load it directly from the REL so treating it as BE is the correct behavior

* Fix Cape Tearing

- Update the cached textures when the cape is torn, reset the texture when creating the actor
2026-06-07 21:14:10 -06: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
CraftyBoss 83adafff82 basic setup for archipelago support started
For now we'll be using APCpp, seems to be good enough for what we need to do for this. might eventually roll my own library if things end up being too weird/complicated to integrate properly.
2026-06-06 19:39:23 -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
Luke Street 08e0f4a2ee Update aurora & remove old pipeline cache handling 2026-06-06 09:41:07 -06: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
doop 7a900471bf Clamp flycam FOV (#1996) 2026-06-05 17:05:54 -04:00
MelonSpeedruns d9d9966f8f Time Freezing Camera (#1787)
Thanks to @bkd89 for the idea!

Co-authored-by: MelonSpeedruns <melonspeedruns@stratobox.net>
2026-06-05 00:17:06 -06:00
Kevin Lema 8705e75b9d Add HUD scale setting (#1387)
* Add HUD scale setting

Adds a "HUD Scale" preference (50%–200%) that scales the gameplay HUD
(hearts, magic/lantern meter, light drops, rupees/keys, action buttons
and the mini-map) without affecting dialog boxes or menus.

Each HUD group is scaled around its own pane origin and nudged toward
its anchor corner (via dApplyHudCorner) so it stays put against the
screen edge instead of drifting toward the centre when shrunk. The
mini-map is scaled and shifted in d_meter_map so its bottom-left corner
stays anchored. The setting is clamped to a safe range and is a no-op on
non-PC targets. It is disabled in the menu while Minimal HUD is enabled.

Signed-off-by: kevin Lema <kevin.soesto@gmail.com>

* Scale remaining gameplay HUD elements with HUD scale

Extends the HUD Scale setting to the item ammo counters, the lantern oil
  gauge and the small-key counter, and gives the oil/magic meter a reduced
  horizontal anchor pull so it stays on-screen at small scales.

Signed-off-by: kevin Lema <kevin.soesto@gmail.com>

* Update settings.cpp

Signed-off-by: kevin Lema <kevin.soesto@gmail.com>

---------

Signed-off-by: kevin Lema <kevin.soesto@gmail.com>
2026-06-05 00:14:09 -06:00
Luke Street 1b42c4ecac ci: Build Android w/ release & LTO 2026-06-05 00:12:59 -06:00
SuperDude88 24ca190029 Adjust Total Achievement Count (#1924)
- Don't count the glitched achievements towards the total so that they appear over 100%
2026-06-05 00:05:47 -06:00
doop eefa69b53d Re-enable JParticle interpolation and fix emitter direction issue (#1968)
* Re-enable JParticle interpolation

* Ensure emitter direction is valid for JPA interp

Fixes #618.

* Don't `calcWorkData` if we don't need to
2026-06-05 00:05:20 -06:00
Luke Street da3ac9f546 ci: Build with shared vcruntime 2026-06-05 00:03:43 -06:00
Luke Street 7f306fe1ec Update aurora 2026-06-05 00:03:29 -06:00
Luke Street 358de64570 ci: Use mold linker on Linux 2026-06-04 23:30:30 -06:00
Luke Street e484a10018 tvOS fixes 2026-06-04 23:28:44 -06:00
Luke Street 0936115483 Optimize display lists in J3DShapeDraw
This is a stop-gap until DL optimization
is upstreamed to Aurora.
2026-06-04 23:27:30 -06:00
Luke Street b00b7f8f1b More texture caching 2026-06-04 23:21:13 -06: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
Luke Street 08c4442fdf Update aurora 2026-06-03 21:01:39 -06:00
Pieter-Jan Briers 74f20c38e0 Don't send debug groups to Aurora if not enabled (#1984)
Intended together with https://github.com/encounter/aurora/pull/221
2026-06-03 20:58:35 -06:00
gymnast86 7b521aef02 fix missing location category 2026-06-03 19:39:25 -07:00
Pieter-Jan Briers b7d32918bd Fix a warning (#1985)
Lol
2026-06-03 20:29:54 -06:00
Joshua Trees e99b604dd2 Fix flake.nix for systems where nod must build from source (#1987)
This should actually be fixed upstream, but until then...

See here for more details:

https://github.com/NixOS/nixpkgs/issues/144170

Co-authored-by: Joshua Trees <gh@jtrees.io>
2026-06-03 20:29:41 -06: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
MelonSpeedruns 2376e0102e TPHD Button Fishing (#1949)
Co-authored-by: MelonSpeedruns <melonspeedruns@stratobox.net>
2026-06-03 13:35:51 -04:00
Luke Street 5a9bd6f8dc Update aurora 2026-06-03 02:17:58 -06:00
Luke Street 62a26a639d Bump CMAKE_OSX_DEPLOYMENT_TARGET to 12.0 2026-06-03 02:17:54 -06:00
Luke Street 1a247c2977 Pass CMAKE_OSX_* to libjpeg-turbo build 2026-06-03 02:17:46 -06:00
Luke Street ef122efccd Update aurora 2026-06-03 00:56:44 -06:00
gymnast86 b3dbf2c71b Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-02 23:25:57 -07:00
Luke Street deadde352c Update aurora 2026-06-03 00:02:47 -06:00
Luke Street 460b96c709 More Tracy zones 2026-06-03 00:01:34 -06:00
Pieter-Jan Briers f8ba14ea8f Optimize some special kankyo draw packets (housi, snow, odour) (#1970)
* Slight dKankyo_housi_Packet documentation

* Optimize dKyr_drawHousi (twilight squares)

Now a single draw call rather than like 300

* Optimize dKyr_drawSnow

Snowpeak stonks rising

* Optimize dKyr_odour_draw
2026-06-02 23:47:34 -06: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
Irastris bd9b81f700 Add mouse input option for the third-person camera (#1011)
* Untie existing mouse logic from gyro

* A bit more mouse cleanup before I start building off it

* Rebase and last bit of cleanup

* Fix rebase mistake, don't apply invertFirstPerson to gyro or mouse input

* Remove the deprecated ImGui toast system

* Add Mouse Camera option in preparation for its use

* WIP, add mouse controls for the third-person camera

* Various helpText revisions

* Enable free camera on horseback

* Untie mouse camera and free camera options
Either being enabled now allows the underlying freecam logic to run

* Allow simultaneous C-stick and mouse input

* Combine mouse sensitivities for both aim and camera

* Add option for inverting mouse Y

* Refactor cursor visibility handling

* Tighten aim capture condition and constrain cursor to window region

* Tidying my trash

* Last bit of housekeeping so I'm satisfied

* Don't write code while sleep deprived

* Fix my sloppy merge and a few helpText updates

* Disable control stick aim when mouse aim is active

* Use same conditions for cursor grabbing as for capture
2026-06-01 23:37:53 -06:00
gymnast86 e3eb63f158 Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer 2026-06-01 19:28:36 -07:00
Reilly Brogan b531936a1f linux: Add metainfo file (#1860)
* linux: Add metainfo file

Split from https://github.com/TwilitRealm/dusklight/pull/1191 and adjusted for the correct appId and to remove any trademarks.

Credit to @Gabantax

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>

* Update metainfo per suggestions

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>

---------

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>
2026-06-01 20:24:02 -06:00
Pieter-Jan Briers 21692d5a78 Fix portable mode Unicode (#1893)
* Fix portable mode Unicode

Fixes https://github.com/TwilitRealm/dusklight/issues/1839

* Use path_from_utf8 instead

Huh yeah sure we have that apparently
2026-06-01 20:23:28 -06:00
Reilly Brogan 7af51e53bd Update aurora and adapt for libzstd changes (#1950)
* Update aurora and adapt for libzstd changes

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>

* Fix android build failure with zstd

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>

* Another attempt at fixing Android

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>

---------

Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>
2026-06-01 20:23:13 -06:00
qubitnano bd90c3fc69 flake.nix: devendor aurora, add BUILD_SHARED_LIBS=OFF (#1956)
* flake.nix: devendor aurora

* flake.nix: nixfmt

* flake.nix: add BUILD_SHARED_LIBS=OFF
2026-06-01 20:22:45 -06: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
Luke Street 37abcaf616 Use BUILD_SHARED_LIBS=OFF on base linux/macos presets 2026-05-31 21:30:25 -06:00
Luke Street b26f3f7f51 Update aurora & fix rebuilding on iOS reconfigure 2026-05-31 17:18:11 -06: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
457 changed files with 76032 additions and 3963 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get -y install ninja-build clang lld openssl libcurl4-openssl-dev \
sudo apt-get -y install ninja-build clang lld mold openssl libcurl4-openssl-dev \
zlib1g-dev libglu1-mesa-dev libdbus-1-dev libvulkan-dev libxi-dev libxrandr-dev libasound2-dev \
libpulse-dev libudev-dev libpng-dev libncurses5-dev libx11-xcb-dev libfreetype-dev \
libxinerama-dev libxcursor-dev python3-markupsafe libgtk-3-dev libssl-dev \
+84 -9
View File
@@ -126,6 +126,33 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "_cmake")
option(ENABLE_ASAN "Enable AddressSanitizer" OFF)
if (ENABLE_ASAN)
if (CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" AND
CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/fsanitize=address>)
add_link_options(/fsanitize=address /INCREMENTAL:NO)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "ProgramDatabase")
foreach (_lang C CXX)
foreach (_rtc_flag /RTC1 /RTCc /RTCs /RTCu)
string(REPLACE "${_rtc_flag}" "" CMAKE_${_lang}_FLAGS_DEBUG "${CMAKE_${_lang}_FLAGS_DEBUG}")
endforeach ()
endforeach ()
elseif (CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "GNU" AND
CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
add_compile_options(
$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-fsanitize=address>
$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-fno-omit-frame-pointer>
)
add_link_options(-fsanitize=address)
else ()
message(FATAL_ERROR "ENABLE_ASAN requires GNU-like or MSVC-like C/C++ compiler frontends")
endif ()
add_compile_definitions(NDEBUG_SANITIZER) # Avoids absl issue with SwissTable debug code
message(STATUS "dusklight: Enabled AddressSanitizer")
endif ()
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
set(DAWN_USE_WAYLAND ON CACHE BOOL "Enable support for Wayland surface" FORCE)
endif ()
@@ -137,11 +164,19 @@ target_compile_definitions(aurora_mtx PRIVATE MTX_USE_PS=1)
add_subdirectory(libs/freeverb)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(DUSK_GFX_DEBUG_GROUPS_DEFAULT ON)
else ()
set(DUSK_GFX_DEBUG_GROUPS_DEFAULT OFF)
endif ()
option(DUSK_BUILD_WARNINGS "Enable compiler warnings (off by default)")
option(DUSK_SELECTED_OPT "If on, selected parts of the project will be compiled with optimizations on Debug, intending to make the game run at 30 FPS. Note for MSVC: you will need to remove '/RTC1' from your debug flags in CMake.")
option(DUSK_MOVIE_SUPPORT "If on, compile against libjpeg-turbo to enable THP file decoding" ON)
option(DUSK_ENABLE_UPDATE_CHECKER "Enable update checking support" ON)
option(DUSK_ENABLE_SENTRY_NATIVE "Enable sentry-native crash reporting support" OFF)
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})
set(DUSK_SENTRY_DSN "" CACHE STRING "Sentry DSN")
set(DUSK_SENTRY_ENVIRONMENT "development" CACHE STRING "Sentry environment")
@@ -189,6 +224,8 @@ if (DUSK_MOVIE_SUPPORT)
CMAKE_MSVC_RUNTIME_LIBRARY
CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
CMAKE_OSX_ARCHITECTURES
CMAKE_OSX_DEPLOYMENT_TARGET
CMAKE_OSX_SYSROOT
DEPLOYMENT_TARGET
ENABLE_ARC
ENABLE_BITCODE
@@ -247,7 +284,6 @@ elseif (MSVC)
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/utf-8>)
endif ()
include(FetchContent)
# Declare all dependencies first so CMake can download them in parallel
@@ -255,13 +291,13 @@ message(STATUS "dusklight: Fetching cxxopts")
FetchContent_Declare(cxxopts
URL https://github.com/jarro2783/cxxopts/archive/refs/tags/v3.3.1.tar.gz
URL_HASH SHA256=3bfc70542c521d4b55a46429d808178916a579b28d048bd8c727ee76c39e2072
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
)
message(STATUS "dusklight: Fetching nlohmann/json")
FetchContent_Declare(json
URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz
URL_HASH SHA256=42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
)
FetchContent_MakeAvailable(cxxopts json)
@@ -342,9 +378,7 @@ set(GAME_INCLUDE_DIRS
find_package(Threads REQUIRED)
set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd
aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt
Threads::Threads)
list(APPEND GAME_LIBS libzstd_static)
Threads::Threads zstd::libzstd)
if (DUSK_ENABLE_SENTRY_NATIVE)
list(APPEND GAME_LIBS sentry)
@@ -403,6 +437,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})
@@ -416,6 +452,16 @@ if(ANDROID)
list(APPEND GAME_COMPILE_DEFS TARGET_ANDROID=1)
endif ()
if (DUSK_PACKAGE_INSTALL)
include(GNUInstallDirs)
list(APPEND GAME_COMPILE_DEFS DUSK_ASSET_DIR="${CMAKE_INSTALL_FULL_DATADIR}/dusklight/")
endif ()
if (DUSK_GFX_DEBUG_GROUPS)
list(APPEND GAME_COMPILE_DEFS DUSK_GFX_DEBUG_GROUPS=1)
target_compile_definitions(aurora_gx PRIVATE AURORA_GFX_DEBUG_GROUPS)
endif ()
# game_debug is for game code files that we know work when compiled with DEBUG=1
# Of course, if building a release build, this distinction is irrelevant
set(GAME_DEBUG_FILES
@@ -472,6 +518,27 @@ if(ANDROID)
else ()
add_executable(dusklight ${DUSK_FILES})
endif ()
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 ${GAME_INCLUDE_DIRS})
@@ -634,12 +701,20 @@ set(EXTRA_TARGETS "")
if (TARGET crashpad_handler)
list(APPEND EXTRA_TARGETS crashpad_handler)
endif ()
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX})
if (DUSK_PACKAGE_INSTALL)
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_BINDIR})
else()
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX})
endif()
aurora_install_runtime_dlls(dusklight ${CMAKE_INSTALL_PREFIX})
if (NOT APPLE)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_PREFIX})
if (DUSK_PACKAGE_INSTALL)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/dusklight)
else()
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_PREFIX})
endif()
endif ()
if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)
if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo AND NOT DUSK_PACKAGE_INSTALL)
set(DEBUG_FILES_LIST "")
foreach (target IN LISTS BINARY_TARGETS EXTRA_TARGETS)
get_target_output_name(${target} output_name)
+116 -21
View File
@@ -19,7 +19,19 @@
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded"
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDLL"
}
},
{
"name": "release",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDLL",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": {
"type": "BOOL",
"value": true
}
}
},
{
@@ -40,12 +52,26 @@
}
}
},
{
"name": "asan",
"hidden": true,
"cacheVariables": {
"ENABLE_ASAN": {
"type": "BOOL",
"value": true
}
}
},
{
"name": "linux-default",
"displayName": "Linux (default)",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
},
"vendor": {
@@ -67,6 +93,15 @@
"linux-default"
]
},
{
"name": "linux-default-debug-asan",
"displayName": "Linux (default) Debug ASan",
"inherits": [
"debug",
"linux-default",
"asan"
]
},
{
"name": "linux-default-relwithdebinfo",
"displayName": "Linux (default) RelWithDebInfo",
@@ -94,6 +129,15 @@
"linux-clang"
]
},
{
"name": "linux-clang-debug-asan",
"displayName": "Linux (Clang) Debug ASan",
"inherits": [
"debug",
"linux-clang",
"asan"
]
},
{
"name": "linux-clang-relwithdebinfo",
"displayName": "Linux (Clang) RelWithDebInfo",
@@ -114,7 +158,11 @@
"cacheVariables": {
"CMAKE_C_COMPILER": "cl",
"CMAKE_CXX_COMPILER": "cl",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install",
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL",
"value": true
}
},
"vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": {
@@ -132,6 +180,15 @@
"windows-msvc"
]
},
{
"name": "windows-msvc-debug-asan",
"displayName": "Windows (MSVC) Debug ASan",
"inherits": [
"debug",
"windows-msvc",
"asan"
]
},
{
"name": "windows-msvc-relwithdebinfo",
"displayName": "Windows (MSVC) RelWithDebInfo",
@@ -201,6 +258,10 @@
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
},
"vendor": {
@@ -219,6 +280,15 @@
"macos-default"
]
},
{
"name": "macos-default-debug-asan",
"displayName": "macOS (default) Debug ASan",
"inherits": [
"debug",
"macos-default",
"asan"
]
},
{
"name": "macos-default-relwithdebinfo",
"displayName": "macOS (default) RelWithDebInfo",
@@ -284,24 +354,21 @@
"type": "BOOL",
"value": false
},
"ENABLE_ARC": {
"type": "BOOL",
"value": false
},
"Rust_CARGO_TARGET": "aarch64-apple-tvos",
"Rust_TOOLCHAIN": "nightly",
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_DISABLE_FIND_PACKAGE_BZip2": {
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_LibLZMA": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_zstd": {
"type": "BOOL",
"value": true
}
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew"
},
"vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": {
@@ -327,8 +394,14 @@
"type": "BOOL",
"value": false
},
"AURORA_SDL3_VERSION": "3.4.8",
"AURORA_SDL3_REF": "refs/tags/release-3.4.8"
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_zstd": {
"type": "BOOL",
"value": true
}
}
},
{
@@ -356,7 +429,8 @@
"hidden": true,
"inherits": [
"android-base",
"ci"
"ci",
"release"
],
"cacheVariables": {
"DUSK_ENABLE_SENTRY_NATIVE": {
@@ -384,7 +458,8 @@
"ci"
],
"cacheVariables": {
"AURORA_SDL3_PROVIDER": "vendor"
"AURORA_SDL3_PROVIDER": "vendor",
"CMAKE_LINKER_TYPE": "MOLD"
}
},
{
@@ -413,12 +488,8 @@
"type": "BOOL",
"value": true
},
"CMAKE_OSX_DEPLOYMENT_TARGET": "11.0",
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew",
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
}
"CMAKE_OSX_DEPLOYMENT_TARGET": "12.0",
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew"
}
},
{
@@ -508,6 +579,12 @@
"description": "Linux (default) debug build",
"displayName": "Linux (default) Debug"
},
{
"name": "linux-default-debug-asan",
"configurePreset": "linux-default-debug-asan",
"description": "Linux (default) debug build with AddressSanitizer",
"displayName": "Linux (default) Debug ASan"
},
{
"name": "linux-default-relwithdebinfo",
"configurePreset": "linux-default-relwithdebinfo",
@@ -520,6 +597,12 @@
"description": "Linux (Clang) debug build",
"displayName": "Linux (Clang) Debug"
},
{
"name": "linux-clang-debug-asan",
"configurePreset": "linux-clang-debug-asan",
"description": "Linux (Clang) debug build with AddressSanitizer",
"displayName": "Linux (Clang) Debug ASan"
},
{
"name": "linux-clang-relwithdebinfo",
"configurePreset": "linux-clang-relwithdebinfo",
@@ -532,6 +615,12 @@
"description": "macOS debug build",
"displayName": "macOS Debug"
},
{
"name": "macos-default-debug-asan",
"configurePreset": "macos-default-debug-asan",
"description": "macOS debug build with AddressSanitizer",
"displayName": "macOS Debug ASan"
},
{
"name": "macos-default-relwithdebinfo",
"configurePreset": "macos-default-relwithdebinfo",
@@ -589,6 +678,12 @@
"description": "Windows (MSVC) debug build",
"displayName": "Windows (MSVC) Debug"
},
{
"name": "windows-msvc-debug-asan",
"configurePreset": "windows-msvc-debug-asan",
"description": "Windows (MSVC) debug build with AddressSanitizer",
"displayName": "Windows (MSVC) Debug ASan"
},
{
"name": "windows-msvc-relwithdebinfo",
"configurePreset": "windows-msvc-relwithdebinfo",
+4 -18
View File
@@ -20,31 +20,17 @@ It aims to be as accurate as possible to the original while also providing new o
> Dusklight does *not* provide any copyrighted assets. You must provide your own copy of the original game.
> [!IMPORTANT]
> At a minimum, Dusklight requires a GPU with support for either D3D12, Vulkan, or Metal. Your experience with specific hardware, operating systems, and drivers may vary. In particular, older Intel iGPUs have a high likelihood of incompatibility. We are also aware of a number of issues on devices with Adreno GPUs and are working to resolve them.
> At a minimum, Dusklight requires a GPU with support for D3D12, Vulkan 1.1+, or Metal. For older devices, best-effort support is provided for D3D11 and OpenGL ES (Android), but will not achieve full accuracy or performance. Your experience with specific hardware, operating systems, and drivers may vary.
### 1. Dump your game
You must dump your own copy of the game, please see [this article](https://wiki.dolphin-emu.org/index.php?title=Ripping_Games) for instructions. After dumping, you can use a program like [Dolphin](https://dolphin-emu.org/) or [nodtool](https://github.com/encounter/nod/releases) to convert the `.iso` to a `.rvz` to save space.
You must dump your own copy of the game. Please see [this article](https://wiki.dolphin-emu.org/index.php?title=Ripping_Games) for instructions. After dumping, you can use a program like [Dolphin](https://dolphin-emu.org/) or [nodtool](https://github.com/encounter/nod/releases) to convert the `.iso` to `.rvz` to save space.
Currently, only the GameCube USA and EUR releases are supported. Support for other versions of the game is planned in the future.
### 2. Download [Dusklight](https://github.com/TwilitRealm/dusklight/releases)
### 2. Install Dusklight
### 3. Setup the game
**Windows / macOS / Linux**
- Extract the .zip file
- Launch Dusklight
- Press **Select Disc Image** and provide the path to your supported game dump
- Press **Play**!
**iOS**
- Follow the [iOS setup guide](docs/ios-install-altstore.md)
**Android**
- Install the Dusklight APK
- Launch Dusklight
- Press **Select Disc Image** and provide the path to your supported game dump
- Press **Play**!
Visit the [official installation guide](https://twilitrealm.dev/install/) for full instructions.
# Building
+4
View File
@@ -180,6 +180,7 @@ cmake --build --preset macos-default-relwithdebinfo
Alternate presets available:
* `macos-default-debug`: Clang, Debug
* `macos-default-debug-asan`: Clang, Debug, AddressSanitizer
**ninja (Linux)**
@@ -191,8 +192,10 @@ cmake --build --preset linux-default-relwithdebinfo
Alternate presets available:
* `linux-default-debug`: GCC, Debug
* `linux-default-debug-asan`: GCC, Debug, AddressSanitizer
* `linux-clang-relwithdebinfo`: Clang, RelWithDebInfo
* `linux-clang-debug`: Clang, Debug
* `linux-clang-debug-asan`: Clang, Debug, AddressSanitizer
**ninja (Windows)**
@@ -204,6 +207,7 @@ cmake --build --preset windows-msvc-relwithdebinfo
Alternate presets available:
* `windows-msvc-debug`: MSVC, Debug
* `windows-msvc-debug-asan`: MSVC, Debug, AddressSanitizer
* `windows-clang-relwithdebinfo`: Clang-cl, RelWithDebInfo
* `windows-clang-debug`: Clang-cl, Debug
+1 -1
+122
View File
@@ -1418,7 +1418,11 @@ set(DUSK_FILES
include/dusk/scope_guard.hpp
src/dusk/dvd_asset.cpp
src/d/actor/d_a_alink_dusk.cpp
src/dusk/android_frame_rate.hpp
src/dusk/android_frame_rate.cpp
src/dusk/asserts.cpp
src/dusk/batch.cpp
src/dusk/batch.hpp
src/dusk/config.cpp
src/dusk/crash_handler.cpp
src/dusk/crash_reporting.cpp
@@ -1432,6 +1436,9 @@ set(DUSK_FILES
src/dusk/game_clock.cpp
src/dusk/globals.cpp
src/dusk/gyro.cpp
include/dusk/menu_pointer.h
src/dusk/menu_pointer.cpp
src/dusk/mouse.cpp
src/dusk/gamepad_color.cpp
src/dusk/autosave.cpp
src/dusk/http/http.hpp
@@ -1444,6 +1451,7 @@ set(DUSK_FILES
src/dusk/stubs.cpp
include/dusk/texture_replacements.hpp
src/dusk/texture_replacements.cpp
src/dusk/touch_camera.cpp
src/dusk/update_check.cpp
src/dusk/update_check.hpp
#src/dusk/m_Do_ext_dusk.cpp
@@ -1456,6 +1464,9 @@ set(DUSK_FILES
src/dusk/imgui/ImGuiBloomWindow.hpp
src/dusk/imgui/ImGuiMenuTools.cpp
src/dusk/imgui/ImGuiMenuTools.hpp
src/dusk/imgui/ImGuiMenuRandomizer.cpp
src/dusk/imgui/ImGuiMenuRandomizer.hpp
src/dusk/imgui/ImGuiArchipelagoDebug.cpp
src/dusk/imgui/ImGuiActorSpawner.cpp
src/dusk/imgui/ImGuiProcessOverlay.cpp
src/dusk/imgui/ImGuiCameraOverlay.cpp
@@ -1473,8 +1484,11 @@ set(DUSK_FILES
src/dusk/ui/button.hpp
src/dusk/ui/component.cpp
src/dusk/ui/component.hpp
src/dusk/ui/controls.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/document.cpp
src/dusk/ui/document.hpp
src/dusk/ui/editor.cpp
@@ -1485,6 +1499,8 @@ set(DUSK_FILES
src/dusk/ui/graphics_tuner.hpp
src/dusk/ui/input.cpp
src/dusk/ui/input.hpp
src/dusk/ui/icon_provider.cpp
src/dusk/ui/icon_provider.hpp
src/dusk/ui/modal.cpp
src/dusk/ui/modal.hpp
src/dusk/ui/nav_types.hpp
@@ -1510,12 +1526,24 @@ set(DUSK_FILES
src/dusk/ui/string_button.hpp
src/dusk/ui/tab_bar.cpp
src/dusk/ui/tab_bar.hpp
src/dusk/ui/touch_controls_common.cpp
src/dusk/ui/touch_controls_common.hpp
src/dusk/ui/touch_controls.cpp
src/dusk/ui/touch_controls.hpp
src/dusk/ui/touch_controls_editor.cpp
src/dusk/ui/touch_controls_editor.hpp
src/dusk/ui/ui.cpp
src/dusk/ui/ui.hpp
src/dusk/ui/warp.cpp
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/ui/archi_connect_modal.cpp
src/dusk/ui/archi_connect_modal.hpp
src/dusk/achievements.cpp
src/dusk/iso_validate.cpp
src/dusk/livesplit.cpp
@@ -1529,6 +1557,100 @@ set(DUSK_FILES
src/dusk/discord_presence.cpp
src/dusk/version.cpp
src/dusk/action_bindings.cpp
src/dusk/cosmetics/color_utils.hpp
src/dusk/cosmetics/color_utils.cpp
src/dusk/cosmetics/texture_utils.hpp
src/dusk/cosmetics/texture_utils.cpp
# Randomizer files
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
# Archipelago Files
src/dusk/archipelago/archipelago_context.cpp
)
set(DUSK_HTTP_BACKEND_FILES
+32
View File
@@ -0,0 +1,32 @@
From f69d29614644f9963f5cb3f828b58575d60a1c5a Mon Sep 17 00:00:00 2001
From: Joshua Trees <gh@jtrees.io>
Date: Thu, 4 Jun 2026 01:04:04 +0100
Subject: [PATCH] fix cmake paths
---
cmake/nodConfig.cmake.in | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/cmake/nodConfig.cmake.in b/cmake/nodConfig.cmake.in
index 0969382..2a24a88 100644
--- a/cmake/nodConfig.cmake.in
+++ b/cmake/nodConfig.cmake.in
@@ -1,12 +1,12 @@
@PACKAGE_INIT@
-set(_nod_libdir "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_LIBDIR@")
-set(_nod_incdir "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@")
+set(_nod_libdir "@CMAKE_INSTALL_FULL_LIBDIR@")
+set(_nod_incdir "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
if (NOT TARGET nod::nod_shared AND NOT TARGET nod::nod_static)
# Shared library
if (WIN32)
- set(_nod_dll "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_BINDIR@/${CMAKE_SHARED_LIBRARY_PREFIX}nod${CMAKE_SHARED_LIBRARY_SUFFIX}")
+ set(_nod_dll "@CMAKE_INSTALL_FULL_BINDIR@/${CMAKE_SHARED_LIBRARY_PREFIX}nod${CMAKE_SHARED_LIBRARY_SUFFIX}")
set(_nod_implib "${_nod_libdir}/${CMAKE_IMPORT_LIBRARY_PREFIX}nod${CMAKE_IMPORT_LIBRARY_SUFFIX}")
if (EXISTS "${_nod_dll}")
add_library(nod::nod_shared SHARED IMPORTED)
--
2.53.0
+148 -130
View File
@@ -16,37 +16,37 @@
];
forAllSystems = lib.genAttrs supportedSystems;
dawnVersion = "v20260423.175430";
nodVersion = "v2.0.0-alpha.8";
dawnVersion = "v20260618.032059";
nodVersion = "v2.0.0-alpha.10";
versionSuffix = "nix-" + (self.shortRev or self.dirtyShortRev or "dirty");
dawnInfo = {
"x86_64-linux" = {
triple = "linux-x86_64";
hash = "sha256-HXfKTLHtMPwupnFnaflCARtXVPuS/0PoCePXidjE5xs=";
hash = "sha256-GFSd573b+VQx/VmFdNQgWDd0V9ayQlcw0Zuopke12ak=";
};
"aarch64-linux" = {
triple = "linux-aarch64";
hash = "sha256-34yyFpfqBZUwoFXQ41F0AwAU78FaNihOSY0oriwn6B0=";
hash = "sha256-ZaoP7BAjBMnfAv2/AMRi3FNH2ZtyqASCSFyU/oB2Mzg=";
};
"aarch64-darwin" = {
triple = "darwin-arm64";
hash = "sha256-eQnzrBp6gjiBek1VYQ9A5W13ClYWrDDKjIqv/7eNTR4=";
hash = "sha256-HT+qtlLaSHyoXPrUcXgcTGa877X5YfzbxRD4bJb7i1Y=";
};
"x86_64-darwin" = {
triple = "darwin-x86_64";
hash = "sha256-QGWiGdxiI9kci3NPXH6QFFirxn16851zB/w3jqhIBJ4=";
hash = "sha256-cUNaCbA7rlKSukDVKGaVEVw0Zt1+mSbaHbmUCMvMVWc=";
};
};
nodPrebuiltInfo = {
"x86_64-linux" = {
triple = "linux-x86_64";
hash = "sha256-mUqvLsbsqaZ+HAjMmHYPYO+MgtanGRTw7Gzn5uXR5rE=";
hash = "sha256-FVQWECVA2gWdc+n5OQ/Tvwn8z0qdgjSd1WlFt5HKOec=";
};
"aarch64-darwin" = {
triple = "macos-arm64";
hash = "sha256-UPy1ywCcv0K6VJOU3uUelJuUdBh3UNaPRlyP5LOBeDw=";
hash = "sha256-8ZEejxksVgShNKUVRCBYaLOp9x/qOC9pAeVrElQUGUk=";
};
};
@@ -57,15 +57,25 @@
inherit (pkgs.stdenv.hostPlatform) isDarwin;
hasNodPrebuilt = nodPrebuiltInfo ? ${system};
aurora = pkgs.fetchFromGitHub {
owner = "encounter";
repo = "aurora";
rev = "10006618ee493f248b8597e4dfa1d2871d76a1d9";
hash = "sha256-lY2xuVyB7aPJ9+2wwLRB3F5U/BuPSxdSpegdG+qNd9o=";
};
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-build/releases/download/${dawnVersion}/dawn-${dawnInfo.${system}.triple}.tar.gz";
url = "https://github.com/encounter/dawn/releases/download/${dawnVersion}/dawn-${dawnInfo.${system}.triple}.tar.gz";
hash = dawnInfo.${system}.hash;
stripRoot = false;
};
@@ -84,8 +94,9 @@
owner = "encounter";
repo = "nod";
rev = nodVersion;
hash = "sha256-+zrtVzjo0+X/6uMcNUn1+FaSR+jOhrcQSDNBFjw0NDs=";
hash = "sha256-r8qDlOVxv5iKiFjJQrcBuL9HVoOM3yEjRVnQIMqaICs=";
};
patches = [ ./fix-cmake-paths.patch ];
cargoDeps = pkgs.rustPlatform.importCargoLock {
lockFile = "${finalAttrs.src}/Cargo.lock";
};
@@ -127,15 +138,15 @@
NOD_PREBUILT = nod;
CXXOPTS = pkgs.cxxopts.src;
JSON = pkgs.nlohmann_json.src;
XXHASH = pkgs.xxHash.src;
XXHASH = pkgs.xxhash.src;
ZSTD = pkgs.zstd.src;
FMT = pkgs.fetchzip {
url = "https://github.com/fmtlib/fmt/archive/refs/tags/11.1.4.tar.gz";
hash = "sha256-sUbxlYi/Aupaox3JjWFqXIjcaQa0LFjclQAOleT+FRA=";
url = "https://github.com/fmtlib/fmt/archive/refs/tags/12.1.0.tar.gz";
hash = "sha256-ZmI1Dv0ZabPlxa02OpERI47jp7zFfjpeWCy1WyuPYZ0=";
};
TRACY = pkgs.fetchzip {
url = "https://github.com/wolfpld/tracy/archive/a64b9a20294d59421a2f57aeca3c6383d8c48169.tar.gz";
hash = "sha256-hbNGOsGeyGSvCJ2No8RkwOib1lX2on3vNZSzyVkZdXw=";
url = "https://github.com/wolfpld/tracy/archive/6789e7d6f9a65ec98926b602097a33a9676d2606.tar.gz";
hash = "sha256-Xxyd7G/mnXEPpN+ehmwl0AkAhS3CwObpJNDgcqbdUJg=";
};
IMGUI = pkgs.fetchFromGitHub {
owner = "ocornut";
@@ -153,119 +164,126 @@
};
};
dusklight = pkgs.stdenv.mkDerivation {
pname = "dusklight";
version = versionSuffix;
src = ./.;
dusklight =
if !aurora then
throw needSubmodules
else
pkgs.stdenv.mkDerivation {
pname = "dusklight";
version = versionSuffix;
src = ./.;
postUnpack = ''
chmod -R u+w "$sourceRoot"
rm -rf "$sourceRoot/extern/aurora"
mkdir -p "$sourceRoot/extern"
cp -r ${aurora} "$sourceRoot/extern/aurora"
chmod -R u+w "$sourceRoot/extern/aurora"
substituteInPlace "$sourceRoot/extern/aurora/CMakeLists.txt" \
--replace-warn "add_subdirectory(tests)" ""
'';
nativeBuildInputs = [
pkgs.cmake
pkgs.ninja
pkgs.pkg-config
pkgs.python3
pkgs.python3Packages.markupsafe
]
++ lib.optionals (!isDarwin) [ pkgs.autoPatchelfHook ];
buildInputs = [
pkgs.sdl3
pkgs.freetype
pkgs.zstd
pkgs.cxxopts
pkgs.nlohmann_json
pkgs.xxHash
pkgs.abseil-cpp
pkgs.zlib
pkgs.libpng
pkgs.libjpeg_turbo
pkgs.curl
pkgs.openssl
]
++ lib.optionals isDarwin [
pkgs.apple-sdk_15
pkgs.libiconv
]
++ lib.optionals (!isDarwin) [
pkgs.libGL
pkgs.libGLU
pkgs.libglvnd
pkgs.vulkan-loader
pkgs.libX11
pkgs.libxcb
pkgs.libXcursor
pkgs.libxi
pkgs.libxrandr
pkgs.libxscrnsaver
pkgs.libxtst
pkgs.libxinerama
pkgs.libxkbcommon
pkgs.wayland
pkgs.libdecor
pkgs.alsa-lib
pkgs.libpulseaudio
pkgs.pipewire
pkgs.dbus
pkgs.udev
pkgs.libusb1
pkgs.libunwind
pkgs.gtk3
];
cmakeBuildType = "RelWithDebInfo";
ninjaFlags = [ "dusklight" ];
cmakeFlags = [
"-DDUSK_VERSION_OVERRIDE=${versionSuffix}"
"-DFETCHCONTENT_FULLY_DISCONNECTED=ON"
"-DAURORA_DAWN_PROVIDER=package"
"-DAURORA_DAWN_LINKAGE=static"
"-DAURORA_NOD_PROVIDER=package"
"-DAURORA_NOD_LINKAGE=static"
"-DAURORA_SDL3_PROVIDER=system"
]
++ lib.mapAttrsToList (key: src: "-DFETCHCONTENT_SOURCE_DIR_${key}=${src}") fetchContentDirs;
installPhase =
if isDarwin then
''
runHook preInstall
mkdir -p "$out/Applications"
cp -r Dusklight.app "$out/Applications/Dusklight.app"
runHook postInstall
''
else
''
runHook preInstall
install -Dm755 dusklight "$out/bin/dusklight"
cp -r "$src/res" "$out/bin/res"
install -Dm644 "$src/platforms/freedesktop/dev.twilitrealm.dusk.desktop" \
"$out/share/applications/dev.twilitrealm.dusk.desktop"
for size in 16 32 48 64 128 256 512 1024; do
install -Dm644 "$src/platforms/freedesktop/''${size}x''${size}/apps/dev.twilitrealm.dusk.png" \
"$out/share/icons/hicolor/''${size}x''${size}/apps/dev.twilitrealm.dusk.png"
done
runHook postInstall
postUnpack = ''
chmod -R u+w "$sourceRoot"
substituteInPlace "$sourceRoot/extern/aurora/CMakeLists.txt" \
--replace-warn "add_subdirectory(tests)" ""
'';
dontStrip = true;
nativeBuildInputs = [
pkgs.cmake
pkgs.ninja
pkgs.pkg-config
pkgs.python3
pkgs.python3Packages.markupsafe
]
++ lib.optionals (!isDarwin) [ pkgs.autoPatchelfHook ];
meta = {
description = "Dusklight native PC port of the Twilight Princess decompilation";
homepage = "https://github.com/zeldaret/tp";
platforms = supportedSystems;
mainProgram = "dusklight";
};
};
buildInputs = [
pkgs.sdl3
pkgs.freetype
pkgs.zstd
pkgs.cxxopts
pkgs.nlohmann_json
pkgs.xxhash
pkgs.abseil-cpp
pkgs.zlib
pkgs.libpng
pkgs.libjpeg_turbo
pkgs.curl
pkgs.openssl
]
++ lib.optionals isDarwin [
pkgs.apple-sdk_15
pkgs.libiconv
]
++ lib.optionals (!isDarwin) [
pkgs.libGL
pkgs.libGLU
pkgs.libglvnd
pkgs.vulkan-loader
pkgs.libX11
pkgs.libxcb
pkgs.libXcursor
pkgs.libxi
pkgs.libxrandr
pkgs.libxscrnsaver
pkgs.libxtst
pkgs.libxinerama
pkgs.libxkbcommon
pkgs.wayland
pkgs.libdecor
pkgs.alsa-lib
pkgs.libpulseaudio
pkgs.pipewire
pkgs.dbus
pkgs.udev
pkgs.libusb1
pkgs.libunwind
pkgs.gtk3
nod
];
cmakeBuildType = "RelWithDebInfo";
ninjaFlags = [ "dusklight" ];
cmakeFlags = [
"-DDUSK_VERSION_OVERRIDE=${versionSuffix}"
"-DFETCHCONTENT_FULLY_DISCONNECTED=ON"
"-DAURORA_DAWN_PROVIDER=package"
"-DAURORA_DAWN_LINKAGE=static"
"-DAURORA_NOD_PROVIDER=system"
"-DAURORA_SDL3_PROVIDER=system"
"-DBUILD_SHARED_LIBS=OFF"
]
++ lib.mapAttrsToList (key: src: "-DFETCHCONTENT_SOURCE_DIR_${key}=${src}") fetchContentDirs;
installPhase =
if isDarwin then
''
runHook preInstall
mkdir -p "$out/Applications"
cp -r Dusklight.app "$out/Applications/Dusklight.app"
runHook postInstall
''
else
''
runHook preInstall
install -Dm755 dusklight "$out/bin/dusklight"
cp -r "$src/res" "$out/bin/res"
install -Dm644 "$src/platforms/freedesktop/dev.twilitrealm.dusk.desktop" \
"$out/share/applications/dev.twilitrealm.dusk.desktop"
for size in 16 32 48 64 128 256 512 1024; do
install -Dm644 "$src/platforms/freedesktop/''${size}x''${size}/apps/dev.twilitrealm.dusk.png" \
"$out/share/icons/hicolor/''${size}x''${size}/apps/dev.twilitrealm.dusk.png"
done
runHook postInstall
'';
postFixup = lib.optionalString (!isDarwin) ''
patchelf \
--add-needed "${pkgs.vulkan-loader}/lib/libvulkan.so" \
$out/bin/dusklight
'';
dontStrip = true;
meta = {
description = "Dusklight native PC port of the Twilight Princess decompilation";
homepage = "https://github.com/zeldaret/tp";
platforms = supportedSystems;
mainProgram = "dusklight";
};
};
# Tooling common to every supported host (Linux and macOS).
commonDevTools = [
+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;
+28 -3
View File
@@ -88,6 +88,10 @@ public:
/* 0x02C */ cXyz field_0x2c;
/* 0x038 */ cXyz field_0x38[60];
/* 0x308 */ cXyz field_0x308[60];
#if TARGET_PC
TGXTexObj mBlurTexObj;
ResTIMG* mpCachedBlurTex = nullptr;
#endif
}; // Size = 0x5D8
class dAlink_bottleWaterPcallBack_c : public JPAParticleCallBack {
@@ -3908,6 +3912,12 @@ 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);}
#endif
static daAlink_BckData const m_mainBckShield[20];
static daAlink_BckData const m_mainBckSword[5];
@@ -4551,7 +4561,8 @@ public:
#if TARGET_PC
void handleWolfHowl();
void handleQuickTransform();
bool checkGyroAimContext();
bool checkAimContext();
bool checkAimInputContext();
void onIronBallChainInterpCallback();
@@ -4564,6 +4575,18 @@ public:
cXyz mIBChainInterpCurrHandRoot;
bool mIBChainInterpPrevValid;
bool mIBChainInterpCurrValid;
cXyz mHsChainInterpPrevTop;
cXyz mHsChainInterpCurrTop;
cXyz mHsChainInterpPrevRoot;
cXyz mHsChainInterpCurrRoot;
cXyz mHsChainInterpPrevSubRoot;
cXyz mHsChainInterpCurrSubRoot;
cXyz mHsChainInterpPrevSubTop;
cXyz mHsChainInterpCurrSubTop;
bool mHsChainInterpPrevValid;
bool mHsChainInterpCurrValid;
bool mIsRollstab = false;
#endif
}; // Size: 0x385C
@@ -6374,7 +6397,8 @@ public:
class daAlinkHIO_huLight_c0 {
public:
static daAlinkHIO_huLight_c1 const m;
static daAlinkHIO_huLight_c1 IF_NOT_DUSK(const) m;
IF_DUSK(static daAlinkHIO_huLight_c1 const original;)
};
class daAlinkHIO_wlLight_c1 {
@@ -6448,7 +6472,8 @@ public:
class daAlinkHIO_kandelaar_c0 {
public:
static daAlinkHIO_kandelaar_c1 const m;
static daAlinkHIO_kandelaar_c1 IF_NOT_DUSK(const) m;
IF_DUSK(static daAlinkHIO_kandelaar_c1 const original;)
};
class daAlinkHIO_kandelaar_c : public daAlinkHIO_data_c {
+7 -2
View File
@@ -88,9 +88,14 @@ public:
/* 0x396A */ u8 field_0x396A[0x399E - 0x396A];
/* 0x399E */ s16 field_0x399e;
/* 0x39A0 */ u8 field_0x39A0[0x39A4 - 0x39A0];
#if TARGET_PC
/* 0x39A4 */ cM_rnd_c mMantRng;
#endif
};
#if TARGET_PC
STATIC_ASSERT(sizeof(mant_class) == 0x39ac);
#else
STATIC_ASSERT(sizeof(mant_class) == 0x39a4);
#endif
#endif /* D_A_MANT_H */
+7 -2
View File
@@ -299,8 +299,13 @@ public:
/* 0x168C */ u8 field_0x168c;
/* 0x168D */ u8 field_0x168d;
/* 0x168E */ u8 HIOInit;
#if TARGET_PC
cXyz mLineInterpPrev[MG_ROD_LURE_LINE_LEN];
cXyz mLineInterpCurr[MG_ROD_LURE_LINE_LEN];
bool mLineInterpPrevValid;
bool mLineInterpCurrValid;
#endif
};
STATIC_ASSERT(sizeof(dmg_rod_class) == 0x1690);
#endif /* D_A_MG_ROD_H */
+4 -1
View File
@@ -120,7 +120,10 @@ public:
BOOL chkAction(actionFunc action) { return action == mAction; }
static eventFunc mEvtSeqList[1];
#if TARGET_PC
// Keep track of last given bug for rando
static u8 mGivenInsectId;
#endif
private:
/* 0xB48 */ Z2Creature mSound;
/* 0xBD8 */ J3DModel* mpUmbrellaModel;
+9
View File
@@ -66,9 +66,18 @@ public:
/* 0x2CA7 */ s8 hide_lock;
/* 0x2CA8 */ cXyz field_0x2ca8;
/* 0x2CB4 */ u8 field_0x2cb4;
#if TARGET_PC
Mtx mChainInterpPrev[6][16];
Mtx mChainInterpCurr[6][16];
bool mChainInterpPrevValid;
bool mChainInterpCurrValid;
#endif
};
#if !TARGET_PC
STATIC_ASSERT(sizeof(obj_keyhole_class) == 0x2CB8);
#endif
class daObj_Keyhole_HIO_c : public JORReflexible {
public:
+4
View File
@@ -50,6 +50,10 @@ public:
/* 0x14 */ Mtx mProjMtx;
/* 0x44 */ ResTIMG* mpImg;
/* 0x48 */ u8* mpData;
#if TARGET_PC
TGXTexObj mTexObj;
ResTIMG* mpCachedImg = nullptr;
#endif
};
class daPy_boomerangMove_c {
+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); }
+10
View File
@@ -4,6 +4,10 @@
#include "JSystem/J3DGraphBase/J3DPacket.h"
#include "SSystem/SComponent/c_xyz.h"
#if TARGET_PC
#include "dusk/batch.hpp"
#endif
class cCcD_Obj;
class dCcMassS_HitInf;
class fopAc_ac_c;
@@ -107,6 +111,12 @@ public:
#if TARGET_PC
TGXTexObj mTexObj_l_J_Ohana00_64TEX;
TGXTexObj mTexObj_l_J_Ohana01_64128_0419TEX;
dusk::batch::LeafTemplate mTplHana00; // l_J_hana00DL
dusk::batch::LeafTemplate mTplHana00Cut; // l_J_hana00_cDL
dusk::batch::LeafTemplate mTplHana01; // l_J_hana01DL
dusk::batch::LeafTemplate mTplHana01Cut00; // l_J_hana01_c_00DL
dusk::batch::LeafTemplate mTplHana01Cut; // l_J_hana01_c_01DL
#endif
}; // Size: 0x12A54
+8
View File
@@ -4,6 +4,10 @@
#include "JSystem/J3DGraphBase/J3DPacket.h"
#include "SSystem/SComponent/c_xyz.h"
#if TARGET_PC
#include "../../../src/dusk/batch.hpp"
#endif
class cCcD_Obj;
class csXyz;
class dCcMassS_HitInf;
@@ -110,6 +114,10 @@ public:
#if TARGET_PC
TGXTexObj mTexObj_l_M_Hijiki00TEX;
TGXTexObj mTexObj_l_M_kusa05_RGBATEX;
dusk::batch::LeafTemplate mTplKusa9q; // l_M_Kusa_9qDL
dusk::batch::LeafTemplate mTplKusa9qCut; // l_M_Kusa_9q_cDL
dusk::batch::LeafTemplate mTplTengusa; // l_M_TenGusaDL
#endif
}; // Size: 0x1D718
+4
View File
@@ -114,6 +114,10 @@ public:
bool checkBoomWindTgTimer() { return mBoomWindTgTimer == 0; }
#if TARGET_PC
void setRandomizerItem(bool setFoolishItemModel = false);
#endif
static procFunc mFuncPtr[];
static const dCcD_SrcCyl m_cyl_src;
static 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 ResourceData const mData[23];
#if TARGET_PC
static ResourceData mRandoData[23];
#define M_SHOP_DATA (isRandomized() ? mRandoData : mData)
#else
#define M_SHOP_DATA mData
#endif
static f32 const m_cullfar_max;
enum {
+1
View File
@@ -1037,6 +1037,7 @@ public:
bool test1Camera(s32);
bool test2Camera(s32);
#if TARGET_PC
static bool isAimActive();
bool freeCamera();
bool executeDebugFlyCam();
void deactivateDebugFlyCam();
+104
View File
@@ -1,6 +1,10 @@
#ifndef D_COM_D_COM_INF_GAME_H
#define D_COM_D_COM_INF_GAME_H
#if TARGET_PC
#include "dusk/randomizer/game/randomizer_context.hpp"
#endif
#include "d/d_attention.h"
#include "d/d_cc_s.h"
#include "d/d_event.h"
@@ -466,6 +470,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(); }
@@ -1121,6 +1128,15 @@ void dComIfGs_setWarpItemData(char const* stage, cXyz pos, s16 angle, s8 roomNo,
u8 param_5);
BOOL dComIfGs_isStageSwitch(int i_stageNo, int i_no);
BOOL dComIfGs_isStageTbox(int i_stageNo, int i_no);
#if TARGET_PC
void dComIfGs_onStageTbox(int i_stageNo, int i_no);
void dComIfGs_offStageTbox(int i_stageNo, int i_no);
void dComIfGs_onStageItem(int i_stageNo, int i_no);
void dComIfGs_offStageItem(int i_stageNo, int i_no);
#endif
void dComIfGs_onStageSwitch(int i_stageNo, int i_no);
void dComIfGs_offStageSwitch(int i_stageNo, int i_no);
BOOL dComIfGs_isStageSwitch(int i_stageNo, int i_no);
@@ -1268,6 +1284,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;
}
@@ -1328,9 +1348,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);
@@ -1420,6 +1444,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);
}
@@ -1497,6 +1527,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,
@@ -1648,6 +1684,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;
}
@@ -1820,7 +1866,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);
}
@@ -1936,6 +1991,33 @@ 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);
}
inline void dComIfGs_onSaveTbox(int i_stageNo, int i_no) {
g_dComIfG_gameInfo.info.getSavedata().getSave(i_stageNo).getBit().onTbox(i_no);
}
inline void dComIfGs_offSaveTbox(int i_stageNo, int i_no) {
g_dComIfG_gameInfo.info.getSavedata().getSave(i_stageNo).getBit().offTbox(i_no);
}
inline void dComIfGs_onSaveItem(int i_no) {
g_dComIfG_gameInfo.info.getMemory().getBit().onItem(i_no);
}
inline void dComIfGs_offSaveItem(int i_no) {
g_dComIfG_gameInfo.info.getMemory().getBit().offItem(i_no);
}
#endif
inline BOOL dComIfGs_isSaveTbox(int i_stageNo, int i_no) {
return g_dComIfG_gameInfo.info.getSavedata().getSave(i_stageNo).getBit().isTbox(i_no);
}
@@ -2020,6 +2102,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();
}
@@ -2396,6 +2482,12 @@ inline void dComIfGs_onItem(int i_bitNo, int i_roomNo) {
g_dComIfG_gameInfo.info.onItem(i_bitNo, i_roomNo);
}
#if TARGET_PC
inline void dComIfGs_offItem(int i_bitNo, int i_roomNo) {
g_dComIfG_gameInfo.info.offItem(i_bitNo, i_roomNo);
}
#endif
inline bool dComIfGs_isItem(int i_bitNo, int i_roomNo) {
return g_dComIfG_gameInfo.info.isItem(i_bitNo, i_roomNo);
}
@@ -2452,6 +2544,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();
}
@@ -2496,6 +2594,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();
}
+30 -2
View File
@@ -203,6 +203,10 @@ 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
DATASELPROC_MENU_ARCHIPELAGO_CONNECT, // Wait for archipelago to connect
#endif
DATASELPROC_SELECT_DATA_OPENERASE_MOVE,
DATASELPROC_MENU_SELECT,
DATASELPROC_MENU_SELECT_MOVE_ANM,
@@ -287,6 +291,11 @@ public:
MEMCARDCHECKPROC_ERR_YESNO_CURSOR_MOVE_ANM,
MEMCARDCHECKPROC_SAVEDATA_CLEAR,
#if TARGET_PC
MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE,
MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE_ERR_WAIT,
#endif
#if PLATFORM_WII || PLATFORM_SHIELD
MEMCARDCHECKPROC_NAND_STAT_CHECK,
MEMCARDCHECKPROC_GAMEFILE_INIT_SEL,
@@ -326,6 +335,10 @@ public:
void makeRecInfo(u8);
void selectDataOpenMove();
void selectDataNameMove();
#if TARGET_PC
void selectDataPlayTypeMove();
void menuArchipelagoConnect();
#endif
void selectDataOpenEraseMove();
void menuSelect();
void menuSelectStart();
@@ -411,6 +424,10 @@ public:
bool yesnoWakuAlpahAnm(u8);
#if TARGET_PC
void fileSelectWide();
bool pointerDataSelect();
bool pointerMenuSelect();
bool pointerCopyDataToSelect();
bool pointerYesNoSelect(bool errorSelect);
#endif
void _draw();
void errorMoveAnmInitSet(int, int);
@@ -445,6 +462,10 @@ public:
void MemCardMakeGameFile();
void MemCardMakeGameFileWait();
void MemCardMakeGameFileCheck();
#if TARGET_PC
void MemCardAutoMakeGameFile();
void MemCardAutoMakeGameFileErrWait();
#endif
void MemCardMsgWindowInitOpen();
void MemCardMsgWindowOpen();
void MemCardMsgWindowClose();
@@ -719,7 +740,14 @@ public:
/* 0x2378 */ J2DPicture* mpFadePict;
#endif
#ifdef TARGET_PC
dDlst_FileSelFade_c mFadeDlst;
struct mDusk {
dDlst_FileSelFade_c mFadeDlst;
bool mStartNameAnm;
bool mBackToFileSelect;
bool mArchipelagoBeginConnect;
bool mArchiStartCloseFile;
int mPendingRmlCloseFrames{0};
} mDusk;
#endif
#if PLATFORM_WII || PLATFORM_SHIELD
@@ -730,7 +758,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
+135
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,24 @@ 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();
void item_func_ARCHIPELAGO_ITEM();
#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 +306,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 +343,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 +365,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 +427,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 +445,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 +482,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 +527,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 dItem_itemResource item_resource[255];
static dItem_fieldItemResource field_item_res[255];
static dItem_itemInfo item_info[255];
#if TARGET_PC
static dItem_itemResource item_resource_randomizer[255];
static dItem_fieldItemResource field_item_res_randomizer[255];
static 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_ARCHIPELAGO_ITEM_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 -1
View File
@@ -198,6 +198,7 @@ struct HOUSI_EFF {
/* 0x4C */ u16 field_0x4c;
}; // Size: 0x50
// Housi is the rising square particles in Twilight
class dKankyo_housi_Packet : public J3DPacket {
public:
virtual void draw();
@@ -208,7 +209,7 @@ public:
/* 0x0020 */ HOUSI_EFF mHousiEff[300];
/* 0x5DE0 */ u8 field_0x5de0[8];
/* 0x5DE8 */ f32 field_0x5de8;
/* 0x5DEC */ s16 field_0x5dec;
/* 0x5DEC */ s16 mHousiCount;
}; // Size: 0x5DF0
struct CLOUD_EFF {
+3
View File
@@ -157,6 +157,9 @@ public:
int getDispType() const;
void _move(f32, f32, int, f32);
void _draw();
#if TARGET_PC
bool refreshTextureSize();
#endif
virtual ~dMap_c() {
#if DEBUG
+2
View File
@@ -74,6 +74,8 @@ public:
#if TARGET_PC
void menuCollectWide();
bool pointerWait();
void pointerActivateCurrent();
#endif
void _create();
+4
View File
@@ -51,6 +51,10 @@ public:
void setBButtonString(u16);
void setHIO(bool);
#if TARGET_PC
bool pointerWait();
#endif
virtual void draw() { _draw(); }
virtual ~dMenu_Insect_c();
+4
View File
@@ -55,6 +55,10 @@ public:
u8 getLetterNum();
void setHIO(bool);
#if TARGET_PC
bool pointerWait();
#endif
virtual void draw() { _draw(); }
virtual ~dMenu_Letter_c();
+3
View File
@@ -80,6 +80,9 @@ public:
void setBButtonString(u16);
bool isRumbleSupported();
bool dpdMenuMove();
#if TARGET_PC
bool pointerConfirmSelect();
#endif
void paneResize(u64);
void initialize();
void yesnoMenuMoveAnmInitSet(int, int);
+6
View File
@@ -74,6 +74,10 @@ public:
void clacEllipsePlotAverage(int, f32, f32);
bool dpdMove();
u8 openExplain(u8);
#if TARGET_PC
void updateSlotImage(u8 slot);
bool pointerMove();
#endif
virtual void draw() { _draw(); }
virtual ~dMenu_Ring_c();
@@ -215,6 +219,8 @@ private:
bool mCursorInterpPrevAngular;
bool mCursorInterpCurrAngular;
bool mCursorInterpInit;
bool mPointerTouchPressHoveredCurrent;
J2DPicture* mDpadIcon;
#endif
};
+2
View File
@@ -266,6 +266,8 @@ public:
#if TARGET_PC
void menuSaveWide();
bool pointerSaveSelect();
bool pointerYesNoSelect(bool errorSelect, u8 errParam = 0, u8 soundParam = 0);
#endif
void _draw2();
+4
View File
@@ -49,6 +49,10 @@ public:
u8 getSkillNum();
void setHIO(bool);
#if TARGET_PC
bool pointerWait();
#endif
virtual void draw() { _draw(); }
virtual ~dMenu_Skill_c();
+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; }
+20 -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,9 @@ 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);
#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 +177,11 @@ 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*);
#endif
void initWord(fopAc_ac_c*, const char*, u8, int, fopAc_ac_c**);
@@ -185,8 +196,15 @@ public:
void setMsg(u32 msg) { mMsg = msg; }
bool checkEndFlow() { return (u32)field_0x26 == 1; }
static queryFunc mQueryList[53];
static eventFunc mEventList[43];
static queryFunc mQueryList[DUSK_IF_ELSE(54, 53)];
static eventFunc mEventList[DUSK_IF_ELSE(45, 43)];
#if TARGET_PC
// patch funcs for rando
void randoPatchNodeType(u8& type, 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;
+10
View File
@@ -360,7 +360,12 @@ inline void dMsgObject_demoMessageGroup() {
}
inline bool dMsgObject_isTalkNowCheck() {
#if TARGET_PC
dMsgObject_c* msgObject = dMsgObject_getMsgObjectClass();
return msgObject != NULL && msgObject->getStatus() != 1;
#else
return dMsgObject_getMsgObjectClass()->getStatus() == 1 ? false : true;
#endif
}
inline bool dMsgObject_isKillMessageFlag() {
@@ -497,7 +502,12 @@ inline void dMsgObject_onMsgSend() {
}
inline bool dMsgObject_isFukidashiCheck() {
#if TARGET_PC
dMsgObject_c* msgObject = dMsgObject_getMsgObjectClass();
return msgObject != NULL && msgObject->getScrnDrawPtr() != NULL;
#else
return dMsgObject_getMsgObjectClass()->getScrnDrawPtr() == NULL ? false : true;
#endif
}
inline void* dMsgObject_getTalkHeap() {
+4
View File
@@ -49,6 +49,10 @@ public:
void selectScale();
void selectTrans();
void selectAnimeTransform(int);
#if TARGET_PC
bool pointerMove();
bool consumePointerClick();
#endif
void setOffsetX(f32 i_offsetX) { mOffsetX = i_offsetX; }
bool isAnimeUpdate(int param_0) { return (field_0x114 & (u8)(1 << param_0)) ? TRUE : FALSE; }
+36
View File
@@ -10,6 +10,10 @@
#include "JSystem/JHostIO/JORReflexible.h"
#include "dusk/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();
@@ -960,6 +993,9 @@ public:
BOOL isSwitch(int i_no, int i_roomNo) const;
BOOL revSwitch(int i_no, int i_roomNo);
void onItem(int i_no, int i_roomNo);
#if TARGET_PC
void offItem(int i_no, int i_roomNo);
#endif
BOOL isItem(int i_no, int i_roomNo) const;
void onActor(int i_no, int i_roomNo);
void offActor(int i_no, int i_roomNo);
+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; }
+8
View File
@@ -9,6 +9,8 @@ namespace dusk {
enum class ActionBinds {
FIRST_PERSON_CAMERA,
CALL_MIDNA,
OPEN_MAP_SCREEN,
TOGGLE_MINIMAP,
OPEN_DUSKLIGHT_MENU,
TURBO_SPEED_BUTTON,
COUNT,
@@ -32,6 +34,12 @@ bool isActionBound(ActionBinds action, u32 port);
void updateActionBindings();
void setVirtualActionBind(ActionBinds action, u32 port, bool pressed, bool available = true);
void clearVirtualActionBind(ActionBinds action, u32 port);
void clearAllVirtualActionBinds();
bool getActionBindTrig(ActionBinds action, u32 port);
bool getActionBindHold(ActionBinds action, u32 port);
+9 -2
View File
@@ -4,6 +4,7 @@
#include "dolphin/types.h"
#include <type_traits>
#include <cstdlib>
#include <limits>
#include <string>
/**
@@ -139,11 +140,16 @@ concept ConfigValueInteger =
|| std::is_same_v<T, s64>
|| std::is_same_v<T, u64>;
template <typename T>
struct ConfigValueTraits {
static constexpr bool enabled = false;
};
/**
* \brief Concept that defines the legal set of types that can be used for CVar values.
*
* Valid types cannot be cv-qualified and must be basic primitive types (int, float, bool),
* strings, or enums of the basic primitives.
* strings, enums of the basic primitives, or explicitly-enabled structured settings.
*/
template <typename T>
concept ConfigValue =
@@ -154,7 +160,8 @@ concept ConfigValue =
|| std::is_same_v<T, f32>
|| std::is_same_v<T, f64>
|| std::is_same_v<T, std::string>
|| (std::is_enum_v<T> && ConfigValueInteger<std::underlying_type_t<T>>));
|| (std::is_enum_v<T> && ConfigValueInteger<std::underlying_type_t<T>>)
|| ConfigValueTraits<T>::enabled);
template <ConfigValue T>
const ConfigImplBase* GetConfigImpl();
+25
View File
@@ -7,12 +7,16 @@
#include <dolphin/gx/GXExtra.h>
#include "tracy/Tracy.hpp"
#if DUSK_GFX_DEBUG_GROUPS
#define GX_DEBUG_GROUP(name, ...) \
do { \
GXPushDebugGroup(#name); \
name(__VA_ARGS__); \
GXPopDebugGroup(); \
} while (0)
#else
#define GX_DEBUG_GROUP(name, ...) name(__VA_ARGS__)
#endif
#ifdef TARGET_PC
class GXTexObjRAII : public GXTexObj {
@@ -39,16 +43,37 @@ public:
static_assert(sizeof(GXTexObjRAII) == sizeof(GXTexObj),
"GXTexObjRAII should have the same size as GXTexObj");
typedef GXTexObjRAII TGXTexObj;
class GXTlutObjRAII : public GXTlutObj {
public:
GXTlutObjRAII() : GXTlutObj() {}
~GXTlutObjRAII() { GXDestroyTlutObj(this); }
void reset() { GXDestroyTlutObj(this); }
GXTlutObjRAII(const GXTlutObjRAII&) = delete;
GXTlutObjRAII& operator=(const GXTlutObjRAII&) = delete;
GXTlutObjRAII(GXTlutObjRAII&&) = delete;
GXTlutObjRAII& operator=(GXTlutObjRAII&&) = delete;
};
static_assert(sizeof(GXTlutObjRAII) == sizeof(GXTlutObj),
"GXTlutObjRAII should have the same size as GXTlutObj");
typedef GXTlutObjRAII TGXTlutObj;
#else
typedef GXTexObj TGXTexObj;
typedef GXTlutObj TGXTlutObj;
#endif
struct GXScopedDebugGroup {
explicit GXScopedDebugGroup(const char* text) {
#if DUSK_GFX_DEBUG_GROUPS
GXPushDebugGroup(text);
#endif
}
~GXScopedDebugGroup() {
#if DUSK_GFX_DEBUG_GROUPS
GXPopDebugGroup();
#endif
}
};
+1 -4
View File
@@ -1,5 +1,4 @@
#ifndef DUSK_GYRO_H
#define DUSK_GYRO_H
#pragma once
namespace dusk::gyro {
void read(float dt);
@@ -14,5 +13,3 @@ bool get_sensor_keep_alive();
void set_sensor_keep_alive(bool value);
bool rollgoal_gyro_enabled();
} // namespace dusk::gyro
#endif
+65
View File
@@ -0,0 +1,65 @@
#pragma once
#include "dolphin/types.h"
class CPaneMgr;
namespace dusk::menu_pointer {
using TargetId = u16;
constexpr TargetId InvalidTarget = 0xffff;
enum class Context {
None,
FileSelect,
Save,
ItemWheel,
Collection,
Options,
Dialog,
};
enum class Phase {
Move,
Press,
Release,
Cancel,
};
struct State {
f32 x = 0.0f;
f32 y = 0.0f;
bool valid = false;
bool down = false;
bool pressed = false;
bool released = false;
bool clicked = false;
bool touch = false;
};
void begin_game_frame() noexcept;
void end_game_frame() noexcept;
void begin_context(Context context) noexcept;
bool handle_fallthrough_pointer(f32 x, f32 y, Phase phase, bool touch, s32 mouseButton = -1) noexcept;
bool active() noexcept;
bool enabled() noexcept;
bool mouse_capture_active() noexcept;
const State& state() noexcept;
void set_hover_target(TargetId target) noexcept;
bool consume_click() noexcept;
bool peek_click() noexcept;
void set_dialog_choice(u8 choice, bool clicked) noexcept;
bool get_dialog_choice(u8& choice) noexcept;
bool consume_dialog_click(u8& choice) noexcept;
void defer_activation(Context context, TargetId target) noexcept;
bool consume_deferred_activation(Context context, TargetId target) noexcept;
void clear_deferred_activation(Context context) noexcept;
u32 suppressed_pad_buttons(u32 port) noexcept;
void finish_pad_suppression_read(u32 port) noexcept;
bool hit_rect(f32 left, f32 top, f32 right, f32 bottom, f32 padding = 0.0f) noexcept;
bool hit_pane(CPaneMgr* pane, f32 padding = 0.0f) noexcept;
bool hit_pane(J2DPane* pane, f32 padding = 0.0f) noexcept;
} // namespace dusk::menu_pointer
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include <SDL3/SDL_events.h>
namespace dusk::mouse {
void read();
void getAimDeltas(float& out_yaw, float& out_pitch);
void getCameraDeltas(float& out_yaw, float& out_pitch);
void handle_event(const SDL_Event& event) noexcept;
void onFocusLost();
void onFocusGained();
} // namespace dusk::mouse
+90 -19
View File
@@ -1,9 +1,9 @@
#ifndef DUSK_CONFIG_H
#define DUSK_CONFIG_H
#pragma once
#include <array>
#include "dusk/config_var.hpp"
#include "dusk/ui/controls.hpp"
namespace dusk {
@@ -40,23 +40,32 @@ enum class DiscVerificationState : u8 {
HashMismatch,
};
enum class GyroMode : u8 {
Sensor = 0,
Mouse = 1,
};
enum class FrameInterpMode : u8 {
Off = 0,
Capped = 1,
Unlimited = 2,
};
enum class TouchTargeting : u8 {
Hybrid = 0,
Hold = 1,
Switch = 2,
};
enum class MenuScaling : u8 {
GameCube = 0,
Wii = 1,
Dusklight = 2,
};
enum class MagicArmorMode : u8 {
NORMAL = 0,
ON_DAMAGE = 1,
DOUBLE_DEFENSE = 2,
INVINCIBLE = 3,
COSMETIC = 4,
};
namespace config {
template <>
struct ConfigEnumRange<BloomMode> {
@@ -88,23 +97,34 @@ struct ConfigEnumRange<DiscVerificationState> {
static constexpr auto max = DiscVerificationState::HashMismatch;
};
template <>
struct ConfigEnumRange<GyroMode> {
static constexpr auto min = GyroMode::Sensor;
static constexpr auto max = GyroMode::Mouse;
};
template <>
struct ConfigEnumRange<FrameInterpMode> {
static constexpr auto min = FrameInterpMode::Off;
static constexpr auto max = FrameInterpMode::Unlimited;
};
template <>
struct ConfigEnumRange<TouchTargeting> {
static constexpr auto min = TouchTargeting::Hybrid;
static constexpr auto max = TouchTargeting::Switch;
};
template <>
struct ConfigEnumRange<MenuScaling> {
static constexpr auto min = MenuScaling::GameCube;
static constexpr auto max = MenuScaling::Dusklight;
};
template <>
struct ConfigEnumRange<MagicArmorMode> {
static constexpr auto min = MagicArmorMode::NORMAL;
static constexpr auto max = MagicArmorMode::COSMETIC;
};
template <>
struct ConfigValueTraits<ui::ControlLayout> {
static constexpr bool enabled = true;
};
} // namespace config
// Persistent user settings
@@ -120,6 +140,9 @@ struct UserSettings {
ConfigVar<bool> enableFpsOverlay;
ConfigVar<int> fpsOverlayCorner;
ConfigVar<int> maxFrameRate;
ConfigVar<bool> rememberWindowSize;
ConfigVar<int> lastWindowWidth;
ConfigVar<int> lastWindowHeight;
} video;
struct {
@@ -153,6 +176,7 @@ struct UserSettings {
ConfigVar<bool> noMissClimbing;
ConfigVar<bool> fastTears;
ConfigVar<bool> no2ndFishForCat;
ConfigVar<bool> buttonFishing;
ConfigVar<bool> instantSaves;
ConfigVar<bool> instantText;
ConfigVar<bool> sunsSong;
@@ -162,6 +186,7 @@ struct UserSettings {
// Preferences
ConfigVar<bool> enableMirrorMode;
ConfigVar<bool> minimalHUD;
ConfigVar<float> hudScale;
ConfigVar<bool> pauseOnFocusLost;
ConfigVar<bool> enableLinkDollRotation;
ConfigVar<bool> enableAchievementToasts;
@@ -187,7 +212,6 @@ struct UserSettings {
ConfigVar<bool> midnasLamentNonStop;
// Input
ConfigVar<GyroMode> gyroMode;
ConfigVar<bool> enableGyroAim;
ConfigVar<bool> enableGyroRollgoal;
ConfigVar<float> gyroSensitivityX;
@@ -197,7 +221,16 @@ struct UserSettings {
ConfigVar<float> gyroDeadband;
ConfigVar<bool> gyroInvertPitch;
ConfigVar<bool> gyroInvertYaw;
ConfigVar<bool> enableMouseCamera;
ConfigVar<bool> enableMouseAim;
ConfigVar<float> mouseAimSensitivity;
ConfigVar<float> mouseCameraSensitivity;
ConfigVar<bool> invertMouseY;
ConfigVar<bool> freeCamera;
ConfigVar<bool> enableTouchControls;
ConfigVar<TouchTargeting> touchTargeting;
ConfigVar<bool> enableMenuPointer;
ConfigVar<ui::ControlLayout> touchControlsLayout;
ConfigVar<bool> invertCameraXAxis;
ConfigVar<bool> invertCameraYAxis;
ConfigVar<bool> invertFirstPersonXAxis;
@@ -206,6 +239,8 @@ struct UserSettings {
ConfigVar<bool> invertAirSwimY;
ConfigVar<float> freeCameraXSensitivity;
ConfigVar<float> freeCameraYSensitivity;
ConfigVar<float> touchCameraXSensitivity;
ConfigVar<float> touchCameraYSensitivity;
ConfigVar<bool> debugFlyCam;
ConfigVar<bool> debugFlyCamLockEvents;
ConfigVar<bool> allowBackgroundInput;
@@ -228,7 +263,7 @@ struct UserSettings {
ConfigVar<bool> canTransformAnywhere;
ConfigVar<bool> fastRoll;
ConfigVar<bool> fastSpinner;
ConfigVar<bool> freeMagicArmor;
ConfigVar<MagicArmorMode> armorRupeeDrain;
ConfigVar<bool> invincibleEnemies;
// Technical
@@ -243,6 +278,8 @@ struct UserSettings {
ConfigVar<bool> liveSplitEnabled;
ConfigVar<bool> showSpeedrunRTATimer;
ConfigVar<bool> recordingMode;
// Misc
ConfigVar<bool> removeQuestMapMarkers;
ConfigVar<bool> showInputViewer;
ConfigVar<bool> showInputViewerGyro;
@@ -253,7 +290,6 @@ struct UserSettings {
ConfigVar<DiscVerificationState> isoVerification;
ConfigVar<std::string> graphicsBackend;
ConfigVar<bool> skipPreLaunchUI;
ConfigVar<bool> showPipelineCompilation;
ConfigVar<bool> wasPresetChosen;
ConfigVar<bool> checkForUpdates;
ConfigVar<int> cardFileType;
@@ -264,9 +300,46 @@ struct UserSettings {
struct {
std::array<ActionBindConfigVar, 4> firstPersonCamera;
std::array<ActionBindConfigVar, 4> callMidna;
std::array<ActionBindConfigVar, 4> openMapScreen;
std::array<ActionBindConfigVar, 4> toggleMinimap;
std::array<ActionBindConfigVar, 4> openDusklightMenu;
std::array<ActionBindConfigVar, 4> turboSpeedButton;
} actionBindings;
// Randomizer seed hashes, 1 per file
struct {
std::array<ConfigVar<std::string>, 3> seedHashes;
} randomizer;
// Archipelago Settings
struct {
std::array<ConfigVar<std::string>, 3> savesServerIP;
std::array<ConfigVar<std::string>, 3> savesServerPass;
std::array<ConfigVar<std::string>, 3> savesSlotName;
} archipelago;
// Cosmetics
struct {
ConfigVar<std::string> herosTunicCapColor;
ConfigVar<std::string> herosTunicTorsoColor;
ConfigVar<std::string> herosTunicSkirtColor;
ConfigVar<std::string> zoraArmorCapColor;
ConfigVar<std::string> zoraArmorHelmetColor;
ConfigVar<std::string> zoraArmorTorsoColor;
ConfigVar<std::string> zoraArmorScalesColor;
ConfigVar<std::string> zoraArmorFlippersColor;
ConfigVar<std::string> lanternGlowColor;
ConfigVar<std::string> woodenSwordColor;
ConfigVar<std::string> msBladeColor;
ConfigVar<std::string> msHandleColor;
ConfigVar<std::string> lightSwordGlowColor;
ConfigVar<std::string> boomerangColor;
ConfigVar<std::string> ironBootsColor;
ConfigVar<std::string> spinnerColor;
ConfigVar<std::string> linkHairColor;
ConfigVar<std::string> wolfLinkColor;
ConfigVar<std::string> eponaColor;
} cosmetics;
};
UserSettings& getSettings();
@@ -295,6 +368,4 @@ struct TransientSettings {
TransientSettings& getTransientSettings();
}
#endif // DUSK_CONFIG_H
} // namespace dusk
+12
View File
@@ -0,0 +1,12 @@
#pragma once
namespace dusk::touch_camera {
constexpr float YAW_DEGREES_PER_DP = 0.34f;
constexpr float PITCH_DEGREES_PER_DP = 0.22f;
void add_delta(float yaw_dp, float pitch_dp) noexcept;
bool consume_delta(float& yaw_dp, float& pitch_dp) noexcept;
void clear() noexcept;
} // namespace dusk::touch_camera
+3
View File
@@ -398,4 +398,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;
+1 -1
View File
@@ -44,7 +44,7 @@ struct mDoLib_clipper {
void mDoLib_project(Vec* src, Vec* dst);
u32 mDoLib_setResTimgObj(ResTIMG const* res, TGXTexObj* o_texObj, u32 tlut_name,
GXTlutObj* o_tlutObj);
TGXTlutObj* o_tlutObj);
void mDoLib_pos2camera(Vec* src, Vec* dst);
#if PLATFORM_WII
+41 -16
View File
@@ -952,45 +952,70 @@ if(DEFINED APPLE_TARGET_TRIPLE)
set(APPLE_TARGET_TRIPLE_FLAG "-target ${APPLE_TARGET_TRIPLE}")
endif()
function(ios_toolchain_set_cached_flags variable description)
set(clean_flags "${${variable}}")
foreach(toolchain_flag IN LISTS ARGN)
if(NOT "${toolchain_flag}" STREQUAL "")
string(REPLACE "${toolchain_flag}" "" clean_flags "${clean_flags}")
endif()
endforeach()
string(REGEX REPLACE "[ \t]+" " " clean_flags "${clean_flags}")
string(STRIP "${clean_flags}" clean_flags)
set(final_flags "")
foreach(toolchain_flag IN LISTS ARGN)
if(NOT "${toolchain_flag}" STREQUAL "")
string(APPEND final_flags " ${toolchain_flag}")
endif()
endforeach()
if(NOT "${clean_flags}" STREQUAL "")
string(APPEND final_flags " ${clean_flags}")
endif()
string(REGEX REPLACE "[ \t]+" " " final_flags "${final_flags}")
string(STRIP "${final_flags}" final_flags)
set(${variable} "${final_flags}" CACHE INTERNAL "${description}")
endfunction()
#Check if Xcode generator is used since that will handle these flags automagically
if(CMAKE_GENERATOR MATCHES "Xcode")
message(STATUS "Not setting any manual command-line buildflags, since Xcode is selected as the generator. Modifying the Xcode build-settings directly instead.")
else()
set(CMAKE_C_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_C_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all C build types.")
ios_toolchain_set_cached_flags(CMAKE_C_FLAGS "Flags used by the compiler during all C build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${OBJC_LEGACY_VARS}" "${BITCODE}" "${VISIBILITY}")
set(CMAKE_C_FLAGS_DEBUG "-O0 -g ${CMAKE_C_FLAGS_DEBUG}")
set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_C_FLAGS_MINSIZEREL}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_C_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_CXX_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all CXX build types.")
ios_toolchain_set_cached_flags(CMAKE_CXX_FLAGS "Flags used by the compiler during all CXX build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${OBJC_LEGACY_VARS}" "${BITCODE}" "${VISIBILITY}")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g ${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_CXX_FLAGS_MINSIZEREL}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_CXX_FLAGS_RELEASE}")
if(NAMED_LANGUAGE_SUPPORT_INT)
set(CMAKE_OBJC_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJC_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all OBJC build types.")
ios_toolchain_set_cached_flags(CMAKE_OBJC_FLAGS "Flags used by the compiler during all OBJC build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${BITCODE}" "${VISIBILITY}" "${FOBJC_ARC}" "${OBJC_VARS}")
set(CMAKE_OBJC_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJC_FLAGS_DEBUG}")
set(CMAKE_OBJC_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJC_FLAGS_MINSIZEREL}")
set(CMAKE_OBJC_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJC_FLAGS_RELWITHDEBINFO}")
set(CMAKE_OBJC_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJC_FLAGS_RELEASE}")
set(CMAKE_OBJCXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJCXX_FLAGS}" CACHE INTERNAL
"Flags used by the compiler during all OBJCXX build types.")
ios_toolchain_set_cached_flags(CMAKE_OBJCXX_FLAGS "Flags used by the compiler during all OBJCXX build types."
"${C_TARGET_FLAGS}" "${APPLE_TARGET_TRIPLE_FLAG}" "${SDK_NAME_VERSION_FLAGS}" "${BITCODE}" "${VISIBILITY}" "${FOBJC_ARC}" "${OBJC_VARS}")
set(CMAKE_OBJCXX_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJCXX_FLAGS_DEBUG}")
set(CMAKE_OBJCXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJCXX_FLAGS_MINSIZEREL}")
set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_OBJCXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJCXX_FLAGS_RELEASE}")
endif()
set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all C link types.")
set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all CXX link types.")
ios_toolchain_set_cached_flags(CMAKE_C_LINK_FLAGS "Flags used by the compiler for all C link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
ios_toolchain_set_cached_flags(CMAKE_CXX_LINK_FLAGS "Flags used by the compiler for all CXX link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
if(NAMED_LANGUAGE_SUPPORT_INT)
set(CMAKE_OBJC_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJC_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all OBJC link types.")
set(CMAKE_OBJCXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJCXX_LINK_FLAGS}" CACHE INTERNAL
"Flags used by the compiler for all OBJCXX link types.")
ios_toolchain_set_cached_flags(CMAKE_OBJC_LINK_FLAGS "Flags used by the compiler for all OBJC link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
ios_toolchain_set_cached_flags(CMAKE_OBJCXX_LINK_FLAGS "Flags used by the compiler for all OBJCXX link types."
"${C_TARGET_FLAGS}" "${SDK_NAME_VERSION_FLAGS}" "-Wl,-search_paths_first")
endif()
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp" CACHE INTERNAL
"Flags used by the compiler for all ASM build types.")
@@ -212,6 +212,9 @@ public:
void setCornerColor(JUtility::TColor c0) {
setCornerColor(c0, c0, c0, c0);
}
#if TARGET_PC
JUtility::TColor corner(size_t index) const { return mCornerColor[index]; }
#endif
protected:
/* 0x100 */ JUTTexture* mTexture[2];
@@ -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; }
@@ -1,6 +1,7 @@
#ifndef J3DSHAPEDRAW_H
#define J3DSHAPEDRAW_H
#include <gx.h>
#include <types.h>
/**
@@ -12,6 +13,9 @@ public:
u32 countVertex(u32);
void addTexMtxIndexInDL(u32, u32, u32);
J3DShapeDraw(u8 const*, u32);
#if TARGET_PC
J3DShapeDraw(u8 const*, u32, const GXVtxDescList*);
#endif
void draw() const;
virtual ~J3DShapeDraw();
@@ -3,6 +3,20 @@
#include <gx.h>
#if TARGET_PC
#include <mtx.h>
struct ParticleDrawCtx {
bool batch; // off = immediate mode
bool useTexMtx; // UVs transformed by texMtx
bool useClr0; // prm color in GX_VA_CLR0
bool useClr1; // env color in GX_VA_CLR1
Mtx texMtx;
GXColor clr0;
GXColor clr1;
};
#endif
struct JPAEmitterWorkData;
class JPABaseParticle;
class JKRHeap;
@@ -75,6 +89,9 @@ public:
const GXTevColorArg* getTevColorArg() const { return st_ca[(pBsd->mFlags >> 0x0F) & 0x07]; }
const GXTevAlphaArg* getTevAlphaArg() const { return st_aa[(pBsd->mFlags >> 0x12) & 0x01]; }
#if TARGET_PC
u32 getTevColorArgSel() const { return (pBsd->mFlags >> 0x0F) & 0x07; }
#endif
u32 getType() const { return (pBsd->mFlags >> 0) & 0x0F; }
u32 getDirType() const { return (pBsd->mFlags >> 4) & 0x07; }
@@ -186,26 +203,34 @@ void JPARegistPrm(JPAEmitterWorkData*);
void JPARegistEnv(JPAEmitterWorkData*);
void JPARegistPrmEnv(JPAEmitterWorkData*);
void JPADrawPoint(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawLine(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotDirection(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawDirection(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotation(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawDBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawRotYBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawYBillboard(JPAEmitterWorkData*, JPABaseParticle*);
void JPADrawParticleCallBack(JPAEmitterWorkData*, JPABaseParticle*);
void JPALoadTexAnm(JPAEmitterWorkData*, JPABaseParticle*);
void JPASetPointSize(JPAEmitterWorkData*, JPABaseParticle*);
void JPASetLineWidth(JPAEmitterWorkData*, JPABaseParticle*);
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistAlpha(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistEnv(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistPrmAlpha(JPAEmitterWorkData*, JPABaseParticle*);
void JPARegistPrmAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*);
#if TARGET_PC
#define JPA_DRAW_PARTICLE_ARGS JPAEmitterWorkData*, JPABaseParticle*, ParticleDrawCtx*
#else
#define JPA_DRAW_PARTICLE_ARGS JPAEmitterWorkData*, JPABaseParticle*
#endif
void JPADrawPoint(JPA_DRAW_PARTICLE_ARGS);
void JPADrawLine(JPA_DRAW_PARTICLE_ARGS);
void JPADrawRotBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawRotDirection(JPA_DRAW_PARTICLE_ARGS);
void JPADrawDirection(JPA_DRAW_PARTICLE_ARGS);
void JPADrawRotation(JPA_DRAW_PARTICLE_ARGS);
void JPADrawDBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawRotYBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawYBillboard(JPA_DRAW_PARTICLE_ARGS);
void JPADrawParticleCallBack(JPA_DRAW_PARTICLE_ARGS);
void JPALoadTexAnm(JPA_DRAW_PARTICLE_ARGS);
void JPASetPointSize(JPA_DRAW_PARTICLE_ARGS);
void JPASetLineWidth(JPA_DRAW_PARTICLE_ARGS);
void JPALoadCalcTexCrdMtxAnm(JPA_DRAW_PARTICLE_ARGS);
void JPARegistAlpha(JPA_DRAW_PARTICLE_ARGS);
void JPARegistEnv(JPA_DRAW_PARTICLE_ARGS);
void JPARegistAlphaEnv(JPA_DRAW_PARTICLE_ARGS);
void JPARegistPrmAlpha(JPA_DRAW_PARTICLE_ARGS);
void JPARegistPrmAlphaEnv(JPA_DRAW_PARTICLE_ARGS);
#undef JPA_DRAW_PARTICLE_ARGS
#if TARGET_PC
void JPAInterpBillboard(JPAEmitterWorkData*, JPABaseParticle*);
@@ -17,6 +17,10 @@ class JPADynamicsBlock;
class JPAFieldBlock;
class JPAKeyBlock;
#if TARGET_PC
struct ParticleDrawCtx;
#endif
/**
* @ingroup jsystem-jparticle
*
@@ -50,13 +54,19 @@ public:
public:
typedef void (*EmitterFunc)(JPAEmitterWorkData*);
typedef void (*ParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*);
#if TARGET_PC
typedef void (*DrawParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*,
ParticleDrawCtx*);
#else
typedef ParticleFunc DrawParticleFunc;
#endif
/* 0x00 */ EmitterFunc* mpCalcEmitterFuncList;
/* 0x04 */ EmitterFunc* mpDrawEmitterFuncList;
/* 0x08 */ EmitterFunc* mpDrawEmitterChildFuncList;
/* 0x0C */ ParticleFunc* mpCalcParticleFuncList;
/* 0x10 */ ParticleFunc* mpDrawParticleFuncList;
/* 0x10 */ DrawParticleFunc* mpDrawParticleFuncList;
/* 0x14 */ ParticleFunc* mpCalcParticleChildFuncList;
/* 0x18 */ ParticleFunc* mpDrawParticleChildFuncList;
/* 0x18 */ DrawParticleFunc* mpDrawParticleChildFuncList;
/* 0x1C */ JPABaseShape* pBsp;
/* 0x20 */ JPAExtraShape* pEsp;
@@ -77,6 +87,20 @@ public:
/* 0x45 */ u8 mpDrawParticleFuncListNum;
/* 0x46 */ u8 mpCalcParticleChildFuncListNum;
/* 0x47 */ u8 mpDrawParticleChildFuncListNum;
#if TARGET_PC
struct BatchInfo {
f32 vtxPos[8][3];
f32 vtxUv[8][2];
u8 vtxCount; // 4 (quad) or 8 (cross)
bool supported; // draw func list contains only batchable funcs
bool hasPtclColor; // per-particle JPARegist* func is present
bool hasPtclTexMtx; // JPALoadCalcTexCrdMtxAnm is present
};
BatchInfo mBatchInfo;
void initBatchInfo();
#endif
};
#endif /* JPARESOURCE_H */
@@ -3,6 +3,8 @@
#include "JSystem/J2DGraph/J2DGrafContext.h"
#include <gx.h>
#include <tracy/Tracy.hpp>
J2DGrafContext::J2DGrafContext(f32 x, f32 y, f32 width, f32 height)
: mBounds(x, y, x + width, y + height), mScissorBounds(x, y, x + width, y + height) {
if (x < 0.0f || y < 0.0f) {
@@ -137,6 +139,7 @@ void J2DGrafContext::setLineWidth(u8 lineWidth) {
}
void J2DGrafContext::fillBox(JGeometry::TBox2<f32> const& box) {
ZoneScoped;
GXSetBlendMode((GXBlendMode)mBoxPart.mType, (GXBlendFactor)mBoxPart.mSrcFactor,
(GXBlendFactor)mBoxPart.mDstFactor, GX_LO_SET);
GXLoadPosMtxImm(mPosMtx, 0);
@@ -155,6 +158,7 @@ void J2DGrafContext::fillBox(JGeometry::TBox2<f32> const& box) {
}
void J2DGrafContext::drawFrame(JGeometry::TBox2<f32> const& box) {
ZoneScoped;
GXSetBlendMode((GXBlendMode)mBoxPart.mType, (GXBlendFactor)mBoxPart.mSrcFactor,
(GXBlendFactor)mBoxPart.mDstFactor, GX_LO_SET);
GXLoadPosMtxImm(mPosMtx, 0);
@@ -175,6 +179,7 @@ void J2DGrafContext::drawFrame(JGeometry::TBox2<f32> const& box) {
}
void J2DGrafContext::line(JGeometry::TVec2<f32> start, JGeometry::TVec2<f32> end) {
ZoneScoped;
GXSetBlendMode((GXBlendMode)mLinePart.mType, (GXBlendFactor)mLinePart.mSrcFactor,
(GXBlendFactor)mLinePart.mDstFactor, GX_LO_SET);
GXLoadPosMtxImm(mPosMtx, 0);
@@ -542,8 +542,11 @@ void J3DModel::viewCalc() {
}
#ifdef TARGET_PC
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
dusk::frame_interp::record_final_mtx(getDrawMtxPtr()[i]);
Mtx* drawMtx = getDrawMtxPtr();
if (drawMtx != J3DMtxBuffer::sNoUseDrawMtxPtr) {
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
dusk::frame_interp::record_final_mtx(drawMtx[i]);
}
}
#endif
+2 -2
View File
@@ -136,8 +136,8 @@ void J3DLoadCPCmd(u8 addr, u32 val) {
#if TARGET_PC
static void J3DLoadArrayBasePtr(GXAttr attr, void* data, u32 size, bool le) {
u32 idx = (attr == GX_VA_NBT) ? 1 : (attr - GX_VA_POS);
GXCmd1u8(GX_LOAD_AURORA);
GXCmd1u16(GX_LOAD_AURORA_ARRAYBASE | idx);
GXCmd1u8(GX_AURORA);
GXCmd1u16(GX_AURORA_LOAD_ARRAYBASE | idx);
GXCmd1u64((u64)data);
GXCmd1u32(size);
GXCmd1u8(le ? 1 : 0);
+101 -4
View File
@@ -1,15 +1,47 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include <cstring>
#include <gx.h>
#include <stdint.h>
#include "JSystem/J3DGraphBase/J3DShapeDraw.h"
#include "JSystem/JKernel/JKRHeap.h"
#include <cstring>
#include <stdint.h>
#include <gx.h>
#if TARGET_PC
#include <aurora/dl.hpp>
#include <tracy/Tracy.hpp>
namespace {
void set_display_list_copy(void*& displayList, u32& displayListSize, const u8* data, u32 size) {
const u32 alignedSize = ALIGN_NEXT(size, 0x20);
u8* newDL = JKR_NEW_ARRAY_ARGS(u8, alignedSize, 0x20);
if (size != 0) {
std::memcpy(newDL, data, size);
}
for (u32 i = size; i < alignedSize; i++) {
newDL[i] = 0;
}
displayList = newDL;
displayListSize = alignedSize;
DCStoreRange(newDL, displayListSize);
}
} // namespace
#endif
u32 J3DShapeDraw::countVertex(u32 stride) {
u32 count = 0;
u8* dlStart = (u8*)getDisplayList();
#if TARGET_PC
aurora::gx::dl::Reader reader{dlStart, getDisplayListSize(), static_cast<u8>(stride)};
while (const auto cmd = reader.next()) {
if (cmd->kind != aurora::gx::dl::Command::Kind::Passthrough) {
count += cmd->draw.vtxCount;
}
}
#else
for (u8* dl = dlStart; (dl - dlStart) < getDisplayListSize();) {
u8 cmd = *(u8*)dl;
dl++;
@@ -20,10 +52,58 @@ u32 J3DShapeDraw::countVertex(u32 stride) {
count += vtxNum;
dl = (u8*)dl + stride * vtxNum;
}
#endif
return count;
}
#if TARGET_PC
void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
u32 byteNum = countVertex(stride);
u32 oldSize = mDisplayListSize;
u32 newSize = ALIGN_NEXT(oldSize + byteNum, 0x20);
u8* newDLStart = JKR_NEW_ARRAY_ARGS(u8, newSize, 0x20);
u8* oldDLStart = (u8*)mDisplayList;
u8* newDL = newDLStart;
aurora::gx::dl::Reader reader{oldDLStart, mDisplayListSize, static_cast<u8>(stride)};
while (const auto cmd = reader.next()) {
if (cmd->kind == aurora::gx::dl::Command::Kind::Passthrough) {
std::memcpy(newDL, cmd->data, cmd->size);
newDL += cmd->size;
continue;
}
const auto& draw = cmd->draw;
const u32 headerSize = draw.vertices - cmd->data;
std::memcpy(newDL, cmd->data, headerSize);
newDL += headerSize;
for (u32 i = 0; i < draw.vtxCount; i++) {
const u8* oldVtx = draw.vertices + stride * i;
u8 pnmtxidx = oldVtx[0];
std::memcpy(newDL, oldVtx, attrOffs);
newDL += attrOffs;
*newDL++ = valueBase + pnmtxidx;
std::memcpy(newDL, oldVtx + attrOffs, stride - attrOffs);
newDL += stride - attrOffs;
}
}
if (reader.failed()) {
// preserve the remainder untouched
std::memcpy(newDL, oldDLStart + reader.pos(), mDisplayListSize - reader.pos());
newDL += mDisplayListSize - reader.pos();
}
u32 realSize = ALIGN_NEXT((uintptr_t)newDL - (uintptr_t)newDLStart, 0x20);
for (; (newDL - newDLStart) < newSize; newDL++)
*newDL = 0;
mDisplayListSize = realSize;
mDisplayList = newDLStart;
DCStoreRange(newDLStart, mDisplayListSize);
}
#else
void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
u32 byteNum = countVertex(stride);
u32 oldSize = mDisplayListSize;
@@ -69,13 +149,30 @@ void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
mDisplayList = newDLStart;
DCStoreRange(newDLStart, mDisplayListSize);
}
#endif
J3DShapeDraw::J3DShapeDraw(const u8* displayList, u32 displayListSize) {
#if TARGET_PC
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
#else
mDisplayList = (void*)displayList;
mDisplayListSize = displayListSize;
#endif
}
#if TARGET_PC
J3DShapeDraw::J3DShapeDraw(
const u8* displayList, u32 displayListSize, const GXVtxDescList* vtxDesc) {
if (const auto optimized = aurora::gx::dl::optimize(displayList, displayListSize, vtxDesc)) {
set_display_list_copy(mDisplayList, mDisplayListSize, optimized->data(), optimized->size());
} else {
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
}
}
#endif
void J3DShapeDraw::draw() const {
ZoneScoped;
GXCallDisplayList(mDisplayList, mDisplayListSize);
}
@@ -132,7 +132,12 @@ J3DShapeDraw* J3DShapeFactory::newShapeDraw(int shapeNo, int mtxGroupNo) const {
const J3DShapeInitData& shapeInitData = mShapeInitData[mIndexTable[shapeNo]];
const J3DShapeDrawInitData& drawInitData =
(&mDrawInitData[shapeInitData.mDrawInitDataIndex])[mtxGroupNo];
#if TARGET_PC
shapeDraw = JKR_NEW J3DShapeDraw(&mDisplayListData[drawInitData.mDisplayListIndex], drawInitData.mDisplayListSize,
getVtxDescList(shapeNo));
#else
shapeDraw = JKR_NEW J3DShapeDraw(&mDisplayListData[drawInitData.mDisplayListIndex], drawInitData.mDisplayListSize);
#endif
J3D_ASSERT_ALLOCMEM(193, shapeDraw);
return shapeDraw;
}
@@ -154,7 +159,7 @@ s32 J3DShapeFactory::calcSize(int shapeNo, u32 flag) {
for (u32 i = 0; i < mtxGroupNo; i++) {
size += calcSizeShapeMtx(flag, shapeNo, i);
size += 0x0C;
size += sizeof(J3DShapeDraw);
}
return size;
+8
View File
@@ -7,6 +7,10 @@
#include "JSystem/JMessage/control.h"
#if TARGET_PC
#include "dusk/randomizer/game/messages.hpp"
#endif
JMessage::TControl::TControl()
: pSequenceProcessor_(NULL),
pRenderingProcessor_(NULL),
@@ -90,6 +94,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;
+269 -30
View File
@@ -14,6 +14,33 @@
#endif
#include "tracy/Tracy.hpp"
#if TARGET_PC
#define JPA_DRAW_CTX_PARAM , ParticleDrawCtx* ctx
namespace {
GXColor emitter_prm_color(JPAEmitterWorkData* work) {
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
prm.g = COLOR_MULTI(prm.g, emtr->mGlobalPrmClr.g);
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
return prm;
}
GXColor emitter_env_color(JPAEmitterWorkData* work) {
JPABaseEmitter* emtr = work->mpEmtr;
GXColor env = emtr->mEnvClr;
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
return env;
}
} // namespace
#else
#define JPA_DRAW_CTX_PARAM
#endif
void JPASetPointSize(JPAEmitterWorkData* work) {
GXSetPointSize((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE);
}
@@ -22,15 +49,16 @@ void JPASetLineWidth(JPAEmitterWorkData* work) {
GXSetLineWidth((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE);
}
void JPASetPointSize(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPASetPointSize(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
GXSetPointSize((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE);
}
void JPASetLineWidth(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPASetLineWidth(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
GXSetLineWidth((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE);
}
void JPARegistPrm(JPAEmitterWorkData* work) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
@@ -41,6 +69,7 @@ void JPARegistPrm(JPAEmitterWorkData* work) {
}
void JPARegistEnv(JPAEmitterWorkData* work) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor env = emtr->mEnvClr;
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
@@ -50,6 +79,7 @@ void JPARegistEnv(JPAEmitterWorkData* work) {
}
void JPARegistPrmEnv(JPAEmitterWorkData* work) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
GXColor env = emtr->mEnvClr;
@@ -64,7 +94,8 @@ void JPARegistPrmEnv(JPAEmitterWorkData* work) {
GXSetTevColor(GX_TEVREG1, env);
}
void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
@@ -72,10 +103,19 @@ void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
if (ctx->useClr1) {
ctx->clr1 = emitter_env_color(work);
}
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm);
}
void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = ptcl->mPrmClr;
@@ -84,10 +124,19 @@ void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
if (ctx->useClr1) {
ctx->clr1 = emitter_env_color(work);
}
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm);
}
void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = ptcl->mPrmClr;
@@ -100,11 +149,19 @@ void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
ctx->clr1 = env;
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm);
GXSetTevColor(GX_TEVREG1, env);
}
void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor prm = emtr->mPrmClr;
GXColor env = ptcl->mEnvClr;
@@ -116,16 +173,31 @@ void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = prm;
ctx->clr1 = env;
return;
}
#endif
GXSetTevColor(GX_TEVREG0, prm);
GXSetTevColor(GX_TEVREG1, env);
}
void JPARegistEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPARegistEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
JPABaseEmitter* emtr = work->mpEmtr;
GXColor env = ptcl->mEnvClr;
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
#if TARGET_PC
if (ctx->batch) {
ctx->clr0 = emitter_prm_color(work);
ctx->clr1 = env;
return;
}
#endif
GXSetTevColor(GX_TEVREG1, env);
}
@@ -258,7 +330,7 @@ void JPAGenCalcTexCrdMtxAnm(JPAEmitterWorkData* work) {
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
}
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
ZoneScoped;
JPABaseShape* shape = work->mpRes->getBsp();
f32 dVar16 = param_1->mAge;
@@ -286,6 +358,12 @@ void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1)
local_108[2][1] = 0.0f;
local_108[2][2] = 1.0f;
local_108[2][3] = 0.0f;
#if TARGET_PC
if (ctx->batch) {
MTXCopy(local_108, ctx->texMtx);
return;
}
#endif
GXLoadTexMtxImm(local_108, 0x1e, GX_MTX2x4);
}
@@ -299,7 +377,7 @@ void JPALoadTexAnm(JPAEmitterWorkData* work) {
work->mpResMgr->load(work->mpRes->getTexIdx(work->mpEmtr->mTexAnmIdx), GX_TEXMAP0);
}
void JPALoadTexAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPALoadTexAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
ZoneScoped;
work->mpResMgr->load(work->mpRes->getTexIdx(ptcl->mTexAnmIdx), GX_TEXMAP0);
}
@@ -429,6 +507,47 @@ static projectionFunc p_prj[3] = {
};
#if TARGET_PC
static void emit_batch_quad(JPAEmitterWorkData* work, const ParticleDrawCtx* ctx,
const Mtx posMtx) {
const JPAResource::BatchInfo& info = work->mpRes->mBatchInfo;
for (int i = 0; i < info.vtxCount; i++) {
Vec localPos = {info.vtxPos[i][0], info.vtxPos[i][1], info.vtxPos[i][2]};
Vec drawPos;
MTXMultVec(posMtx, &localPos, &drawPos);
f32 texS = info.vtxUv[i][0];
f32 texT = info.vtxUv[i][1];
if (ctx->useTexMtx) {
f32 srcS = texS;
f32 srcT = texT;
texS = ctx->texMtx[0][0] * srcS + ctx->texMtx[0][1] * srcT + ctx->texMtx[0][3];
texT = ctx->texMtx[1][0] * srcS + ctx->texMtx[1][1] * srcT + ctx->texMtx[1][3];
}
GXPosition3f32(drawPos.x, drawPos.y, drawPos.z);
if (ctx->useClr0) {
GXColor4u8(ctx->clr0.r, ctx->clr0.g, ctx->clr0.b, ctx->clr0.a);
}
if (ctx->useClr1) {
GXColor4u8(ctx->clr1.r, ctx->clr1.g, ctx->clr1.b, ctx->clr1.a);
}
GXTexCoord2f32(texS, texT);
}
}
static void submit_particle_quad(
JPAEmitterWorkData* work, ParticleDrawCtx* ctx, const Mtx posMtx, const u8* dl, u32 dlSize) {
if (ctx->batch) {
emit_batch_quad(work, ctx, posMtx);
return;
}
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(dl, dlSize);
}
void JPAInterpBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
Mtx ptclPosMtx;
MTXTrans(ptclPosMtx, ptcl->mPosition.x, ptcl->mPosition.y, ptcl->mPosition.z);
@@ -448,7 +567,7 @@ void JPAInterpRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
}
#endif
void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -473,12 +592,16 @@ void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
posMtx[2][2] = 1.0f;
posMtx[2][3] = pos.z;
posMtx[0][1] = posMtx[0][2] = posMtx[1][0] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
#if TARGET_PC
submit_particle_quad(work, ctx, posMtx, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
}
void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -517,12 +640,16 @@ void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
posMtx[2][2] = 1.0f;
posMtx[2][3] = pos.z;
posMtx[0][2] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
#if TARGET_PC
submit_particle_quad(work, ctx, posMtx, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
}
void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -542,12 +669,16 @@ void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
local_38[2][2] = work->mYBBCamMtx[2][2];
local_38[2][3] = local_48.z;
local_38[0][1] = local_38[0][2] = local_38[1][0] = local_38[2][0] = 0.0f;
#if TARGET_PC
submit_particle_quad(work, ctx, local_38, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(local_38, GX_PNMTX0);
p_prj[work->mPrjType](work, local_38);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
}
void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -576,9 +707,13 @@ void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
local_38[2][1] = local_94 * fVar1;
local_38[2][2] = local_90;
local_38[2][3] = local_48.z;
#if TARGET_PC
submit_particle_quad(work, ctx, local_38, jpa_dl, sizeof(jpa_dl));
#else
GXLoadPosMtxImm(local_38, GX_PNMTX0);
p_prj[work->mPrjType](work, local_38);
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
#endif
}
void dirTypeVel(JPAEmitterWorkData const* work, JPABaseParticle const* param_1,
@@ -741,6 +876,88 @@ static u8* p_dl[2] = {
};
#if TARGET_PC
static bool make_direction_mtx(JPAEmitterWorkData* work, JPABaseParticle* ptcl, Mtx posMtx) {
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
JGeometry::TVec3<f32> baseAxis(ptcl->mBaseAxis);
p_direction[work->mDirType](work, ptcl, &axisY);
if (axisY.isZero()) {
return false;
}
axisY.normalize();
axisZ.cross(baseAxis, axisY);
if (axisZ.isZero()) {
return false;
}
axisZ.normalize();
baseAxis.cross(axisY, axisZ);
baseAxis.normalize();
ptcl->mBaseAxis.set(baseAxis);
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
posMtx[0][0] = baseAxis.x;
posMtx[0][1] = axisY.x;
posMtx[0][2] = axisZ.x;
posMtx[0][3] = ptcl->mPosition.x;
posMtx[1][0] = baseAxis.y;
posMtx[1][1] = axisY.y;
posMtx[1][2] = axisZ.y;
posMtx[1][3] = ptcl->mPosition.y;
posMtx[2][0] = baseAxis.z;
posMtx[2][1] = axisY.z;
posMtx[2][2] = axisZ.z;
posMtx[2][3] = ptcl->mPosition.z;
p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
return true;
}
static bool make_rot_direction_mtx(JPAEmitterWorkData* work, JPABaseParticle* ptcl, Mtx posMtx) {
f32 sinRot = JMASSin(ptcl->mRotateAngle);
f32 cosRot = JMASCos(ptcl->mRotateAngle);
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
JGeometry::TVec3<f32> baseAxis(ptcl->mBaseAxis);
p_direction[work->mDirType](work, ptcl, &axisY);
if (axisY.isZero()) {
return false;
}
axisY.normalize();
axisZ.cross(baseAxis, axisY);
if (axisZ.isZero()) {
return false;
}
axisZ.normalize();
baseAxis.cross(axisY, axisZ);
baseAxis.normalize();
ptcl->mBaseAxis.set(baseAxis);
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
Mtx rotMtx;
Mtx dirMtx;
p_rot[work->mRotType](sinRot, cosRot, rotMtx);
p_plane[work->mPlaneType](rotMtx, scaleX, scaleY);
dirMtx[0][0] = baseAxis.x;
dirMtx[0][1] = axisY.x;
dirMtx[0][2] = axisZ.x;
dirMtx[0][3] = ptcl->mPosition.x;
dirMtx[1][0] = baseAxis.y;
dirMtx[1][1] = axisY.y;
dirMtx[1][2] = axisZ.y;
dirMtx[1][3] = ptcl->mPosition.y;
dirMtx[2][0] = baseAxis.z;
dirMtx[2][1] = axisY.z;
dirMtx[2][2] = axisZ.z;
dirMtx[2][3] = ptcl->mPosition.z;
MTXConcat(dirMtx, rotMtx, posMtx);
return true;
}
void JPAInterpDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
@@ -823,7 +1040,7 @@ void JPAInterpRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
}
#endif
void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -832,8 +1049,12 @@ void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
Mtx posMtx;
#if TARGET_PC
if (!dusk::frame_interp::lookup_replacement(ptcl, posMtx))
#endif
if (!dusk::frame_interp::lookup_replacement(ptcl, posMtx) &&
!make_direction_mtx(work, ptcl, posMtx))
{
return;
}
#else
{
JGeometry::TVec3<f32> axisY;
JGeometry::TVec3<f32> axisZ;
@@ -869,14 +1090,19 @@ void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
posMtx[2][3] = ptcl->mPosition.z;
p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
}
#endif
MTXConcat(work->mPosCamMtx, posMtx, posMtx);
#if TARGET_PC
submit_particle_quad(work, ctx, posMtx, p_dl[work->mDLType], sizeof(jpa_dl));
#else
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
p_prj[work->mPrjType](work, posMtx);
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
#endif
}
void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -886,8 +1112,12 @@ void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
Mtx mtx1;
Mtx mtx2;
#if TARGET_PC
if (!dusk::frame_interp::lookup_replacement(ptcl, mtx1))
#endif
if (!dusk::frame_interp::lookup_replacement(ptcl, mtx1) &&
!make_rot_direction_mtx(work, ptcl, mtx1))
{
return;
}
#else
{
f32 sinRot = JMASSin(ptcl->mRotateAngle);
f32 cosRot = JMASCos(ptcl->mRotateAngle);
@@ -927,13 +1157,18 @@ void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
mtx2[2][3] = ptcl->mPosition.z;
MTXConcat(mtx2, mtx1, mtx1);
}
#endif
MTXConcat(work->mPosCamMtx, mtx1, mtx2);
#if TARGET_PC
submit_particle_quad(work, ctx, mtx2, p_dl[work->mDLType], sizeof(jpa_dl));
#else
GXLoadPosMtxImm(mtx2, GX_PNMTX0);
p_prj[work->mPrjType](work, mtx2);
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
#endif
}
void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -970,7 +1205,7 @@ void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
}
void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -988,12 +1223,16 @@ void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
auStack_88[1][3] = param_1->mPosition.y;
auStack_88[2][3] = param_1->mPosition.z;
MTXConcat(param_0->mPosCamMtx, auStack_88, auStack_88);
#if TARGET_PC
submit_particle_quad(param_0, ctx, auStack_88, p_dl[param_0->mDLType], sizeof(jpa_dl));
#else
GXLoadPosMtxImm(auStack_88, 0);
p_prj[param_0->mPrjType](param_0, auStack_88);
GXCallDisplayList(p_dl[param_0->mDLType], sizeof(jpa_dl));
#endif
}
void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -1010,7 +1249,7 @@ void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
}
void JPADrawLine(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
void JPADrawLine(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
return;
}
@@ -1086,7 +1325,7 @@ void JPADrawStripe(JPAEmitterWorkData* param_0) {
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
node = node_func(node), coord += step) {
param_0->mpCurNode = node;
JPABaseParticle* particle = node->getObject();
@@ -1111,7 +1350,7 @@ void JPADrawStripe(JPAEmitterWorkData* param_0) {
}
particle->mBaseAxis.cross(local_f8, local_104);
particle->mBaseAxis.normalize();
local_c8[0][0] = local_104.x;
local_c8[0][1] = local_f8.x;
local_c8[0][2] = particle->mBaseAxis.x;
@@ -1177,7 +1416,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
node = node_func(node), coord += step) {
param_0->mpCurNode = node;
JPABaseParticle* particle = node->getObject();
@@ -1202,7 +1441,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
}
particle->mBaseAxis.cross(local_c0, local_cc);
particle->mBaseAxis.normalize();
local_90[0][0] = local_cc.x;
local_90[0][1] = local_c0.x;
local_90[0][2] = particle->mBaseAxis.x;
@@ -1227,7 +1466,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
coord = start_coord;
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
node = node_func(node), coord += step) {
param_0->mpCurNode = node;
JPABaseParticle* particle = node->getObject();
@@ -1252,7 +1491,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
}
particle->mBaseAxis.cross(local_c0, local_cc);
particle->mBaseAxis.normalize();
local_90[0][0] = local_cc.x;
local_90[0][1] = local_c0.x;
local_90[0][2] = particle->mBaseAxis.x;
@@ -1289,7 +1528,7 @@ void JPADrawEmitterCallBackB(JPAEmitterWorkData* work) {
emtr->mpEmtrCallBack->draw(emtr);
}
void JPADrawParticleCallBack(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
void JPADrawParticleCallBack(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
JPABaseEmitter* emtr = work->mpEmtr;
if (emtr->mpPtclCallBack == NULL) {
return;
+1 -2
View File
@@ -206,8 +206,7 @@ void JPABaseParticle::init_c(JPAEmitterWorkData* work, JPABaseParticle* parent)
#if TARGET_PC
void JPABaseParticle::interp(JPAEmitterWorkData* work, void const* drawFunc) {
static bool enable = false;
if (!enable)
if (!dusk::frame_interp::is_enabled())
return;
// don't interpolate the first frame
+284 -6
View File
@@ -18,9 +18,21 @@
#include "global.h"
#include "tracy/Tracy.hpp"
#if TARGET_PC
#define JPA_DRAW_CTX_ARG , &ctx
#else
#define JPA_DRAW_CTX_ARG
#endif
JPAResource::JPAResource() {
mpCalcEmitterFuncList = mpDrawEmitterFuncList = mpDrawEmitterChildFuncList = NULL;
#if TARGET_PC
mpCalcParticleFuncList = mpCalcParticleChildFuncList = NULL;
mpDrawParticleFuncList = mpDrawParticleChildFuncList = NULL;
mBatchInfo = {};
#else
mpCalcParticleFuncList = mpDrawParticleFuncList = mpCalcParticleChildFuncList = mpDrawParticleChildFuncList = NULL;
#endif
pBsp = NULL;
pEsp = NULL;
pCsp = NULL;
@@ -61,6 +73,60 @@ static u8 jpa_crd[32] ATTRIBUTE_ALIGN(32) = {
0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02,
};
#if TARGET_PC
void JPAResource::initBatchInfo() {
mBatchInfo = {};
bool hasDrawFunc = false;
for (int i = 0; i < mpDrawParticleFuncListNum; i++) {
DrawParticleFunc func = mpDrawParticleFuncList[i];
if (func == JPADrawBillboard || func == JPADrawRotBillboard ||
func == JPADrawYBillboard || func == JPADrawRotYBillboard ||
func == JPADrawDirection || func == JPADrawRotDirection || func == JPADrawRotation)
{
hasDrawFunc = true;
} else if (func == JPADrawParticleCallBack) {
// Batchable only for emitters without a particle callback; checked per draw
} else if (func == JPALoadCalcTexCrdMtxAnm) {
mBatchInfo.hasPtclTexMtx = true;
} else if (func == JPARegistAlpha || func == JPARegistPrmAlpha ||
func == JPARegistPrmAlphaEnv || func == JPARegistAlphaEnv ||
func == static_cast<DrawParticleFunc>(JPARegistEnv)) // overloaded
{
mBatchInfo.hasPtclColor = true;
} else {
// JPADrawPoint, JPADrawLine, JPADrawDBillboard, JPALoadTexAnm,
// JPASetPointSize, JPASetLineWidth
return;
}
}
if (!hasDrawFunc) {
return;
}
// Template array offsets, same math as setPTev
int base_plane_type = (pBsp->getType() == 3 || pBsp->getType() == 7) ?
pBsp->getBasePlaneType() : 0;
int center_offset = pEsp != nullptr ? (pEsp->getScaleCenterX() + 3 * pEsp->getScaleCenterY()) * 0xC : 0x30;
const s8* pos = reinterpret_cast<const s8*>(jpa_pos) + center_offset + base_plane_type * 0x6C;
const s8* crd = reinterpret_cast<const s8*>(jpa_crd) + (pBsp->getTilingS() + 2 * pBsp->getTilingT()) * 8;
bool cross = pBsp->getType() == 4 || pBsp->getType() == 8;
mBatchInfo.vtxCount = cross ? 8 : 4;
for (int i = 0; i < mBatchInfo.vtxCount; i++) {
int posIdx = i < 4 ? i : 72 + (i - 4);
int crdIdx = i & 3;
mBatchInfo.vtxPos[i][0] = pos[posIdx * 3 + 0];
mBatchInfo.vtxPos[i][1] = pos[posIdx * 3 + 1];
mBatchInfo.vtxPos[i][2] = pos[posIdx * 3 + 2];
mBatchInfo.vtxUv[i][0] = crd[crdIdx * 2 + 0];
mBatchInfo.vtxUv[i][1] = crd[crdIdx * 2 + 1];
}
mBatchInfo.supported = true;
}
#endif
void JPAResource::init(JKRHeap* heap) {
BOOL is_glbl_clr_anm = pBsp->isGlblClrAnm();
BOOL is_glbl_tex_anm = pBsp->isGlblTexAnm();
@@ -525,7 +591,10 @@ void JPAResource::init(JKRHeap* heap) {
if (mpDrawParticleFuncListNum != 0) {
mpDrawParticleFuncList =
(ParticleFunc*)JKRAllocFromHeap(heap, mpDrawParticleFuncListNum * sizeof(ParticleFunc), alignof(ParticleFunc));
(DrawParticleFunc*)JKRAllocFromHeap(
heap,
mpDrawParticleFuncListNum * sizeof(DrawParticleFunc),
alignof(DrawParticleFunc));
}
func_no = 0;
@@ -635,7 +704,10 @@ void JPAResource::init(JKRHeap* heap) {
if (mpDrawParticleChildFuncListNum != 0) {
mpDrawParticleChildFuncList =
(ParticleFunc*)JKRAllocFromHeap(heap, mpDrawParticleChildFuncListNum * sizeof(ParticleFunc), sizeof(EmitterFunc));
(DrawParticleFunc*)JKRAllocFromHeap(
heap,
mpDrawParticleChildFuncListNum * sizeof(DrawParticleFunc),
alignof(DrawParticleFunc));
}
func_no = 0;
@@ -699,6 +771,10 @@ void JPAResource::init(JKRHeap* heap) {
mpDrawParticleChildFuncList[func_no] = &JPARegistPrmAlphaEnv;
func_no++;
}
#if TARGET_PC
initBatchInfo();
#endif
}
bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
@@ -761,6 +837,15 @@ bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
}
}
#ifdef TARGET_PC
if (((pBsp && pBsp->getDirType() == 3) || (pCsp && pCsp->getDirType() == 3)) &&
dusk::frame_interp::is_enabled())
{
// ensure mGlobalEmtrDir is valid
calcWorkData_d(work);
}
#endif
JPANode<JPABaseParticle>* next = NULL;
for (JPANode<JPABaseParticle>* node = emtr->mAlivePtclBase.getFirst(); node != emtr->mAlivePtclBase.getEnd(); node = next) {
next = node->getNext();
@@ -799,6 +884,183 @@ void JPAResource::draw(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
}
}
#if TARGET_PC
static GXTevAlphaArg to_vtx_alpha_arg(GXTevAlphaArg arg) {
return arg == GX_CA_A0 ? GX_CA_RASA : arg;
}
static void batch_set_tev_op(GXTevStageID stage) {
GXSetTevColorOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
GXSetTevAlphaOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
}
static void batch_setup_tev(JPAEmitterWorkData* work, bool useClr1) {
JPABaseShape* shape = work->mpRes->getBsp();
JPAExTexShape* ets = work->mpRes->getEts();
bool useIndirect = ets != nullptr && ets->isUseIndirect();
// JPAEmitterManager::draw configures both channels to pass vertex color through
GXSetNumChans(useClr1 ? 2 : 1);
const GXTevAlphaArg* alphaArg = shape->getTevAlphaArg();
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GXSetTevAlphaIn(GX_TEVSTAGE0, to_vtx_alpha_arg(alphaArg[0]), to_vtx_alpha_arg(alphaArg[1]),
to_vtx_alpha_arg(alphaArg[2]), to_vtx_alpha_arg(alphaArg[3]));
batch_set_tev_op(GX_TEVSTAGE0);
if (!useIndirect) {
GXSetTevDirect(GX_TEVSTAGE0);
}
GXTevStageID nextStage = GX_TEVSTAGE1;
switch (shape->getTevColorArgSel()) {
case 0: // TEXC
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_ONE, GX_CC_ZERO);
break;
case 1: // C0 * TEXC
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
break;
case 2: // lerp(C0, 1, TEXC)
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO);
break;
case 3: // lerp(C1, C0, TEXC) = C0 * TEXC (stage 0) + C1 * (1 - TEXC) (stage 1)
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
GXSetTevOrder(nextStage, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR1A1);
GXSetTevColorIn(nextStage, GX_CC_RASC, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV);
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
batch_set_tev_op(nextStage);
GXSetTevDirect(nextStage);
nextStage = static_cast<GXTevStageID>(nextStage + 1);
break;
case 4: // TEXC * C0 + C1: C0 * TEXC (stage 0), + C1 (stage 1)
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
GXSetTevOrder(nextStage, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR1A1);
GXSetTevColorIn(nextStage, GX_CC_CPREV, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
batch_set_tev_op(nextStage);
GXSetTevDirect(nextStage);
nextStage = static_cast<GXTevStageID>(nextStage + 1);
break;
case 5: // C0
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
break;
}
if (ets != nullptr && ets->isUseSecTex()) {
// Mirrors setPTev's secondary texture stage, at the next free stage
GXTexCoordID texCoord = useIndirect ? GX_TEXCOORD2 : GX_TEXCOORD1;
GXSetTevOrder(nextStage, texCoord, GX_TEXMAP3, GX_COLOR_NULL);
GXSetTevColorIn(nextStage, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_ZERO);
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO);
batch_set_tev_op(nextStage);
GXSetTevDirect(nextStage);
nextStage = static_cast<GXTevStageID>(nextStage + 1);
}
GXSetNumTevStages(nextStage);
}
static void batch_setup_vtx_desc(bool useClr0, bool useClr1) {
static Mtx identityMtx = {
{1.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f, 0.0f},
};
GXLoadPosMtxImm(identityMtx, GX_PNMTX0);
GXSetCurrentMtx(GX_PNMTX0);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
if (useClr0) {
GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
}
if (useClr1) {
GXSetVtxDesc(GX_VA_CLR1, GX_DIRECT);
}
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
if (useClr0) {
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
}
if (useClr1) {
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0);
}
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
}
static void batch_restore_gx(JPAEmitterWorkData* work, bool changedTev, bool changedTexMtx) {
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GXSetCurrentMtx(GX_PNMTX0);
if (changedTexMtx) {
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
}
if (changedTev) {
GXSetNumChans(0);
work->mpRes->getBsp()->setGX(work);
work->mpRes->setPTev();
}
}
static bool draw_particle_batch(JPAEmitterWorkData* work) {
ZoneScoped;
JPAResource* res = work->mpRes;
const JPAResource::BatchInfo& info = res->mBatchInfo;
if (!info.supported || work->mPrjType != 0 || work->mpEmtr->mpPtclCallBack != nullptr) {
return false;
}
bool useClr0 = false;
bool useClr1 = false;
if (info.hasPtclColor) {
u32 colorSel = res->getBsp()->getTevColorArgSel();
if (colorSel >= 6) {
return false;
}
useClr0 = true;
useClr1 = colorSel == 3 || colorSel == 4;
batch_setup_tev(work, useClr1);
}
if (info.hasPtclTexMtx) {
// UVs are CPU-transformed; drop the texgen
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
}
batch_setup_vtx_desc(useClr0, useClr1);
ParticleDrawCtx ctx{};
ctx.batch = true;
ctx.useTexMtx = info.hasPtclTexMtx;
ctx.useClr0 = useClr0;
ctx.useClr1 = useClr1;
bool fwdAhead = res->getBsp()->isDrawFwdAhead();
JPANode<JPABaseParticle>* node = fwdAhead ? work->mpEmtr->mAlivePtclBase.getLast() :
work->mpEmtr->mAlivePtclBase.getFirst();
GXBegin(GX_QUADS, GX_VTXFMT1, GX_AUTO);
while (node != work->mpEmtr->mAlivePtclBase.getEnd()) {
work->mpCurNode = node;
for (int i = res->mpDrawParticleFuncListNum - 1; i >= 0; i--) {
(*res->mpDrawParticleFuncList[i])(work, node->getObject(), &ctx);
}
node = fwdAhead ? node->getPrev() : node->getNext();
}
GXEnd();
batch_restore_gx(work, useClr0, info.hasPtclTexMtx);
return true;
}
#endif
void JPAResource::drawP(JPAEmitterWorkData* work) {
ZoneScoped;
work->mpEmtr->clearStatus(0x80);
@@ -833,13 +1095,25 @@ void JPAResource::drawP(JPAEmitterWorkData* work) {
(*mpDrawEmitterFuncList[i])(work);
}
#if TARGET_PC
if (draw_particle_batch(work)) {
GXSetMisc(GX_MT_XF_FLUSH, 0);
if (work->mpEmtr->mpEmtrCallBack != nullptr) {
work->mpEmtr->mpEmtrCallBack->drawAfter(work->mpEmtr);
}
return;
}
ParticleDrawCtx ctx{}; // immediate mode
#endif
if (pBsp->isDrawFwdAhead()) {
JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclBase.getLast();
for (; node != work->mpEmtr->mAlivePtclBase.getEnd(); node = node->getPrev()) {
work->mpCurNode = node;
if (mpDrawParticleFuncList != NULL) {
for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleFuncList[i])(work, node->getObject());
(*mpDrawParticleFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
}
}
}
@@ -849,7 +1123,7 @@ void JPAResource::drawP(JPAEmitterWorkData* work) {
work->mpCurNode = node;
if (mpDrawParticleFuncList != NULL) {
for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleFuncList[i])(work, node->getObject());
(*mpDrawParticleFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
}
}
}
@@ -896,13 +1170,17 @@ void JPAResource::drawC(JPAEmitterWorkData* work) {
(*mpDrawEmitterChildFuncList[i])(work);
}
#if TARGET_PC
ParticleDrawCtx ctx{}; // immediate mode
#endif
if (pBsp->isDrawFwdAhead()) {
JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclChld.getLast();
for (; node != work->mpEmtr->mAlivePtclChld.getEnd(); node = node->getPrev()) {
work->mpCurNode = node;
if (mpDrawParticleChildFuncList != NULL) {
for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleChildFuncList[i])(work, node->getObject());
(*mpDrawParticleChildFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
}
}
}
@@ -912,7 +1190,7 @@ void JPAResource::drawC(JPAEmitterWorkData* work) {
work->mpCurNode = node;
if (mpDrawParticleChildFuncList != NULL) {
for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) {
(*mpDrawParticleChildFuncList[i])(work, node->getObject());
(*mpDrawParticleChildFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
}
}
}
+1
View File
@@ -249,6 +249,7 @@ f32 JUTResFont::drawChar_scale(f32 pos_x, f32 pos_y, f32 scale_x, f32 scale_y, i
f32 x2;
f32 y1;
ZoneScoped;
JUT_ASSERT(378, mValid);
JUTFont::TWidth width;
loadFont(str_int, GX_TEXMAP0, &width FONT_DRAW_CTX_ARG);
@@ -4,6 +4,7 @@ import android.app.ActionBar;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
@@ -14,12 +15,16 @@ import android.provider.DocumentsContract;
import android.provider.OpenableColumns;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import org.libsdl.app.SDLActivity;
import org.libsdl.app.SDLSurface;
import java.io.File;
import java.util.ArrayList;
@@ -27,6 +32,7 @@ import java.util.List;
public class DuskActivity extends SDLActivity {
private static final String TAG = "DuskActivity";
private static final float DEFAULT_SURFACE_FRAME_RATE = 60.0f;
private static final int FOLDER_DIALOG_REQUEST_CODE = 0x4455;
private static final int MANAGE_STORAGE_REQUEST_CODE = 0x4456;
private static final String EXTERNAL_STORAGE_AUTHORITY =
@@ -88,6 +94,11 @@ public class DuskActivity extends SDLActivity {
hideSystemBars();
}
@Override
protected SDLSurface createSDLSurface(Context context) {
return new DuskSurface(context);
}
@Override
protected void onResume() {
super.onResume();
@@ -139,6 +150,77 @@ public class DuskActivity extends SDLActivity {
};
}
public void setPreferredSurfaceFrameRate(float frameRate) {
runOnUiThread(() -> {
if (mSurface instanceof DuskSurface) {
((DuskSurface)mSurface).setPreferredFrameRate(frameRate);
}
});
}
private static final class DuskSurface extends SDLSurface {
private float preferredFrameRate = DEFAULT_SURFACE_FRAME_RATE;
DuskSurface(Context context) {
super(context);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.surfaceChanged(holder, format, width, height);
setTargetFrameRate(holder);
}
void setPreferredFrameRate(float frameRate) {
preferredFrameRate = frameRate;
setTargetFrameRate(getHolder());
}
private void setTargetFrameRate(SurfaceHolder holder) {
if (!mIsSurfaceReady || Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
return;
}
Surface surface = holder != null ? holder.getSurface() : getHolder().getSurface();
if (surface == null || !surface.isValid()) {
return;
}
float targetFrameRate = getMaxSupportedFrameRate();
if (preferredFrameRate > 0.0f) {
targetFrameRate = preferredFrameRate;
}
if (targetFrameRate <= 0.0f) {
return;
}
try {
surface.setFrameRate(
targetFrameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
Log.v(TAG, "Requested surface frame rate " + targetFrameRate + " fps");
} catch (RuntimeException e) {
Log.w(TAG, "Failed to request surface frame rate", e);
}
}
private float getMaxSupportedFrameRate() {
if (mDisplay == null) {
return 0.0f;
}
float maxFrameRate = mDisplay.getRefreshRate();
Display.Mode[] modes = mDisplay.getSupportedModes();
if (modes == null) {
return maxFrameRate;
}
for (Display.Mode mode : modes) {
maxFrameRate = Math.max(maxFrameRate, mode.getRefreshRate());
}
return maxFrameRate;
}
}
@Override
protected String[] getArguments() {
Intent intent = getIntent();
@@ -19,9 +19,13 @@ import android.os.*;
import java.lang.Runnable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDevice {
private static final String TAG = "hidapi";
@@ -33,10 +37,19 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
private boolean mIsConnected = false;
private boolean mIsChromebook = false;
private boolean mIsReconnecting = false;
private boolean mHasEnabledNotifications = false;
private boolean mHasSeenInputUpdate = false;
private boolean mFrozen = false;
private LinkedList<GattOperation> mOperations;
GattOperation mCurrentOperation = null;
private Handler mHandler;
private int mProductId = -1;
private int mReportId = 0;
private UUID mInputCharacteristic;
private static final int D0G_BLE2_PID = 0x1106;
private static final int TRITON_BLE_PID = 0x1303;
private static final int TRANSPORT_AUTO = 0;
private static final int TRANSPORT_BREDR = 1;
@@ -45,10 +58,14 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
private static final int CHROMEBOOK_CONNECTION_CHECK_INTERVAL = 10000;
static final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristic = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristicD0G = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristicTriton_0x45 = UUID.fromString("100F6C7A-1735-4313-B402-38567131E5F3");
static final UUID inputCharacteristicTriton_0x47 = UUID.fromString("100F6C7C-1735-4313-B402-38567131E5F3");
static final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3");
static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 };
private HashMap<Integer, BluetoothGattCharacteristic> mOutputReportChars = new HashMap<Integer, BluetoothGattCharacteristic>();
static class GattOperation {
private enum Operation {
CHR_READ,
@@ -61,6 +78,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
byte[] mValue;
BluetoothGatt mGatt;
boolean mResult = true;
int mDelayMs = 0;
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid) {
mGatt = gatt;
@@ -68,6 +86,13 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mUuid = uuid;
}
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, int delayMs) {
mGatt = gatt;
mOp = operation;
mUuid = uuid;
mDelayMs = delayMs;
}
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value) {
mGatt = gatt;
mOp = operation;
@@ -75,6 +100,14 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mValue = value;
}
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value, int delayMs) {
mGatt = gatt;
mOp = operation;
mUuid = uuid;
mValue = value;
mDelayMs = delayMs;
}
public void run() {
// This is executed in main thread
BluetoothGattCharacteristic chr;
@@ -136,6 +169,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
return mResult;
}
public int getDelayMs() { return mDelayMs; }
private BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
BluetoothGattService valveService = mGatt.getService(steamControllerService);
if (valveService == null)
@@ -154,6 +189,10 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid) {
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid);
}
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid, int delayMs) {
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid, delayMs);
}
}
HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) {
@@ -166,6 +205,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mHandler = new Handler(Looper.getMainLooper());
mGatt = connectGatt();
mHasEnabledNotifications = false;
mHasSeenInputUpdate = false;
// final HIDDeviceBLESteamController finalThis = this;
// mHandler.postDelayed(new Runnable() {
// @Override
@@ -314,8 +355,45 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
Log.v(TAG, "Found Valve steam controller service " + service.getUuid());
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
if (chr.getUuid().equals(inputCharacteristic)) {
Log.v(TAG, "Found input characteristic");
if (chr.getUuid().equals(inputCharacteristicTriton_0x45)) {
Log.v(TAG, "Found Triton input characteristic 0x45");
mProductId = TRITON_BLE_PID;
mReportId = 0x45;
mInputCharacteristic = chr.getUuid();
} else if (chr.getUuid().equals(inputCharacteristicTriton_0x47)) {
Log.v(TAG, "Found Triton input characteristic 0x47");
mProductId = TRITON_BLE_PID;
mReportId = 0x47;
mInputCharacteristic = chr.getUuid();
} else if (chr.getUuid().equals(inputCharacteristicD0G)) {
Log.v(TAG, "Found D0G input characteristic");
mProductId = D0G_BLE2_PID;
mReportId = 0x03;
mInputCharacteristic = chr.getUuid();
} else {
Pattern reportPattern = Pattern.compile("100F6C([0-9A-Z]{2})", Pattern.CASE_INSENSITIVE);
Matcher matcher = reportPattern.matcher(chr.getUuid().toString());
if (matcher.find()) {
try {
int reportId = Integer.parseInt(matcher.group(1), 16);
reportId -= 0x35;
if (reportId >= 0x80) {
// This is a Triton output report characteristic that we need to care about.
Log.v(TAG, "Found Triton output report 0x" + Integer.toString(reportId, 16));
mOutputReportChars.put(reportId, chr);
}
}
catch (NumberFormatException nfe) {
Log.w(TAG, "Could not parse report characteristic " + chr.getUuid().toString() + ": " + nfe.toString());
}
}
}
}
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
if (chr.getUuid().equals(mInputCharacteristic)) {
// Start notifications
BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
if (cccd != null) {
@@ -372,21 +450,30 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mCurrentOperation = mOperations.removeFirst();
}
// Run in main thread
mHandler.post(new Runnable() {
@Override
public void run() {
synchronized (mOperations) {
if (mCurrentOperation == null) {
Log.e(TAG, "Current operation null in executor?");
return;
}
Runnable gattOperationRunnable = new Runnable() {
@Override
public void run() {
synchronized (mOperations) {
if (mCurrentOperation == null) {
Log.e(TAG, "Current operation null in executor?");
return;
}
mCurrentOperation.run();
// now wait for the GATT callback and when it comes, finish this operation
mCurrentOperation.run();
// now wait for the GATT callback and when it comes, finish this operation
}
}
}
});
};
if (mCurrentOperation.getDelayMs() == 0) {
// Run in main thread
mHandler.post(gattOperationRunnable);
}
else {
// If we have a delay on this operation, wait before we post it.
mHandler.postDelayed(gattOperationRunnable, mCurrentOperation.getDelayMs());
}
}
private void queueGattOperation(GattOperation op) {
@@ -397,8 +484,39 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
}
private void enableNotification(UUID chrUuid) {
GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid);
// Add a 500ms delay to notification write for Amazon Fire TV devices, as otherwise if we do this too quickly after connecting
// it will return success and then silently drop the operation on the floor.
GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid, 500);
queueGattOperation(op);
// Amazon Fire devices can also silently timeout on writeDescriptor, so
// set up a little delayed check that will attempt to write a second time.
//
// While this only seems to be needed on Amazon Fire TV devices at present, it
// doesn't hurt to have a retry on other devices as well.
//
final HIDDeviceBLESteamController finalThis = this;
final UUID finalUuid = chrUuid;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (!finalThis.mHasEnabledNotifications) {
if (finalThis.mHasSeenInputUpdate) {
// Amazon Five devices may have enabled notifications on the input characteristic and not given us a callback. If we've seen
// input reports, though, somewhat by definition notifications are enabled.
Log.w(TAG, "WriteDescriptor has never returned, but we've seen input reports. Moving on with controller initialization.");
finalThis.mHasEnabledNotifications = true;
finalThis.enableValveMode();
return;
}
// Give one more try.
GattOperation retry = HIDDeviceBLESteamController.GattOperation.enableNotification(finalThis.mGatt, finalUuid, 500);
finalThis.queueGattOperation(retry);
}
}
}, 1000);
}
void writeCharacteristic(UUID uuid, byte[] value) {
@@ -448,8 +566,16 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
mIsConnected = false;
gatt.disconnect();
mGatt = connectGatt(false);
}
else {
} else {
if (getProductId() == TRITON_BLE_PID) {
// Android will not properly play well with Data Length Extensions without manually requesting a large MTU,
// and Triton controllers require DLE support.
//
// 517 is basically a "magic number" as far as Android's bluetooth code is concerned, so do not change
// this value. It is functionally "please enable data length extensions" on some Android builds.
mGatt.requestMtu(517);
}
probeService(this);
}
}
@@ -474,7 +600,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
// Only register controller with the native side once it has been fully configured
if (!isRegistered()) {
Log.v(TAG, "Registering Steam Controller with ID: " + getId());
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true);
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true, mReportId);
setRegistered();
}
}
@@ -487,7 +613,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
// Enable this for verbose logging of controller input reports
//Log.v(TAG, "onCharacteristicChanged uuid=" + characteristic.getUuid() + " data=" + HexDump.dumpHexString(characteristic.getValue()));
if (characteristic.getUuid().equals(inputCharacteristic) && !mFrozen) {
if (characteristic.getUuid().equals(mInputCharacteristic) && !mFrozen) {
mHasSeenInputUpdate = true;
mManager.HIDDeviceInputReport(getId(), characteristic.getValue());
}
}
@@ -497,19 +624,36 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
//Log.v(TAG, "onDescriptorRead status=" + status);
}
private void enableValveMode()
{
BluetoothGattService valveService = mGatt.getService(steamControllerService);
if (valveService == null)
return;
BluetoothGattCharacteristic reportChr = valveService.getCharacteristic(reportCharacteristic);
if (reportChr != null) {
if (getProductId() == TRITON_BLE_PID) {
// For Triton we just mark things registered.
Log.v(TAG, "Registering Triton Steam Controller with ID: " + getId());
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true, mReportId);
setRegistered();
} else {
// For the original controller, we need to manually enter Valve mode.
Log.v(TAG, "Writing report characteristic to enter valve mode");
reportChr.setValue(enterValveMode);
mGatt.writeCharacteristic(reportChr);
}
}
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
BluetoothGattCharacteristic chr = descriptor.getCharacteristic();
//Log.v(TAG, "onDescriptorWrite status=" + status + " uuid=" + chr.getUuid() + " descriptor=" + descriptor.getUuid());
if (chr.getUuid().equals(inputCharacteristic)) {
boolean hasWrittenInputDescriptor = true;
BluetoothGattCharacteristic reportChr = chr.getService().getCharacteristic(reportCharacteristic);
if (reportChr != null) {
Log.v(TAG, "Writing report characteristic to enter valve mode");
reportChr.setValue(enterValveMode);
gatt.writeCharacteristic(reportChr);
}
if (chr.getUuid().equals(mInputCharacteristic)) {
mHasEnabledNotifications = true;
enableValveMode();
}
finishCurrentGattOperation();
@@ -548,9 +692,20 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
@Override
public int getProductId() {
// We don't have an easy way to query from the Bluetooth device, but we know what it is
final int D0G_BLE2_PID = 0x1106;
return D0G_BLE2_PID;
if (mProductId > 0) {
// We've already set a product ID.
return mProductId;
}
if (mDevice.getName().startsWith("Steam Ctrl")) {
// We're a newer Triton device
mProductId = TRITON_BLE_PID;
} else {
// We're an OG Steam Controller
mProductId = D0G_BLE2_PID;
}
return mProductId;
}
@Override
@@ -601,10 +756,29 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
writeCharacteristic(reportCharacteristic, actual_report);
return report.length;
} else {
//Log.v(TAG, "writeOutputReport " + HexDump.dumpHexString(report));
writeCharacteristic(reportCharacteristic, report);
return report.length;
// If we're an original-recipe Steam Controller we just write to the characteristic directly.
if (getProductId() == D0G_BLE2_PID) {
//Log.v(TAG, "writeOutputReport " + HexDump.dumpHexString(report));
writeCharacteristic(reportCharacteristic, report);
return report.length;
}
// If we're a Triton, we need to find the correct report characteristic.
if (report.length > 0) {
int reportId = report[0] & 0xFF;
BluetoothGattCharacteristic targetedReportCharacteristic = mOutputReportChars.get(reportId);
if (targetedReportCharacteristic != null) {
byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1);
//Log.v(TAG, "writeOutputReport 0x" + Integer.toString(reportId, 16) + " " + HexDump.dumpHexString(report));
writeCharacteristic(targetedReportCharacteristic.getUuid(), actual_report);
return report.length;
} else {
Log.w(TAG, "Got report write request for unknown report type 0x" + Integer.toString(reportId, 16));
}
}
}
return -1;
}
@Override
@@ -256,6 +256,7 @@ public class HIDDeviceManager {
0x24c6, // PowerA
0x2c22, // Qanba
0x2dc8, // 8BitDo
0x3537, // GameSir
0x37d7, // Flydigi
0x9886, // ASTRO Gaming
};
@@ -360,7 +361,7 @@ public class HIDDeviceManager {
HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index);
int id = device.getId();
mDevicesById.put(id, device);
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false);
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false, 0);
}
}
}
@@ -529,7 +530,13 @@ public class HIDDeviceManager {
return false;
}
return bluetoothDevice.getName().equals("SteamController") && ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) != 0);
// Steam Controllers will always support Bluetooth Low Energy
if ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) == 0) {
return false;
}
// Match on the name either the original Steam Controller or the new second-generation one advertise with.
return bluetoothDevice.getName().equals("SteamController") || bluetoothDevice.getName().startsWith("Steam Ctrl");
}
private void close() {
@@ -681,7 +688,7 @@ public class HIDDeviceManager {
private native void HIDDeviceRegisterCallback();
private native void HIDDeviceReleaseCallback();
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth);
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth, int reportID);
native void HIDDeviceOpenPending(int deviceID);
native void HIDDeviceOpenResult(int deviceID, boolean opened);
native void HIDDeviceDisconnected(int deviceID);
@@ -21,6 +21,7 @@ class HIDDeviceUSB implements HIDDevice {
protected InputThread mInputThread;
protected boolean mRunning;
protected boolean mFrozen;
protected boolean mClaimed;
public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) {
mManager = manager;
@@ -29,6 +30,7 @@ class HIDDeviceUSB implements HIDDevice {
mInterface = mDevice.getInterface(mInterfaceIndex).getId();
mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier());
mRunning = false;
mClaimed = false;
}
String getIdentifier() {
@@ -114,6 +116,7 @@ class HIDDeviceUSB implements HIDDevice {
close();
return false;
}
mClaimed = true;
// Find the endpoints
for (int j = 0; j < iface.getEndpointCount(); j++) {
@@ -132,9 +135,12 @@ class HIDDeviceUSB implements HIDDevice {
}
}
// Make sure the required endpoints were present
if (mInputEndpoint == null || mOutputEndpoint == null) {
// Make sure the required endpoints were present. The original Steam Controller and the wireless dongle for it do NOT
// actually have -- or require -- output endpoints, so we need to accept only an input one for them or else we'll fall
// back to the Android system gamepad functionality (and lose our paddles et al).
if (mInputEndpoint == null) {
Log.w(TAG, "Missing required endpoint on USB device " + getDeviceName());
mConnection.releaseInterface(iface);
close();
return false;
}
@@ -154,6 +160,11 @@ class HIDDeviceUSB implements HIDDevice {
return -1;
}
if (!mClaimed) {
Log.w(TAG, "writeReport() called but some other process currently owns the USB device");
return -1;
}
if (feature) {
int res = -1;
int offset = 0;
@@ -185,6 +196,11 @@ class HIDDeviceUSB implements HIDDevice {
}
return length;
} else {
if (mOutputEndpoint == null)
{
Log.e(TAG, "Tried to write an output report to an interface with no output endpoint!");
return -1;
}
int res = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);
if (res != report.length) {
Log.w(TAG, "writeOutputReport() returned " + res + " on device " + getDeviceName());
@@ -205,6 +221,12 @@ class HIDDeviceUSB implements HIDDevice {
Log.w(TAG, "readReport() called with no device connection");
return false;
}
if (!mClaimed) {
if (feature) {
return false;
}
return true;
}
if (report_number == 0x0) {
/* Offset the return buffer by 1, so that the report ID
@@ -258,10 +280,13 @@ class HIDDeviceUSB implements HIDDevice {
mInputThread = null;
}
if (mConnection != null) {
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
mConnection.releaseInterface(iface);
if (mClaimed) {
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
mConnection.releaseInterface(iface);
}
mConnection.close();
mConnection = null;
mClaimed = false;
}
}
@@ -274,6 +299,22 @@ class HIDDeviceUSB implements HIDDevice {
@Override
public void setFrozen(boolean frozen) {
mFrozen = frozen;
/* If we have a valid device connection and the claim state doesn't match what we want, try to correct that. */
if (mConnection != null && mClaimed == mFrozen) {
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
if (frozen) {
mClaimed = !mConnection.releaseInterface(iface);
if (mClaimed) {
Log.e(TAG, "Tried to release claim on USB device, but failed!");
}
} else {
mClaimed = mConnection.claimInterface(iface, true);
if (!mClaimed) {
Log.e(TAG, "Tried to regain claim on USB device, but failed!");
}
}
}
}
protected class InputThread extends Thread {
@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 3;
private static final int SDL_MINOR_VERSION = 4;
private static final int SDL_MICRO_VERSION = 8;
private static final int SDL_MICRO_VERSION = 10;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
@@ -530,7 +530,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(true);
}
}
if (!mHasMultiWindow) {
pauseNativeThread();
}
@@ -543,7 +544,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(false);
}
}
if (!mHasMultiWindow) {
resumeNativeThread();
}
@@ -616,6 +618,14 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
super.onWindowFocusChanged(hasFocus);
Log.v(TAG, "onWindowFocusChanged(): " + hasFocus);
// If we are gaining focus, we can always try to restore our USB devices. If we are losing focus,
// only try to relinquish them if we don't have background events allowed (for multi-window Android setups).
if (hasFocus || !SDLActivity.nativeGetHintBoolean("SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", false)) {
if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(!hasFocus);
}
}
if (SDLActivity.mBrokenLibraries) {
return;
}
@@ -1481,11 +1491,11 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
// Note that we process events with specific key codes here
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLControllerManager.onNativePadDown(deviceId, keyCode)) {
if (SDLControllerManager.onNativePadDown(deviceId, keyCode, event.getScanCode())) {
return true;
}
} else if (event.getAction() == KeyEvent.ACTION_UP) {
if (SDLControllerManager.onNativePadUp(deviceId, keyCode)) {
if (SDLControllerManager.onNativePadUp(deviceId, keyCode, event.getScanCode())) {
return true;
}
}
@@ -1963,7 +1973,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
| Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
i.addFlags(flags);
@@ -2227,3 +2237,4 @@ class SDLClipboardHandler implements
SDLActivity.onNativeClipboardChanged();
}
}
@@ -10,6 +10,10 @@ import android.hardware.lights.Light;
import android.hardware.lights.LightsRequest;
import android.hardware.lights.LightsManager;
import android.hardware.lights.LightState;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.graphics.Color;
import android.os.Build;
import android.os.VibrationEffect;
@@ -30,16 +34,18 @@ public class SDLControllerManager
static native void nativeAddJoystick(int device_id, String name, String desc,
int vendor_id, int product_id,
int button_mask,
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led);
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led,
boolean has_accelerometer, boolean has_gyroscope);
static native void nativeRemoveJoystick(int device_id);
static native void nativeAddHaptic(int device_id, String name);
static native void nativeRemoveHaptic(int device_id);
static public native boolean onNativePadDown(int device_id, int keycode);
static public native boolean onNativePadUp(int device_id, int keycode);
static public native boolean onNativePadDown(int device_id, int keycode, int scancode);
static public native boolean onNativePadUp(int device_id, int keycode, int scancode);
static native void onNativeJoy(int device_id, int axis,
float value);
static native void onNativeHat(int device_id, int hat_id,
int x, int y);
static native void onNativeJoySensor(int device_id, int sensor_type, long sensor_timestamp, float x, float y, float z);
protected static SDLJoystickHandler mJoystickHandler;
protected static SDLHapticHandler mHapticHandler;
@@ -81,6 +87,13 @@ public class SDLControllerManager
mJoystickHandler.setLED(device_id, red, green, blue);
}
/**
* This method is called by SDL using JNI.
*/
static void joystickSetSensorsEnabled(int device_id, boolean enabled) {
mJoystickHandler.setSensorsEnabled(device_id, enabled);
}
/**
* This method is called by SDL using JNI.
*/
@@ -153,6 +166,10 @@ class SDLJoystickHandler {
ArrayList<InputDevice.MotionRange> hats;
ArrayList<Light> lights;
LightsManager.LightsSession lightsSession;
SensorManager sensorManager;
SDLJoySensorListener sensorListener;
Sensor accelerometerSensor;
Sensor gyroscopeSensor;
}
static class RangeComparator implements Comparator<InputDevice.MotionRange> {
@Override
@@ -225,12 +242,13 @@ class SDLJoystickHandler {
joystick.desc = getJoystickDescriptor(joystickDevice);
joystick.axes = new ArrayList<InputDevice.MotionRange>();
joystick.hats = new ArrayList<InputDevice.MotionRange>();
java.util.Set<Integer> axisStrsSet = new java.util.HashSet<Integer>();
joystick.lights = new ArrayList<Light>();
List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
Collections.sort(ranges, new RangeComparator());
for (InputDevice.MotionRange range : ranges) {
if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
if (((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) && axisStrsSet.add(range.getAxis())) {
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
joystick.hats.add(range);
} else {
@@ -241,6 +259,8 @@ class SDLJoystickHandler {
boolean can_rumble = false;
boolean has_rgb_led = false;
boolean has_accelerometer = false;
boolean has_gyroscope = false;
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
VibratorManager vibratorManager = joystickDevice.getVibratorManager();
int[] vibrators = vibratorManager.getVibratorIds();
@@ -258,12 +278,26 @@ class SDLJoystickHandler {
joystick.lightsSession = lightsManager.openSession();
has_rgb_led = true;
}
SensorManager sensorManager = joystickDevice.getSensorManager();
if (sensorManager != null) {
joystick.sensorManager = sensorManager;
joystick.sensorListener = new SDLJoySensorListener(joystick.device_id);
joystick.accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (joystick.accelerometerSensor != null) {
has_accelerometer = true;
}
joystick.gyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
if (joystick.gyroscopeSensor != null) {
has_gyroscope = true;
}
}
}
mJoysticks.add(joystick);
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
getVendorId(joystickDevice), getProductId(joystickDevice),
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led);
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led,
has_accelerometer, has_gyroscope);
}
}
}
@@ -508,6 +542,31 @@ class SDLJoystickHandler {
}
joystick.lightsSession.requestLights(lightsRequest.build());
}
void setSensorsEnabled(int device_id, boolean enabled) {
if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
return;
}
SDLJoystick joystick = getJoystick(device_id);
if (joystick == null || joystick.sensorManager == null) {
return;
}
if (enabled) {
if (joystick.accelerometerSensor != null) {
SDLSensorManager.registerListener(joystick.sensorManager, joystick.sensorListener, joystick.accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
}
if (joystick.gyroscopeSensor != null) {
SDLSensorManager.registerListener(joystick.sensorManager, joystick.sensorListener, joystick.gyroscopeSensor, SensorManager.SENSOR_DELAY_GAME);
}
} else {
if (joystick.accelerometerSensor != null) {
SDLSensorManager.unregisterListener(joystick.sensorManager, joystick.sensorListener, joystick.accelerometerSensor);
}
if (joystick.gyroscopeSensor != null) {
SDLSensorManager.unregisterListener(joystick.sensorManager, joystick.sensorListener, joystick.gyroscopeSensor);
}
}
}
}
class SDLHapticHandler_API31 extends SDLHapticHandler {
@@ -933,3 +992,19 @@ class SDLGenericMotionListener_API29 extends SDLGenericMotionListener_API26 {
return penDevice.isExternal() ? SDL_PEN_DEVICE_TYPE_INDIRECT : SDL_PEN_DEVICE_TYPE_DIRECT;
}
}
class SDLJoySensorListener implements SensorEventListener {
int device_id;
public SDLJoySensorListener(int device_id) {
this.device_id = device_id;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
@Override
public void onSensorChanged(SensorEvent event) {
SDLControllerManager.onNativeJoySensor(device_id, event.sensor.getType(), event.timestamp, event.values[0], event.values[1], event.values[2]);
}
}
@@ -0,0 +1,32 @@
package org.libsdl.app;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
// This class coordinates synchronized access to sensor manager registration
//
// This prevents a java.util.ConcurrentModificationException exception on
// Android 16, specifically on the Samsung Tab S9 Ultra.
class SDLSensorManager
{
static private SDLSensorManager mManager = new SDLSensorManager();
public static void registerListener(SensorManager manager, SensorEventListener listener, Sensor sensor, int samplingPeriodUs) {
mManager.RegisterListener(manager, listener, sensor, samplingPeriodUs);
}
public static void unregisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor) {
mManager.UnregisterListener(manager, listener, sensor);
}
private synchronized void RegisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor, int samplingPeriodUs) {
manager.registerListener(listener, sensor, samplingPeriodUs, null);
}
private synchronized void UnregisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor) {
manager.unregisterListener(listener, sensor);
}
}
@@ -47,6 +47,9 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// Is SurfaceView ready for rendering
protected boolean mIsSurfaceReady;
// Is on-screen keyboard visible
protected boolean mKeyboardVisible;
// Pinch events
private final ScaleGestureDetector scaleGestureDetector;
@@ -213,6 +216,18 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
WindowInsets.Type.displayCutout());
SDLActivity.onNativeInsetsChanged(combined.left, combined.right, combined.top, combined.bottom);
if (insets.isVisible(WindowInsets.Type.ime())) {
if (!mKeyboardVisible) {
mKeyboardVisible = true;
SDLActivity.onNativeScreenKeyboardShown();
}
} else {
if (mKeyboardVisible) {
mKeyboardVisible = false;
SDLActivity.onNativeScreenKeyboardHidden();
}
}
}
// Pass these to any child views in case they need them
@@ -318,11 +333,11 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
protected void enableSensor(int sensortype, boolean enabled) {
// TODO: This uses getDefaultSensor - what if we have >1 accels?
if (enabled) {
mSensorManager.registerListener(this,
SDLSensorManager.registerListener(mSensorManager, this,
mSensorManager.getDefaultSensor(sensortype),
SensorManager.SENSOR_DELAY_GAME, null);
SensorManager.SENSOR_DELAY_GAME);
} else {
mSensorManager.unregisterListener(this,
SDLSensorManager.unregisterListener(mSensorManager, this,
mSensorManager.getDefaultSensor(sensortype));
}
}
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>dev.twilitrealm.dusk</id>
<launchable type="desktop-id">dev.twilitrealm.dusk.desktop</launchable>
<name>Dusklight</name>
<summary>Native port of a classic adventure game</summary>
<developer id="dev.twilitrealm">
<name>Twilit Realm</name>
</developer>
<url type="homepage">https://twilitrealm.dev</url>
<url type="bugtracker">https://github.com/TwilitRealm/dusklight/issues</url>
<metadata_license>CC0-1.0</metadata_license>
<project_license>CC0-1.0</project_license>
<content_rating type="oars-1.0"/>
<supports>
<control>console</control>
<control>gamepad</control>
</supports>
<description>
<p>
Dusklight is a reverse-engineered reimplementation of a classic adventure game.
It aims to be as accurate as possible to the original while also providing new options, enhancements, and tools to customize your experience.
</p>
</description>
<provides>
<binary>dusklight</binary>
<id>dev.twilitrealm.dusk.desktop</id>
</provides>
<releases>
<release version="UNRELEASED" date="2026-12-31">
<description>
<p>Initial Flatpak release.</p>
</description>
</release>
</releases>
</component>
File diff suppressed because it is too large Load Diff
+53 -3
View File
@@ -16,11 +16,12 @@ body {
flex-direction: column;
justify-content: flex-end;
align-items: stretch;
z-index: 1;
z-index: 2;
pointer-events: none;
}
fps,
pipeline-progress,
toast {
position: absolute;
border: 1dp #92875B;
@@ -98,7 +99,7 @@ toast message row.muted {
opacity: 0.5;
}
toast progress {
progress {
height: 4dp;
position: absolute;
left: 0;
@@ -106,10 +107,50 @@ toast progress {
width: 100%;
}
toast progress fill {
progress fill {
background-color: rgba(194, 164, 45, 80%);
}
pipeline-progress {
left: 12dp;
bottom: 12dp;
display: flex;
flex-flow: column;
z-index: 100;
min-width: 260dp;
max-width: 90%;
padding: 10dp 16dp 12dp;
border-radius: 7dp;
overflow: hidden;
filter: opacity(0);
transition: filter 0.2s linear-in-out;
pointer-events: none;
}
pipeline-progress[open] {
filter: opacity(1);
}
pipeline-status {
display: flex;
align-items: center;
gap: 8dp;
font-size: 18dp;
font-weight: normal;
white-space: nowrap;
}
icon.pipeline-spinner {
width: 1.2em;
height: 1.2em;
line-height: 1.2em;
font-size: 1.2em;
color: #C2A42D;
text-align: center;
transform-origin: center;
animation: 1s linear infinite pipeline-spinner-spin;
}
toast.achievement {
border: 1dp #C2A42D;
}
@@ -310,6 +351,15 @@ logo img.outer {
}
}
@keyframes pipeline-spinner-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (max-height: 640dp) {
toast {
top: 20dp;
+339
View File
@@ -0,0 +1,339 @@
*, *:before, *:after {
box-sizing: border-box;
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
font-family: "Fira Sans Condensed";
font-weight: bold;
color: rgba(248, 244, 232, 90%);
z-index: 1;
filter: opacity(0);
transition: filter 0.2s linear-in-out;
}
body[open] {
filter: opacity(1);
}
body:not([open]) {
pointer-events: none;
}
button {
display: flex;
align-items: center;
justify-content: center;
decorator: none;
padding: 0;
border: 1dp rgba(255, 255, 255, 22%);
background-color: rgba(22, 24, 28, 48%);
color: rgba(248, 244, 232, 90%);
text-align: center;
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 6dp 18dp rgba(0, 0, 0, 28%); */
transform-origin: center;
transition: background-color border-color filter transform 0.08s linear-in-out,
opacity 0.2s linear-in-out;
}
button.pressed,
button.active {
background-color: rgba(63, 78, 90, 68%);
border-color: rgba(255, 255, 255, 48%);
filter: brightness(1.18);
}
button:hidden {
opacity: 0;
pointer-events: none;
}
button span {
display: block;
line-height: 1;
}
button icon {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
button icon glyph {
display: block;
font-family: "Material Symbols Rounded";
font-weight: normal;
font-size: 24dp;
line-height: 1;
}
.midna-icon,
.item-icon,
.item-count,
.oil-meter {
display: none;
}
.midna-icon.visible,
.item-icon.visible,
.item-count.visible,
.oil-meter.visible {
display: block;
}
.control {
position: absolute;
}
.trigger-l.active {
background-color: rgba(57, 116, 133, 74%);
border-color: rgba(128, 222, 234, 72%);
}
.trigger,
.skip {
border-radius: 23dp;
}
.trigger {
font-size: 22dp;
}
.button-z {
background-color: rgba(118, 79, 158, 58%);
border-color: rgba(203, 170, 255, 36%);
}
.midna-icon {
position: absolute;
left: 9dp;
top: -1dp;
height: 48dp;
}
.button-z.has-icon span,
.face.has-item span {
position: absolute;
font-size: 13dp;
line-height: 1;
}
.button-z.has-icon span {
right: 9dp;
bottom: 7dp;
}
.button-z.pressed {
background-color: rgba(139, 91, 187, 82%);
border-color: rgba(220, 194, 255, 70%);
}
action-bar {
position: absolute;
display: flex;
align-items: center;
border: 1dp rgba(255, 255, 255, 22%);
border-radius: 23dp;
background-color: rgba(22, 24, 28, 48%);
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 -6dp 18dp rgba(0, 0, 0, 28%); */
overflow: hidden;
opacity: 1;
transform-origin: center;
transition: opacity 0.2s linear-in-out;
}
action-bar:hidden,
action-bar:hidden button,
action-bar:hidden separator {
opacity: 0;
pointer-events: none;
}
.utility {
position: relative;
flex: 1 1 auto;
width: 56dp;
height: 44dp;
margin: 0;
border-width: 0dp;
border-radius: 0;
background-color: transparent;
box-shadow: none;
}
.utility,
.skip {
opacity: 0.55;
}
.utility.pressed {
background-color: rgba(63, 78, 90, 68%);
}
.utility.pressed,
.skip.pressed {
opacity: 1;
}
.skip {
z-index: 1;
border-color: rgba(255, 255, 255, 36%);
}
separator {
display: block;
flex: 0 0 1dp;
width: 1dp;
height: 24dp;
background-color: rgba(255, 255, 255, 18%);
opacity: 1;
transition: opacity 0.2s linear-in-out;
}
.face {
position: absolute;
border-radius: 29dp;
font-size: 24dp;
overflow: visible;
}
.item-icon {
width: auto;
height: auto;
max-width: 76%;
max-height: 76%;
}
.item-count {
position: absolute;
left: 6dp;
bottom: 5dp;
min-width: 17dp;
height: 15dp;
padding: 1dp 3dp;
border-radius: 7dp;
background-color: rgba(0, 0, 0, 52%);
color: rgba(255, 255, 255, 92%);
font-size: 12dp;
line-height: 13dp;
text-align: center;
}
.oil-meter {
position: absolute;
left: 12dp;
bottom: -5dp;
width: 34dp;
height: 8dp;
padding: 2dp;
border: 1dp rgba(42, 32, 18, 82%);
border-radius: 4dp;
background-color: rgba(18, 14, 10, 70%);
/* box-shadow: 0 2dp 6dp rgba(0, 0, 0, 35%); */
}
oil-fill {
display: block;
width: 0%;
height: 100%;
border-radius: 2dp;
background-color: rgb(255, 232, 74);
}
.face.has-item span {
right: 6dp;
bottom: 6dp;
color: rgba(255, 255, 255, 88%);
}
.face.a {
border-radius: 37dp;
font-size: 31dp;
background-color: rgba(34, 112, 123, 62%);
}
.face.b {
background-color: rgba(161, 61, 66, 58%);
}
.face.x {
background-color: rgba(83, 115, 151, 56%);
}
.face.y {
background-color: rgba(113, 91, 150, 54%);
}
button.control.docked-top,
action-bar.docked-top {
border-top-width: 0dp;
border-top-left-radius: 0dp;
border-top-right-radius: 0dp;
}
button.control.docked-bottom,
action-bar.docked-bottom {
border-bottom-width: 0dp;
border-bottom-left-radius: 0dp;
border-bottom-right-radius: 0dp;
}
button.control.docked-left,
action-bar.docked-left {
border-left-width: 0dp;
border-top-left-radius: 0dp;
border-bottom-left-radius: 0dp;
}
button.control.docked-right,
action-bar.docked-right {
border-right-width: 0dp;
border-top-right-radius: 0dp;
border-bottom-right-radius: 0dp;
}
touch-stick {
display: block;
position: absolute;
width: 124dp;
height: 124dp;
border-radius: 62dp;
background-color: rgba(18, 20, 24, 35%);
border: 1dp rgba(255, 255, 255, 20%);
/* backdrop-filter: blur(7dp); */
/* box-shadow: 0 8dp 24dp rgba(0, 0, 0, 24%); */
opacity: 0;
pointer-events: none;
transition: opacity 0.18s linear-in-out;
}
touch-stick.active {
opacity: 1;
}
stick-ring {
position: absolute;
left: 18dp;
top: 18dp;
width: 88dp;
height: 88dp;
border-radius: 44dp;
border: 1dp rgba(255, 255, 255, 18%);
}
stick-knob {
position: absolute;
width: 48dp;
height: 48dp;
border-radius: 24dp;
background-color: rgba(238, 236, 226, 55%);
border: 1dp rgba(255, 255, 255, 45%);
}
+138
View File
@@ -0,0 +1,138 @@
body.touch-editor {
background-color: rgba(4, 6, 8, 34%);
z-index: 8;
}
body.touch-editor .control,
body.touch-editor action-bar {
opacity: 0.88;
cursor: move;
pointer-events: auto;
}
body.touch-editor .control:hover,
body.touch-editor action-bar:hover,
body.touch-editor .control.editor-selected,
body.touch-editor action-bar.editor-selected {
border-color: rgba(255, 232, 128, 80%);
filter: brightness(1.15);
}
body.touch-editor action-bar button,
body.touch-editor action-bar separator {
pointer-events: none;
}
selection-frame {
display: none;
position: absolute;
z-index: 20;
border: 2dp rgba(255, 232, 128, 88%);
background-color: rgba(255, 232, 128, 7%);
pointer-events: none;
}
selection-frame.visible {
display: block;
}
resize-handle {
display: block;
position: absolute;
width: 22dp;
height: 22dp;
border: 2dp rgba(255, 244, 190, 96%);
border-radius: 11dp;
background-color: rgba(34, 37, 42, 86%);
pointer-events: auto;
}
resize-handle.left {
left: -12dp;
}
resize-handle.right {
right: -12dp;
}
resize-handle.top {
top: -12dp;
}
resize-handle.bottom {
bottom: -12dp;
}
resize-handle.horizontal {
top: 50%;
margin-top: -11dp;
}
resize-handle.vertical {
left: 50%;
margin-left: -11dp;
}
resize-handle.corner.left {
left: -12dp;
}
resize-handle.corner.right {
right: -12dp;
}
resize-handle.corner.top {
top: -12dp;
}
resize-handle.corner.bottom {
bottom: -12dp;
}
editor-toolbar {
display: flex;
position: absolute;
left: 24dp;
right: 24dp;
top: 50%;
z-index: 30;
height: 48dp;
margin-top: -24dp;
gap: 8dp;
justify-content: center;
pointer-events: auto;
}
editor-toolbar button.editor-command {
flex: 0 1 150dp;
min-width: 96dp;
height: 48dp;
padding: 0 14dp;
border-radius: 8dp;
border: 1dp rgba(255, 255, 255, 26%);
background-color: rgba(17, 19, 24, 88%);
color: rgba(255, 250, 232, 94%);
font-family: "Fira Sans";
font-size: 18dp;
line-height: 48dp;
opacity: 1;
cursor: pointer;
}
editor-toolbar button.editor-command span {
display: block;
width: 100%;
line-height: 48dp;
text-align: center;
}
editor-toolbar button.editor-command.primary {
border-color: rgba(255, 232, 128, 70%);
background-color: rgba(96, 82, 38, 90%);
}
editor-toolbar button.editor-command:hover,
editor-toolbar button.editor-command:focus-visible {
border-color: rgba(255, 244, 190, 92%);
background-color: rgba(78, 85, 96, 92%);
}
+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;
}
+10 -7
View File
@@ -1230,7 +1230,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 +1291,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 +1327,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 +1392,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;
+93 -19
View File
@@ -58,6 +58,10 @@
#include "res/Object/Alink.h"
#include <cstring>
#include <dusk/string.hpp>
#include "dusk/cosmetics/color_utils.hpp"
#include "dusk/randomizer/game/flags.h"
#include "dusk/randomizer/game/stages.h"
#include "dusk/randomizer/game/tools.h"
#endif
static int daAlink_Create(fopAc_ac_c* i_this);
@@ -4231,6 +4235,25 @@ int daAlink_c::createHeap() {
if (mpHIO == NULL) {
return 0;
}
#if TARGET_PC
const auto& lanternColor = dusk::getSettings().cosmetics.lanternGlowColor.getValue();
if (dusk::cosmetics::is_valid_hex_color_str(lanternColor)) {
u8 r = std::stoi(lanternColor.substr(0, 2), nullptr, 16);
u8 g = std::stoi(lanternColor.substr(2, 2), nullptr, 16);
u8 b = std::stoi(lanternColor.substr(4, 2), nullptr, 16);
auto& lanternAmbience = mpHIO->mItem.mLanternPL.m;
auto& lanternSphere = mpHIO->mItem.mLantern.m;
lanternAmbience.mColorR = r;
lanternAmbience.mColorG = g;
lanternAmbience.mColorB = b;
lanternSphere.mColorReg1R = r;
lanternSphere.mColorReg1G = g;
lanternSphere.mColorReg1B = b;
lanternSphere.mColorReg2R = r;
lanternSphere.mColorReg2G = g;
lanternSphere.mColorReg2B = b;
}
#endif
if (!(mpWlChangeModel = initModel(dRes_ID_ALINK_BMD_WL_CHANGE_e, 0))) {
return 0;
@@ -10573,9 +10596,16 @@ void daAlink_c::decideDoStatus() {
(actor_name == fpcNm_TAG_KMSG_e &&
static_cast<daTag_KMsg_c*>(field_0x27f4)->getType() == 3))
{
if (!checkEquipAnime() && checkMasterSwordEquip()) {
// Don't check vanilla condition in randomizer
if (!checkEquipAnime() && checkMasterSwordEquip() IF_DUSK(&& !randomizer_IsActive())) {
setDoStatus(BUTTON_STATUS_STRIKE);
}
#if TARGET_PC
// Separate check for striking sword into the pedestal for randomizer
if (!checkEquipAnime() && randomizer_IsActive() && randomizer_checkTempleOfTimeRequirement()) {
setDoStatus(BUTTON_STATUS_STRIKE);
}
#endif
}
} else if (mTargetedActor != NULL && checkGoatCatchActor(mTargetedActor) &&
mAttention->getActionBtnB() != NULL &&
@@ -11483,6 +11513,14 @@ int daAlink_c::orderTalk(int i_checkZTalk) {
static void* daAlink_searchBouDoor(fopAc_ac_c* i_actor, void* i_data) {
UNUSED(i_data);
#if TARGET_PC
// In randomizer, we don't want Bo preventing us from entering his house on Day 2
if (randomizer_IsActive() && daAlink_c::checkStageName("F_SP103"))
{
return NULL;
}
#endif
if (fopAcM_GetName(i_actor) == fpcNm_NPC_BOU_e && ((daNpc_Bou_c*)i_actor)->speakTo()) {
return i_actor;
}
@@ -12263,6 +12301,14 @@ BOOL daAlink_c::checkGroundSpecialMode() {
if (mLinkAcch.ChkGroundHit() && !checkModeFlg(MODE_PLAYER_FLY) && !checkMagneBootsOn() &&
checkEndResetFlg0(ERFLG0_FORCE_WOLF_CHANGE))
{
#if TARGET_PC
u8 stage = getStageID();
// In rando, don't transform in twilight fog unless we have shadow crystal
if (randomizer_IsActive() && !dComIfGs_isEventBit(TRANSFORMING_UNLOCKED) &&
(stage == Palace_of_Twilight || stage == Phantom_Zant_1 || stage == Phantom_Zant_2)) {
return 0;
}
#endif
return procCoMetamorphoseInit();
}
@@ -12734,7 +12780,19 @@ void daAlink_c::setMagicArmorBrk(int i_status) {
BOOL daAlink_c::checkMagicArmorHeavy() const {
#if TARGET_PC
return checkMagicArmorWearAbility() && (dComIfGs_getRupee() == 0 && !dusk::getSettings().game.freeMagicArmor);
if(!checkMagicArmorWearAbility()) {
return false;
}
switch(dusk::getSettings().game.armorRupeeDrain) {
case dusk::MagicArmorMode::NORMAL:
return dComIfGs_getRupee() == 0;
case dusk::MagicArmorMode::ON_DAMAGE:
case dusk::MagicArmorMode::DOUBLE_DEFENSE:
case dusk::MagicArmorMode::INVINCIBLE:
case dusk::MagicArmorMode::COSMETIC:
return false;
}
#else
return checkMagicArmorWearAbility() && dComIfGs_getRupee() == 0;
#endif
@@ -14796,6 +14854,8 @@ void daAlink_c::deleteEquipItem(BOOL i_isPlaySound, BOOL i_isDeleteKantera) {
#if TARGET_PC
mIBChainInterpPrevValid = false;
mIBChainInterpCurrValid = false;
mHsChainInterpPrevValid = false;
mHsChainInterpCurrValid = false;
#endif
field_0x0774 = NULL;
field_0x0778 = NULL;
@@ -18707,7 +18767,7 @@ int daAlink_c::execute() {
#if TARGET_PC
// This handles rupee drain and transitions between rupees/no rupees
// We can skip all of that if the magic armor doesn't use rupees
if (!dusk::getSettings().game.freeMagicArmor && checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) {
if (dusk::getSettings().game.armorRupeeDrain.getValue() == dusk::MagicArmorMode::NORMAL && checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) {
#else
if (checkMagicArmorWearAbility() && mClothesChangeWaitTimer == 0) {
#endif
@@ -19768,23 +19828,37 @@ int daAlink_c::draw() {
dComIfGd_getOpaListDark()->entryImm(mpHookChain, 0);
#if TARGET_PC
if (dusk::frame_interp::is_enabled() &&
mEquipItem == dItemNo_IRONBALL_e &&
mIronBallChainPos != NULL && mIronBallChainAngle != NULL)
{
if (mIBChainInterpCurrValid) {
memcpy(mIBChainInterpPrevPos, mIBChainInterpCurrPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpPrevAngle, mIBChainInterpCurrAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpPrevHandRoot = mIBChainInterpCurrHandRoot;
mIBChainInterpPrevValid = true;
if (dusk::frame_interp::is_enabled()) {
if (mEquipItem == dItemNo_IRONBALL_e &&
mIronBallChainPos != NULL && mIronBallChainAngle != NULL)
{
if (mIBChainInterpCurrValid) {
memcpy(mIBChainInterpPrevPos, mIBChainInterpCurrPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpPrevAngle, mIBChainInterpCurrAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpPrevHandRoot = mIBChainInterpCurrHandRoot;
mIBChainInterpPrevValid = true;
}
memcpy(mIBChainInterpCurrPos, mIronBallChainPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpCurrAngle, mIronBallChainAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpCurrHandRoot = mHookshotTopPos;
mIBChainInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&ironBallChainInterpCallback, this);
} else {
if (mHsChainInterpCurrValid) {
mHsChainInterpPrevTop = mHsChainInterpCurrTop;
mHsChainInterpPrevRoot = mHsChainInterpCurrRoot;
mHsChainInterpPrevSubRoot = mHsChainInterpCurrSubRoot;
mHsChainInterpPrevSubTop = mHsChainInterpCurrSubTop;
mHsChainInterpPrevValid = true;
}
mHsChainInterpCurrTop = mHookshotTopPos;
mHsChainInterpCurrRoot = mHeldItemRootPos;
mHsChainInterpCurrSubRoot = field_0x3810;
mHsChainInterpCurrSubTop = mIronBallBgChkPos;
mHsChainInterpCurrValid = true;
}
memcpy(mIBChainInterpCurrPos, mIronBallChainPos, IRON_BALL_CHAIN_COUNT * sizeof(cXyz));
memcpy(mIBChainInterpCurrAngle, mIronBallChainAngle, IRON_BALL_CHAIN_COUNT * sizeof(csXyz));
mIBChainInterpCurrHandRoot = mHookshotTopPos;
mIBChainInterpCurrValid = true;
dusk::frame_interp::add_interpolation_callback(&ironBallChainInterpCallback, this);
}
#endif
}
+55 -2
View File
@@ -1624,7 +1624,7 @@ const daAlinkHIO_bomb_c1 daAlinkHIO_bomb_c0::m = {
#pragma push
#pragma force_active on
const daAlinkHIO_huLight_c1 daAlinkHIO_huLight_c0::m = {
IF_NOT_DUSK(const) daAlinkHIO_huLight_c1 daAlinkHIO_huLight_c0::m = {
0,
3,
0,
@@ -1638,8 +1638,25 @@ const daAlinkHIO_huLight_c1 daAlinkHIO_huLight_c0::m = {
0.0f,
};
#pragma pop
#if TARGET_PC
// Save original lantern colors incase player reverts to default
const daAlinkHIO_huLight_c1 daAlinkHIO_huLight_c0::original = {
0,
3,
0,
181,
112,
40,
-70,
1.0f,
50.0f,
350.0f,
0.0f,
};
#endif
const daAlinkHIO_kandelaar_c1 daAlinkHIO_kandelaar_c0::m = {
IF_NOT_DUSK(const) daAlinkHIO_kandelaar_c1 daAlinkHIO_kandelaar_c0::m = {
{
30,
1.1f,
@@ -1672,6 +1689,42 @@ const daAlinkHIO_kandelaar_c1 daAlinkHIO_kandelaar_c0::m = {
0.5f,
};
#if TARGET_PC
// Save original lantern colors incase player reverts to default
const daAlinkHIO_kandelaar_c1 daAlinkHIO_kandelaar_c0::original = {
{
30,
1.1f,
2.0f,
3.0f,
17.0f,
},
{
11,
1.0f,
0.0f,
3.0f,
12.0f,
},
{
17,
1.0f,
0.0f,
3.0f,
18.0f,
},
80,
40,
20,
40,
30,
10,
3,
200,
0.5f,
};
#endif
const daAlinkHIO_fmChain_c1 daAlinkHIO_fmChain_c0::m = {
{
20,
+25 -1
View File
@@ -192,7 +192,7 @@ int daAlink_c::setDamagePoint(int i_dmgAmount, BOOL i_checkZoraMag, BOOL i_setDm
if (checkMagicArmorNoDamage()) {
#if TARGET_PC
if(dusk::getSettings().game.freeMagicArmor) {
if(dusk::getSettings().game.armorRupeeDrain.getValue() == dusk::MagicArmorMode::INVINCIBLE) {
i_dmgAmount = 0;
}
#endif
@@ -202,6 +202,11 @@ int daAlink_c::setDamagePoint(int i_dmgAmount, BOOL i_checkZoraMag, BOOL i_setDm
if (!mpHIO->mDamage.m.mInvincible && g_debugHpMode == 0)
#endif
{
#if TARGET_PC
if(checkMagicArmorWearAbility() && dusk::getSettings().game.armorRupeeDrain.getValue() == dusk::MagicArmorMode::DOUBLE_DEFENSE) {
i_dmgAmount /= 2;
}
#endif
dComIfGp_setItemLifeCount(-i_dmgAmount, 0);
}
@@ -281,7 +286,26 @@ BOOL daAlink_c::checkIcePolygonDamage(cBgS_PolyInfo* i_poly) {
}
BOOL daAlink_c::checkMagicArmorNoDamage() {
#ifdef TARGET_PC
if (!checkMagicArmorWearAbility()) {
return false;
}
switch(dusk::getSettings().game.armorRupeeDrain) {
case dusk::MagicArmorMode::NORMAL:
return !checkMagicArmorHeavy();
case dusk::MagicArmorMode::ON_DAMAGE:
return dComIfGs_getRupee() != 0;
case dusk::MagicArmorMode::DOUBLE_DEFENSE:
return false;
case dusk::MagicArmorMode::INVINCIBLE:
return true;
case dusk::MagicArmorMode::COSMETIC:
return false;
}
#else
return checkMagicArmorWearAbility() && !checkMagicArmorHeavy();
#endif
}
int daAlink_c::checkPolyDamage() {
+321 -2
View File
@@ -23,9 +23,14 @@
#include "d/actor/d_a_npc_tkc.h"
#include <cstring>
#include "dusk/archipelago/archipelago_context.hpp"
#if TARGET_PC
#include "dusk/imgui/ImGuiConsole.hpp"
#include "dusk/settings.h"
#include "dusk/speedrun.h"
#include "dusk/randomizer/game/randomizer_context.hpp"
#endif
BOOL daAlink_c::checkEventRun() const {
return dComIfGp_event_runCheck() || checkPlayerDemoMode();
@@ -1023,13 +1028,26 @@ void daAlink_c::setGetItemFace(u16 i_itemNo) {
|| i_itemNo == dItemNo_ANCIENT_DOCUMENT2_e
|| i_itemNo == dItemNo_DROP_CONTAINER_e
|| i_itemNo == dItemNo_DROP_CONTAINER02_e
#if TARGET_PC
// Rando items for facial expressions
|| (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_WOOD_STICK_e)
|| (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_SWORD_e)
|| (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_SHIELD_e)
|| (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_MASTER_SWORD_e)
|| (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_LIGHT_SWORD_e)
|| (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_MAGIC_LV1_e)
#endif
|| i_itemNo == dItemNo_DROP_CONTAINER03_e)
{
setFaceBasicBck(dRes_ID_ALANM_BCK_FI_e);
} else if (i_itemNo == dItemNo_DUNGEON_EXIT_e || i_itemNo == dItemNo_LV7_DUNGEON_EXIT_e) {
setFaceBasicTexture(FTANM_K_A);
setFaceBasicBck(dRes_ID_ALANM_BCK_FK_e);
#if TARGET_PC
} else if (i_itemNo == dItemNo_TOMATO_PUREE_e || i_itemNo == dItemNo_TASTE_e || (randomizer_IsActive() && i_itemNo == dItemNo_Randomizer_FOOLISH_ITEM_e)) {
#else
} else if (i_itemNo == dItemNo_TOMATO_PUREE_e || i_itemNo == dItemNo_TASTE_e) {
#endif
setFaceBasicBck(dRes_ID_ALANM_BCK_FJ_e);
}
}
@@ -2216,18 +2234,283 @@ void daAlink_c::setGetSubBgm(int i_itemNo) {
/* dItemNo_KEY_OF_FILONE_e */ SETYPE_ITEM_GET_MINI,
};
#if TARGET_PC
// Randomizer SeType changes
static const u8 getSeTypeRandomizer[255] = {
/* dItemNo_Randomizer_HEART_e */ SETYPE_NONE,
/* dItemNo_Randomizer_GREEN_RUPEE_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_BLUE_RUPEE_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_YELLOW_RUPEE_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_RED_RUPEE_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_PURPLE_RUPEE_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_ORANGE_RUPEE_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_SILVER_RUPEE_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_S_MAGIC_e */ SETYPE_NONE,
/* dItemNo_Randomizer_L_MAGIC_e */ SETYPE_NONE,
/* dItemNo_Randomizer_BOMB_5_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_BOMB_10_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_BOMB_20_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_BOMB_30_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_ARROW_10_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_ARROW_20_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_ARROW_30_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_ARROW_1_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_PACHINKO_SHOT_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_FOOLISH_ITEM_e_e */ SETYPE_NONE,
/* dItemNo_Randomizer_NOENTRY_20_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_21_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_WATER_BOMB_5_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_WATER_BOMB_10_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_WATER_BOMB_20_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_WATER_BOMB_30_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_BOMB_INSECT_5_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_BOMB_INSECT_10_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_BOMB_INSECT_20_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_BOMB_INSECT_30_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_RECOVERY_FAILY_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_TRIPLE_HEART_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_SMALL_KEY_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_KAKERA_HEART_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_UTAWA_HEART_e */ SETYPE_HEART,
/* dItemNo_Randomizer_MAP_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_COMPUS_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_DUNGEON_EXIT_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_BOSS_KEY_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_DUNGEON_BACK_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_SWORD_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_MASTER_SWORD_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_WOOD_SHIELD_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_SHIELD_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_HYLIA_SHIELD_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_TKS_LETTER_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_WEAR_CASUAL_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_WEAR_KOKIRI_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_ARMOR_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_WEAR_ZORA_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_MAGIC_LV1_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_DUNGEON_EXIT_2_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_WALLET_LV1_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_WALLET_LV2_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_WALLET_LV3_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_55_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_56_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_57_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_58_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_59_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_60_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_ZORAS_JEWEL_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_HAWK_EYE_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_WOOD_STICK_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_BOOMERANG_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_SPINNER_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_IRONBALL_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_BOW_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_HOOKSHOT_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_HVY_BOOTS_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_COPY_ROD_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_W_HOOKSHOT_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_KANTERA_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_LIGHT_SWORD_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_FISHING_ROD_1_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_PACHINKO_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_COPY_ROD_2_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_77_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_78_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_BOMB_BAG_LV2_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_BOMB_BAG_LV1_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_BOMB_IN_BAG_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_82_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_LIGHT_ARROW_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_ARROW_LV1_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_ARROW_LV2_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_ARROW_LV3_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_87_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_LURE_ROD_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_BOMB_ARROW_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_HAWK_ARROW_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_BEE_ROD_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_JEWEL_ROD_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_WORM_ROD_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_JEWEL_BEE_ROD_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_JEWEL_WORM_ROD_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_EMPTY_BOTTLE_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_RED_BOTTLE_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_GREEN_BOTTLE_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_BLUE_BOTTLE_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_MILK_BOTTLE_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_HALF_MILK_BOTTLE_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_OIL_BOTTLE_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_WATER_BOTTLE_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_OIL_BOTTLE_2_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_RED_BOTTLE_2_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_UGLY_SOUP_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_HOT_SPRING_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_FAIRY_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_HOT_SPRING_2_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_OIL2_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_OIL_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NORMAL_BOMB_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_WATER_BOMB_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_POKE_BOMB_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_FAIRY_DROP_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_WORM_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_DROP_BOTTLE_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_BEE_CHILD_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_CHUCHU_RARE_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_CHUCHU_RED_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_CHUCHU_BLUE_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_CHUCHU_GREEN_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_CHUCHU_YELLOW_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_CHUCHU_PURPLE_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_LV1_SOUP_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_LV2_SOUP_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_LV3_SOUP_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_LETTER_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_BILL_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_WOOD_STATUE_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_IRIAS_PENDANT_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_HORSE_FLUTE_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_133_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_134_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_135_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_136_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_137_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_138_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_139_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_140_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_141_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_142_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_143_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_RAFRELS_MEMO_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_ASHS_SCRIBBLING_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_146_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_147_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_148_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_149_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_150_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_151_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_152_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_153_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_154_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_155_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_CHUCHU_YELLOW2_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_OIL_BOTTLE3_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_SHOP_BEE_CHILD_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_CHUCHU_BLACK_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_LIGHT_DROP_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_DROP_CONTAINER_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_DROP_CONTAINER02_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_DROP_CONTAINER03_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_FILLED_CONTAINER_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_MIRROR_PIECE_2_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_MIRROR_PIECE_3_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_MIRROR_PIECE_4_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_168_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_169_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_170_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_171_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_172_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_173_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_174_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_175_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_SMELL_YELIA_POUCH_e */ SETYPE_ITEM_GET_SMELL,
/* dItemNo_Randomizer_SMELL_PUMPKIN_e */ SETYPE_ITEM_GET_SMELL,
/* dItemNo_Randomizer_SMELL_POH_e */ SETYPE_ITEM_GET_SMELL,
/* dItemNo_Randomizer_SMELL_FISH_e */ SETYPE_ITEM_GET_SMELL,
/* dItemNo_Randomizer_SMELL_CHILDREN_e */ SETYPE_ITEM_GET_SMELL,
/* dItemNo_Randomizer_SMELL_MEDICINE_e */ SETYPE_ITEM_GET_SMELL,
/* dItemNo_Randomizer_NOENTRY_182_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_183_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_184_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_185_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_186_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_187_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_188_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_189_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_190_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_NOENTRY_191_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_M_BEETLE_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_F_BEETLE_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_M_BUTTERFLY_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_F_BUTTERFLY_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_M_STAG_BEETLE_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_F_STAG_BEETLE_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_M_GRASSHOPPER_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_F_GRASSHOPPER_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_M_NANAFUSHI_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_F_NANAFUSHI_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_M_DANGOMUSHI_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_F_DANGOMUSHI_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_M_MANTIS_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_F_MANTIS_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_M_LADYBUG_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_F_LADYBUG_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_M_SNAIL_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_F_SNAIL_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_M_DRAGONFLY_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_F_DRAGONFLY_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_M_ANT_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_F_ANT_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_M_MAYFLY_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_F_MAYFLY_e */ SETYPE_ITEM_GET_INSECT,
/* dItemNo_Randomizer_NOENTRY_216_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_217_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_218_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_219_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_220_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_221_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_222_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_223_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_POU_SPIRIT_e */ SETYPE_ITEM_GET_POU,
/* dItemNo_Randomizer_NOENTRY_225_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_226_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_227_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_228_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_229_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_230_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_231_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_NOENTRY_232_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_ANCIENT_DOCUMENT_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_AIR_LETTER_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_ANCIENT_DOCUMENT2_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_LV7_DUNGEON_EXIT_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_LINKS_SAVINGS_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_SMALL_KEY2_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_POU_FIRE1_e */ SETYPE_NONE,
/* dItemNo_Randomizer_POU_FIRE2_e */ SETYPE_NONE,
/* dItemNo_Randomizer_POU_FIRE3_e */ SETYPE_NONE,
/* dItemNo_Randomizer_POU_FIRE4_e */ SETYPE_NONE,
/* dItemNo_Randomizer_BOSSRIDER_KEY_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_TOMATO_PUREE_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_TASTE_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_LV5_BOSS_KEY_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_SURFBOARD_e */ SETYPE_NONE,
/* dItemNo_Randomizer_KANTERA2_e */ SETYPE_ITEM_GET_ME,
/* dItemNo_Randomizer_L2_KEY_PIECES1_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_L2_KEY_PIECES2_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_L2_KEY_PIECES3_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_KEY_OF_CARAVAN_e */ SETYPE_ITEM_GET_MINI,
/* dItemNo_Randomizer_LV2_BOSS_KEY_e */ SETYPE_ITEM_GET,
/* dItemNo_Randomizer_KEY_OF_FILONE_e */ SETYPE_ITEM_GET_MINI,
};
#endif
static u32 const bgmLabel[8] = {
Z2BGM_HEART_GET, Z2BGM_ITEM_GET, Z2BGM_ITEM_GET_MINI, Z2BGM_ITEM_GET_ME,
Z2BGM_ITEM_GET_INSECT, Z2BGM_ITEM_GET_SMELL, Z2BGM_ITEM_GET_POU, Z2BGM_ITEM_GET_ME_S,
};
#if TARGET_PC
u32 se_type = randomizer_IsActive() ? getSeTypeRandomizer[i_itemNo] : getSeType[i_itemNo];
#else
u32 se_type = getSeType[i_itemNo];
#endif
if (se_type == SETYPE_ITEM_GET_ME && mProcVar4.field_0x3010 == 0) {
se_type = SETYPE_ITEM_GET_ME_S;
}
if (se_type != SETYPE_NONE) {
if (se_type != SETYPE_NONE IF_DUSK(|| i_itemNo == dItemNo_Randomizer_FOOLISH_ITEM_e)) {
mDoAud_subBgmStart(bgmLabel[se_type]);
dComIfGp_setMesgBgmOn();
}
@@ -2259,6 +2542,15 @@ int daAlink_c::procCoGetItemInit() {
s16 var_r22 = 0;
BOOL var_r31 = FALSE;
BOOL var_r30 = FALSE;
#if TARGET_PC
if (randomizer_IsActive()) {
// If we are giving a custom item, we want to set mParam0 to 0x100 so that instead of trying to search for an item
// actor that doesnt exist we want the game to create one using the item id in mGtItm.
if (g_randomizerState.getGiveItemToPlayerStatus() == RandomizerState::ITEM_IN_QUEUE) {
mDemo.setParam0(0x100);
}
}
#endif
if (mProcID == PROC_GET_ITEM || mProcID == PROC_INSECT_CATCH ||
(mProcID == PROC_PREACTION_UNEQUIP && !checkNoUpperAnime()))
{
@@ -2296,6 +2588,11 @@ int daAlink_c::procCoGetItemInit() {
} else {
item_no = dComIfGp_event_getGtItm();
}
#if TARGET_PC
if (randomizer_IsActive() && g_randomizerState.getGiveItemToPlayerStatus() == RandomizerState::ITEM_IN_QUEUE) {
g_randomizerState.setGiveItemToPlayerStatus(RandomizerState::CLEAR_QUEUE);
}
#endif
fpc_ProcID item_partner_id = fopAcM_createItemForPresentDemo(&current.pos, item_no, 0, -1,
fopAcM_GetRoomNo(this), NULL, NULL);
@@ -2523,8 +2820,10 @@ int daAlink_c::procCoGetItem() {
} else if (mProcVar2.field_0x300c == 0x23 && checkStageName("D_MN11")) {
field_0x32cc = 0x5C0;
} else if (mProcVar2.field_0x300c == 0xE0) {
if (dComIfGs_getPohSpiritNum() == 20) {
// Don't show special text in rando
if (dComIfGs_getPohSpiritNum() == 20 IF_DUSK(&& !randomizer_IsActive())) {
field_0x32cc = 0x4CF;
// Rando gives poe soul after the text, so it'll never hit this
} else if (dComIfGs_getPohSpiritNum() == 60) {
field_0x32cc = 0x4D0;
} else {
@@ -3005,6 +3304,15 @@ int daAlink_c::procCoDeadInit(int param_0) {
field_0x3080 = 0;
mProcVar5.field_0x3012 = 0x3F;
field_0x3198 = -1;
#if TARGET_PC
// trigger archipelago death link if applicable
if (dusk::archi::ArchipelagoContext::IsConnected()) {
dusk::archi::ArchipelagoContext::TryHandleDeathLink();
}
#endif
return 1;
}
@@ -4014,6 +4322,10 @@ int daAlink_c::procGanonFinishInit() {
dusk::m_speedrunInfo.stopRun();
}
}
if (dusk::archi::ArchipelagoContext::IsConnected()) {
dusk::archi::ArchipelagoContext::TryHandleGameComplete();
}
#endif
return 1;
@@ -4548,6 +4860,13 @@ int daAlink_c::procCoWarpInit(int param_0, int param_1) {
(checkItemGet(dItemNo_DUNGEON_BACK_e, 1) &&
strcmp(stageName, dComIfGs_getWarpStageName()) == 0))
{
#if TARGET_PC
// In rando, only clear the Ooccoo slot if Ooccoo is in it
u8 ooccooSlot = dComIfGs_getItem(SLOT_18, false);
if (!randomizer_IsActive() || ooccooSlot == dItemNo_Randomizer_DUNGEON_EXIT_e ||
ooccooSlot == dItemNo_Randomizer_DUNGEON_EXIT_2_e ||
ooccooSlot == dItemNo_Randomizer_LV7_DUNGEON_EXIT_e)
#endif
dComIfGs_setItem(SLOT_18, dItemNo_NONE_e);
dComIfGs_resetLastWarpAcceptStage();
}
+11 -1
View File
@@ -144,7 +144,7 @@ void daAlink_c::handleQuickTransform() {
procCoMetamorphoseInit();
}
bool daAlink_c::checkGyroAimContext() {
bool daAlink_c::checkAimContext() {
switch (mProcID) {
case PROC_SUBJECTIVITY:
case PROC_SWIM_SUBJECTIVITY:
@@ -175,3 +175,13 @@ bool daAlink_c::checkGyroAimContext() {
return false;
}
}
bool daAlink_c::checkAimInputContext() {
switch (mProcID) {
case PROC_HOOKSHOT_ROOF_WAIT:
case PROC_HOOKSHOT_WALL_WAIT:
return false;
default:
return checkAimContext();
}
}
+29 -3
View File
@@ -1191,6 +1191,19 @@ void daAlink_c::setLightningSwordEffect() {
emitter = setEmitter(&field_0x327c[i], effName[i], &current.pos, &shape_angle);
if (emitter != NULL) {
emitter->setGlobalRTMatrix(mSwordModel->getBaseTRMtx());
#if TARGET_PC
// Apply custom light sword glow if applicable
const auto& lightSwordGlowColor = dusk::getSettings().cosmetics.lightSwordGlowColor.getValue();
if (dusk::cosmetics::is_valid_hex_color_str(lightSwordGlowColor)) {
GXColor color = dusk::cosmetics::hex_color_str_to_gx_color(lightSwordGlowColor);
emitter->setGlobalEnvColor(color.r, color.g, color.b);
emitter->setGlobalPrmColor(color.r, color.g, color.b);
} else if (lightSwordGlowColor == "Rainbow") {
GXColor color = dusk::cosmetics::get_rainbow_rgb(127.5f);
emitter->setGlobalEnvColor(color.r, color.g, color.b);
emitter->setGlobalPrmColor(color.r, color.g, color.b);
}
#endif
}
}
} else {
@@ -2028,11 +2041,10 @@ void daAlink_blur_c::traceBlur(cXyz const* param_0, cXyz const* param_1, s16 par
}
void daAlink_blur_c::draw() {
ZoneScoped;
j3dSys.reinitGX();
#ifdef TARGET_PC
TGXTexObj texObj;
#else
#if !TARGET_PC
static TGXTexObj texObj;
#endif
static GXColor nColor0 = {0xFF, 0xFF, 0xFF, 0x14};
@@ -2040,11 +2052,25 @@ void daAlink_blur_c::draw() {
GXSetNumIndStages(0);
nColor0.a = field_0x20;
#if TARGET_PC
if (mpCachedBlurTex != m_blurTex) {
mBlurTexObj.reset();
GXInitTexObj(&mBlurTexObj,
reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(m_blurTex) + m_blurTex->imageOffset),
16, 4, GX_TF_I4, GX_CLAMP, GX_CLAMP, GX_FALSE);
GXInitTexObjLOD(
&mBlurTexObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1);
mpCachedBlurTex = m_blurTex;
}
GXLoadTexObj(&mBlurTexObj, GX_TEXMAP0);
#else
GXInitTexObj(&texObj, (void*)((uintptr_t)m_blurTex + m_blurTex->imageOffset), 16, 4, GX_TF_I4,
GX_CLAMP, GX_CLAMP, GX_FALSE);
GXInitTexObjLOD(&texObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE,
GX_ANISO_1);
GXLoadTexObj(&texObj, GX_TEXMAP0);
#endif
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBA4, 8);
GXClearVtxDesc();
+23
View File
@@ -136,8 +136,26 @@ void daAlink_c::hsChainShape_c::draw() {
}
}
} else {
#if TARGET_PC
cXyz hsInterpTop, hsInterpRoot, hsInterpSubRoot, hsInterpSubTop;
if (dusk::frame_interp::is_enabled() && alink->mHsChainInterpPrevValid && alink->mHsChainInterpCurrValid) {
const f32 alpha = dusk::frame_interp::get_interpolation_step();
hsInterpTop = alink->mHsChainInterpPrevTop + (alink->mHsChainInterpCurrTop - alink->mHsChainInterpPrevTop) * alpha;
hsInterpRoot = alink->mHsChainInterpPrevRoot + (alink->mHsChainInterpCurrRoot - alink->mHsChainInterpPrevRoot) * alpha;
hsInterpSubRoot = alink->mHsChainInterpPrevSubRoot + (alink->mHsChainInterpCurrSubRoot - alink->mHsChainInterpPrevSubRoot) * alpha;
hsInterpSubTop = alink->mHsChainInterpPrevSubTop + (alink->mHsChainInterpCurrSubTop - alink->mHsChainInterpPrevSubTop) * alpha;
} else {
hsInterpTop = alink->getHsChainTopPos();
hsInterpRoot = alink->getHsChainRootPos();
hsInterpSubRoot = alink->getHsSubChainRootPos();
hsInterpSubTop = alink->getHsSubChainTopPos();
}
const cXyz& chainRootPos = hsInterpRoot;
const cXyz& chainTopPos = hsInterpTop;
#else
const cXyz& chainRootPos = alink->getHsChainRootPos();
const cXyz& chainTopPos = alink->getHsChainTopPos();
#endif
cXyz maxDistance = chainRootPos - chainTopPos;
f32 maxDistanceF = maxDistance.abs();
@@ -200,8 +218,13 @@ void daAlink_c::hsChainShape_c::draw() {
}
}
#if TARGET_PC
const cXyz& subChainRootPos = hsInterpSubRoot;
const cXyz& subChainTopPos = hsInterpSubTop;
#else
const cXyz& subChainRootPos = alink->getHsSubChainRootPos();
const cXyz& subChainTopPos = alink->getHsSubChainTopPos();
#endif
maxDistance = subChainRootPos - subChainTopPos;
maxDistanceF = maxDistance.abs();
+58 -11
View File
@@ -11,8 +11,10 @@
#include "d/actor/d_a_tag_mhint.h"
#if TARGET_PC
#include "dusk/gyro.h"
#include "dusk/action_bindings.h"
#include "dusk/gyro.h"
#include "dusk/mouse.h"
#include "dusk/touch_camera.h"
#endif
bool daAlink_c::checkNoSubjectModeCamera() {
@@ -120,18 +122,28 @@ BOOL daAlink_c::setBodyAngleToCamera() {
var_f31 /= dComIfGp_getCameraZoomScale(field_0x317c);
}
shape_angle.y = shape_angle.y + (var_f31 * cM_ssin(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonXAxis ? -1.0f : 1.0f)));
sp8 = mBodyAngle.x + (var_f31 * cM_scos(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonYAxis ? -1.0f : 1.0f)));
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
#if TARGET_PC
if (dusk::getSettings().game.enableMouseAim && checkAimInputContext()) {
sp8 = mBodyAngle.x;
} else
#endif
{
shape_angle.y = shape_angle.y + (var_f31 * cM_ssin(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonXAxis ? -1.0f : 1.0f)));
sp8 = mBodyAngle.x + (var_f31 * cM_scos(mStickAngle) IF_DUSK(* (dusk::getSettings().game.invertFirstPersonYAxis ? -1.0f : 1.0f)));
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
}
}
} else {
sp8 = mBodyAngle.x;
}
#if TARGET_PC
if (dusk::getSettings().game.enableGyroAim && checkGyroAimContext()) {
if ((dusk::getSettings().game.enableGyroAim ||
dusk::getSettings().game.enableMouseAim) &&
checkAimInputContext())
{
f32 gyro_scale = 1.0f;
if (checkWolfEyeUp()) {
gyro_scale *= 0.6f;
@@ -141,17 +153,52 @@ BOOL daAlink_c::setBodyAngleToCamera() {
gyro_scale /= dComIfGp_getCameraZoomScale(field_0x317c);
}
f32 gy_yaw = 0.f;
f32 gy_pitch = 0.f;
dusk::gyro::getAimDeltas(gy_yaw, gy_pitch);
f32 final_yaw = 0.f;
f32 final_pitch = 0.f;
if (dusk::getSettings().game.enableMouseAim) {
dusk::mouse::getAimDeltas(final_yaw, final_pitch);
}
if (dusk::getSettings().game.enableGyroAim) {
f32 gyro_yaw = 0.f;
f32 gyro_pitch = 0.f;
dusk::gyro::getAimDeltas(gyro_yaw, gyro_pitch);
final_yaw += gyro_yaw;
final_pitch += gyro_pitch;
}
shape_angle.y = shape_angle.y + cM_rad2s(gy_yaw * gyro_scale);
sp8 = sp8 + cM_rad2s(gy_pitch * gyro_scale);
shape_angle.y = shape_angle.y + cM_rad2s(final_yaw * gyro_scale);
sp8 = sp8 + cM_rad2s(final_pitch * gyro_scale);
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
}
}
if (dusk::getSettings().game.enableTouchControls && checkAimInputContext()) {
f32 touchYawDp = 0.0f;
f32 touchPitchDp = 0.0f;
if (dusk::touch_camera::consume_delta(touchYawDp, touchPitchDp)) {
f32 scale = 1.0f;
if (checkWolfEyeUp()) {
scale *= 0.6f;
}
if (dComIfGp_checkPlayerStatus0(0, 0x200000)) {
scale /= dComIfGp_getCameraZoomScale(field_0x317c);
}
const f32 yawDeg = -touchYawDp * dusk::touch_camera::YAW_DEGREES_PER_DP * scale *
dusk::getSettings().game.touchCameraXSensitivity;
const f32 pitchDeg = touchPitchDp * dusk::touch_camera::PITCH_DEGREES_PER_DP *
scale * dusk::getSettings().game.touchCameraYSensitivity;
shape_angle.y = shape_angle.y + cM_deg2s(yawDeg);
sp8 = sp8 + cM_deg2s(pitchDeg);
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
sp8 = mBodyAngle.x;
}
}
}
#endif
if (checkNotItemSinkLimit() && sp8 > 0) {
+2 -2
View File
@@ -348,7 +348,7 @@ void daAlink_c::changeLink(int param_0) {
initModel(static_cast<J3DModelData*>(dComIfG_getObjectRes(l_mArcName, "al_hands.bmd")), 0);
#if TARGET_PC
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.freeMagicArmor)
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.armorRupeeDrain.getValue() != dusk::MagicArmorMode::NORMAL)
#else
if (dComIfGs_getRupee() != 0)
#endif
@@ -458,7 +458,7 @@ void daAlink_c::changeLink(int param_0) {
field_0x06f0 = field_0x064C->getMaterialNodePointer(2)->getShape();
#if TARGET_PC
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.freeMagicArmor) {
if (dComIfGs_getRupee() != 0 || dusk::getSettings().game.armorRupeeDrain.getValue() != dusk::MagicArmorMode::NORMAL) {
#else
if (dComIfGs_getRupee() != 0) {
#endif
+9
View File
@@ -18,6 +18,10 @@
#include "c/c_damagereaction.h"
#include <cmath>
#if TARGET_PC
#include "dusk/randomizer/game/tools.h"
#endif
enum B_bq_RES_File_ID {
/* BCK */
/* 0x07 */ BCK_BQ_APPEAR = 0x7,
@@ -896,6 +900,11 @@ static void b_bq_end(b_bq_class* i_this) {
i_this->mMode = 1;
int sw = fopAcM_GetParam(a_this) >> 0x18;
#if TARGET_PC
if (randomizer_IsActive()) {
checkTransformFromWolf(); // If the player is wolf, they will softlock after the defeat cutscene is completed.
}
#endif
dComIfGs_onSwitch(sw, fopAcM_GetRoomNo(a_this));
// fallthrough
}
+9
View File
@@ -4084,6 +4084,15 @@ void daB_DS_c::executeBattle2Dead() {
camera->mCamera.SetTrimSize(0);
dComIfGp_event_reset();
dComIfGs_onStageBossEnemy(0x13);
#if TARGET_PC
if (randomizer_IsActive()) {
// Give the boss item
u8 agDungeonReward = randomizer_getItemAtLocation("Arbiters Grounds Dungeon Reward");
g_randomizerState.addItemToEventQueue(agDungeonReward);
// Set custom item flag
dComIfGs_onItem(0x9E, -1);
}
#endif
/* dSv_event_flag_c::F_0265 - Arbiter's Grounds - Arbiter's Grounds clear */
dComIfGs_onEventBit(0x2010);
fopAcM_delete(this);
+9
View File
@@ -5472,6 +5472,15 @@ int daB_ZANT_c::create() {
fopAcM_ct(this, daB_ZANT_c);
OS_REPORT("B_ZANT PARAM %x\n", fopAcM_GetParam(this));
#if TARGET_PC
// Due to our loads being so much faster, Zant can initialize *before* the player
// This breaks respawning in the final phase of the fight when it tries
// to load the player's position
if (daPy_getPlayerActorClass() == NULL) {
return cPhs_INIT_e;
}
#endif
mSwbit = fopAcM_GetParam(this);
if (mSwbit != 0xFF) {
if (dComIfGs_isSwitch(mSwbit, fopAcM_GetRoomNo(this))) {
+27
View File
@@ -530,6 +530,33 @@ int daDitem_c::execute() {
}
mSound.framework(0, dComIfGp_getReverb(fopAcM_GetRoomNo(this)));
#if TARGET_PC
// Certain items use field models that are too big to fit in link's hands so we want to scale them down to fit.
if (randomizer_IsActive()) {
switch (m_itemNo)
{
case dItemNo_Randomizer_MIRROR_PIECE_1_e:
case dItemNo_Randomizer_MIRROR_PIECE_2_e:
case dItemNo_Randomizer_MIRROR_PIECE_3_e:
case dItemNo_Randomizer_MIRROR_PIECE_4_e:
{
scale.x = 0.05f;
break;
}
case dItemNo_Randomizer_MASTER_SWORD_e:
case dItemNo_Randomizer_LIGHT_SWORD_e:
{
scale.x = 0.001f;
break;
}
default:
{
break;
}
}
}
#endif
return 1;
}
+13
View File
@@ -10,6 +10,9 @@
#include "d/actor/d_a_midna.h"
#include "d/d_door_param2.h"
#include "d/actor/d_a_player.h"
#if TARGET_PC
#include "d/actor/d_a_alink.h"
#endif
#include "d/d_com_inf_game.h"
#include "d/d_msg_object.h"
#include "d/d_map_path_dmap.h"
@@ -313,7 +316,17 @@ int daDoor20_c::checkOpenMsgDoor(int* param_1) {
return 1;
}
field_0x624.init(NULL, msgNo, 0, NULL);
#if TARGET_PC
int rv = 1;
// If we are in SPR, we don't want Yeta's msg flow to prevent us from opening the door if we haven't talked to her.
if (randomizer_IsActive() && !daAlink_c::checkStageName("D_MN11"))
{
rv = field_0x624.checkOpenDoor(this, param_1);
}
#else
int rv = field_0x624.checkOpenDoor(this, param_1);
#endif
dMsgObject_endFlowGroup();
return rv;
}
+13 -3
View File
@@ -11,6 +11,11 @@
#include "f_op/f_op_actor_enemy.h"
#include <cstring>
#if TARGET_PC
#include "dusk/randomizer/game/randomizer_context.hpp"
#endif
class daE_HP_HIO_c : public JORReflexible {
public:
daE_HP_HIO_c();
@@ -726,11 +731,16 @@ void daE_HP_c::executeDead() {
fopAcM_onSwitch(this, bitSw);
}
dComIfGs_addPohSpiritNum();
#if TARGET_PC
if (randomizer_IsActive()) {
g_randomizerState.handlePoeItem(bitSw);
} else
#endif
dComIfGs_addPohSpiritNum();
field_0x784 = -1;
if (dComIfGs_getPohSpiritNum() == 20) {
if (dComIfGs_getPohSpiritNum() == 20 IF_DUSK(&& !randomizer_IsActive())) {
dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[0x1c9]);
}
@@ -752,7 +762,7 @@ void daE_HP_c::executeDead() {
field_0x788 = 1;
}
}
} else if (field_0x788 != 0) {
} else if (field_0x788 != 0 IF_DUSK(|| randomizer_IsActive())) {
fopAcM_createDisappear(this, &current.pos, 8, 3, 0xff);
fopAcM_delete(this);
} else {
+4 -1
View File
@@ -396,7 +396,10 @@ inline int daE_MD_c::create() {
int phase_state = dComIfG_resLoad(&mPhase, "E_MD");
if (phase_state == cPhs_COMPLEATE_e) {
OS_REPORT("E_MD PARAM %x\n", fopAcM_GetParam(this));
if (cDmr_SkipInfo != 0 && current.pos.z > -1500.0f) {
// Always create the armor in rando (otherwise ball and chain won't spawn
// if the player leaves and re-enters without getting it)
if (cDmr_SkipInfo != 0 && current.pos.z > -1500.0f IF_DUSK(&& !randomizer_IsActive())) {
return cPhs_ERROR_e;
}

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