491 Commits
Author SHA1 Message Date
popux 0fd290c8c3 Fix 3 2026-10-21 19:31:56 +02:00
popux b20abed21e Fix 2 2026-10-21 19:31:42 +02:00
popux c4f12ad0a5 Fix 2026-10-21 19:31:31 +02:00
popux 60989596d5 Decals fix 2026-10-21 19:31:03 +02:00
popux 256323a109 Filter 2026-10-21 19:30:45 +02:00
popux 1e46e68933 format 2026-10-21 19:30:26 +02:00
fgsfds 32a1cb9f26 Merge pull request #747 from johnmcollier/stop-text-input
Prevent keyboard events from being swaollwed on certain Wayland systems
2026-08-13 07:51:05 +02:00
John Collier 9f30f50b79 Prevent keyboard events from being swaollwed on certain Wayland systems
Signed-off-by: John Collier <6880023+johnmcollier@users.noreply.github.com>
2026-08-13 01:10:48 -04:00
fgsfds 514bf7affd Merge pull request #731 from fpiesche/rename-freedesktop
Rename freedesktop
2026-05-29 09:46:49 +02:00
Florian Piesche 7477a6ce44 Update flatpak runtime 2026-05-26 13:13:55 +01:00
Florian Piesche f7c0cb8b03 update workflow to new freedesktop name 2026-05-26 13:09:30 +01:00
Florian Piesche accb882a36 Rename FreeDesktop files 2026-05-26 13:04:46 +01:00
fgsfds 0750c54200 Merge pull request #729 from ZenithMDC/mousewheel-scrollable-menus
Add mousewheel scrolling to scrollable menus
2026-05-25 15:06:30 +02:00
Matthew Coppola b81b7e260b Add mousewheel scrolling to scrollable menus 2026-05-25 08:24:12 -04:00
fgsfds 3f47f1ec6f Merge pull request #443 from blaiz/all-guns-cheat-multiplayer
Make "All Guns in Solo" cheat work in multiplayer
2026-05-24 10:45:03 +02:00
fgsfds f9d847df3b Merge pull request #698 from AL2009man/CameraAngleWrappingFix
Vertical Camera Angle wrapping fix
2026-05-24 10:44:00 +02:00
fgsfds c110f9cf42 Merge pull request #725 from joshuarwood/camspy_light_fix
Allow player character to block lights in camspy mode
2026-05-23 20:49:53 +02:00
joshuarwood cce73d91ce test for eyespy before checking mode 2026-05-21 21:10:29 -05:00
joshuarwood 3360eb429d allow player character to block lights in camspy mode 2026-05-21 20:10:33 -05:00
fgsfds 132e59d3ec Merge pull request #723 from joshuarwood/visiblelos_edge_case
Reset hit prop to continue los test following a glass surface
2026-05-21 17:55:20 +02:00
joshuarwood c166cf0f15 reset hit prop to continue los test following a glass surface 2026-05-20 22:31:58 -05:00
fgsfds 20fc4c6cc7 port: #721: scale glare brightness with FOV; add glare brightness settings 2026-05-17 12:42:54 +02:00
fgsfds 309bd45a01 port: #718: disable linear filtering and mipmaps when three-point is enabled 2026-05-17 12:40:43 +02:00
fgsfds 45139a9293 Merge pull request #719 from jonaeru/fix-menutexture
Fix menu character and weapon texture corruption
2026-05-02 12:19:48 +02:00
Jonaeru 998eee9c61 Fix menu character and weapon texture corruption 2026-05-01 21:28:41 +09:00
fgsfds d8962763b7 port: don't apply linear mag filter when using three-point either 2026-04-28 18:48:55 +02:00
fgsfds 783791064b port: actually use the filter array for the previous fix instead of smoking crack 2026-04-28 18:45:08 +02:00
fgsfds 8106349540 port: if three-point filtering is enabled, don't also enable bilinear filtering 2026-04-28 18:32:23 +02:00
fgsfds bed3bf52d0 Merge pull request #715 from Alex-LeTux/patch-1
Remove trailing slash from directory checks
2026-04-25 19:31:47 +02:00
Alex LeTux f25721da8f Remove trailing slash from directory checks
> The slash is unnecessary and causes issues when building with a recent version of MinGW.
2026-04-24 11:23:38 +02:00
fgsfds 7c949ed9d7 Merge pull request #675 from rafccq/port-tex-mips-aniso
Mipmaps and Anisotropic Filtering
2026-03-23 10:34:33 +01:00
fgsfds 8470d50f21 Merge pull request #697 from TartanSpartan/fix-scissor-viewport
Improve scissor operations to correct "thin blue line" bug
2026-03-23 10:33:12 +01:00
fgsfds 27b2dcc27d Merge pull request #700 from TartanSpartan/acknowledge-npc-gifts
Acknowledge npc gifts and suppress spurious cutscene notifications
2026-03-23 10:31:40 +01:00
fgsfds 2626434b69 Merge pull request #701 from TartanSpartan/fix-cheats-across-optimizations
Fix issue for some cheats across build optimizations
2026-03-23 10:30:44 +01:00
fgsfds 11df50b3ad Merge pull request #707 from cylonicboom/port
fixup keyboard input + vi insert shortcut
2026-03-14 23:35:33 +01:00
Catherine Reprobate ccb3c8668d fixup keyboard input + vi insert shortcut 2026-03-14 12:57:55 -07:00
fgsfds d58a423e5f Merge pull request #706 from joshuarwood/shield_light_fix
Fix for light visibility through shields
2026-03-14 09:15:55 +01:00
joshuarwood fc70da875e add a comment describing PC specific shield handling 2026-03-13 18:01:10 -05:00
fgsfds d4ac8b155d Merge pull request #705 from joshuarwood/fix_chr_light_regression
Fix a regression in light artifact handling through character models
2026-03-13 20:45:33 +01:00
joshuarwood 0946cd18c6 disable bbox padding when performing light los test to prevent shield transparency from blocking light artifacts 2026-03-12 23:59:10 -05:00
joshuarwood 23aafa4ffa use texturenum -1 for chr hits because cheap version of chrTestHit returns an uninitialized value 2026-03-12 18:31:17 -05:00
TartanSpartan 426f9c6890 Fix issue for some cheats across build optimizations 2026-02-12 00:55:28 +00:00
TartanSpartan cc3886888a Suppress gadget notifications in cutscenes 2026-02-12 00:18:36 +00:00
TartanSpartan 55ca51d8cc Have HUD acknowledge new weapons gifted from NPCs 2026-02-11 22:25:25 +00:00
AL2009man f251653317 Vertical camera angle wrapping fix
Solves a issue when using Input Remapper's Mouse-based Reset to Horizon camera function (e.g. Steam Input), where the recenter couldn't stay centered.
2026-01-31 23:38:58 -05:00
TartanSpartan bcb8c2720a Improve scissor operations for upstream. 2026-01-29 22:12:30 +00:00
fgsfds 246d737663 Merge pull request #680 from ZenithMDC/preserve-cs-sim-list
Preserve Combat Simulator sim list after Co-Op/Counter-Op
2026-01-07 09:21:18 +01:00
fgsfds 425b51e51c input: fix build with SDL<2.0.16 2026-01-07 09:17:34 +01:00
fgsfds 6e6ffad1a1 Merge pull request #687 from AL2009man/KB/M-Confirm-Cancel
default PC's KB/M Menu bindings navigation now reflects newer PC Games' KB/M setup
2026-01-04 20:47:11 +01:00
Al. Lopez 2028ae7412 changes default PC's Menu bindings to reflect Modern games' Menu UI design
Those who are playing the PC Port of Perfect Dark for the first time, but coming from newer PC Versions' menu bindings will find out Menu bindings don't confined towards a modern standard. This PR addresses it while retaining backwards compatibility.

the RETURN/ENTER key will become a proper CONFIRM action, as opposed to emulating as a START button. (the emulated START button will still be TAB key), while Right Mouse Click now behaves as a CANCEL key. 

This won't affect existing Perfect Dark PC Players' existing bindings. but the next time you reset the default Key Bindings will experience a more streamlined setup.
2026-01-03 20:14:20 -05:00
Matthew Coppola 0c82545ba9 Preserve Combat Simulator sim list after Co-Op/Counter-Op 2025-12-26 21:25:10 -05:00
fgsfds 2550ce72f4 Merge pull request #684 from AL2009man/XboxREADMEFix
corrected Xbox pad name (LS Click) on Crouch cycle over at `README.md` Controls page
2025-12-20 10:27:31 +01:00
fgsfds 50481b77d0 Merge pull request #683 from qubitnano/bcachefs
fix homeDir check
2025-12-20 10:27:10 +01:00
Al. Lopez 4ee8f3c077 Corrected Xbox Pad page on README.md
last I check: Xbox Controller doesn't refer "Left Stick Click" as "L3".

PlayStation and Steam Deck/Steam Controller (2026) actually refers their variant as "L3".
2025-12-19 21:01:25 -05:00
qubitnano 0df84ff180 fix homeDir check
bcachefs directories return stat.st_size=0
2025-12-19 20:18:18 -05:00
fgsfds a6374b016d Merge pull request #679 from ZenithMDC/fix-cs-load-settings-clobber
Prevent Combat Simulator 'Load Settings' clobber
2025-12-07 09:56:10 +01:00
Matthew Coppola 75d1b8ffd2 Prevent Combat Simulator 'Load Settings' clobber 2025-12-07 03:04:27 -05:00
fgsfds 8165b5005e Merge pull request #677 from AL2009man/CrosshairSwivelFix
fixed Crosshair Swivel conflicting when using Mixed Input
2025-12-05 12:55:07 +01:00
AL2009man 2d0375da2e fixed Crosshair Swivel conflicting when using Mixed Input
Addresses the issue with Crosshair Swivel conflciting with each other when using both Mouse and Camera at the same time.
2025-12-04 14:55:31 -05:00
fgsfds 4bcfeddca7 Merge pull request #674 from ZenithMDC/limit-start-armed-to-csim
Limit 'Start Armed' option to Combat Simulator
2025-12-04 18:20:39 +01:00
Raf 2d390ae5ce small code simplification 2025-12-04 18:55:52 +08:00
Raf c303c81f88 gfx: mipmaps and anisotropic filtering 2025-12-04 18:09:49 +08:00
Matthew Coppola 6b0c4a11e2 Limit 'Start Armed' option to Combat Simulator 2025-12-03 19:35:24 -05:00
fgsfds 7f68c46959 Merge pull request #671 from joshuarwood/light_fix_for_laser
Exclude laser doors from lighting line-of-sight test
2025-11-23 08:38:08 +01:00
joshuarwood f3f2a593e8 exclude laser doors from los test 2025-11-22 00:39:35 -06:00
fgsfds 79711364bb Merge pull request #668 from joshuarwood/light_fix_for_bg_glass
Fix for background lights
2025-11-09 10:39:11 +01:00
fgsfds 0896860d58 Merge pull request #670 from Project516/patch-1
fix link to fast
2025-11-09 10:36:46 +01:00
fgsfds e1dd49fc3a Merge pull request #669 from joshuarwood/light_fix_for_xlu_prop
Fix light transparency for tinted glass doors
2025-11-09 10:36:28 +01:00
joshuarwood b53a62189b protect against surface indexing errors 2025-11-09 01:30:49 -06:00
Project516 77dc12e41f fix link to fast 2025-11-08 15:36:29 -06:00
joshuarwood 42ef08d662 check surfacetype to better skip glass props 2025-11-07 19:50:42 -06:00
joshuarwood f5cbfe6692 disable xlu surface hits with a global to avoid initialization errors with struct flag 2025-11-07 18:38:27 -06:00
joshuarwood 550f1d3182 add flag to ignore line-of-sight hits for transparent background surfaces 2025-11-07 15:18:02 -06:00
joshuarwood 7a728c7feb Removing commit that was intended for a different branch
This reverts commit 857e755b92.
2025-11-07 15:11:09 -06:00
joshuarwood 857e755b92 added flag to ignore line-of-sight hits for transparent background surfaces 2025-11-07 15:08:50 -06:00
fgsfds 8ea7e7b410 Merge pull request #661 from AL2009man/RawInputFix
Temporarily disables RawInput driver by default
2025-10-08 20:50:23 +02:00
AL2009man 6dd3ec7fda Temporarily disables RawInput driver
Due to a Windows Update regression: RawInput driver has a issue related to Xbox Controllers' trigger input only being detected. For safety reasons, `useRawInput` will be disabled by default until the bug is fixed on Microsoft's end.

for those who still needs it: you can head over to `pd.ini` and revert `useRawInput` back to `1`
2025-10-08 14:15:58 -04:00
fgsfds bb4fcffeb5 port: fix #650 2025-08-25 09:26:07 +02:00
fgsfds 498e1667a4 Merge pull request #631 from AL2009man/CrosshairFix
Crosshair Edge Deadzone slider and fixed `insightaim` Camera Movement
2025-08-23 09:17:13 +02:00
fgsfds 19541418b0 Merge pull request #642 from OlegAckbar/port
port: fix multi-monitor issues on Wayland
2025-08-10 12:28:58 +02:00
fgsfds 75952f0395 Merge pull request #643 from OlegAckbar/window-title
port: do not change window title
2025-08-10 12:26:10 +02:00
Oleg 04d280cd42 port: do not change window title 2025-08-10 12:05:46 +03:00
Oleg 58c2f9d8fa port: fix multi-monitor issues on Wayland 2025-08-10 12:04:29 +03:00
fgsfds 6591281d99 Merge pull request #636 from AL2009man/SteamDeck-HID
Steam Controller/Deck HIDAPI Hint Support
2025-07-22 21:33:55 +02:00
AL2009man 5fd4a431b1 fixup whitespace on SDL_SetHint 2025-07-13 06:31:11 -04:00
AL2009man 27223802be added Steam Controller/Deck HIDAPI Hint
This enables HIDAPI support for Steam Controller (Bluetooth only) and Steam Deck.

Note: while SteamDeck HIDAPI is enabled, it works best while in Desktop Mode and without Steam Client running in the background (will show the actual device name instead of "Steam Virtual Gamepad"). It may not support more advanced feature sets, and it only remains that case until Valve adds Motion Sensor passthru support to SDL2/SDL3 while using SteamInput.
2025-07-12 14:56:41 -04:00
Al. Lopez 09df313d09 remove gyro leftover text 2025-06-27 21:24:25 -04:00
AL2009man 01b78105ff added Crosshair Edge Boundary Box 2025-06-27 21:18:52 -04:00
fgsfds 618a1f3386 port: set g_MaxExplosions to 6 by default 2025-06-14 09:59:19 +02:00
fgsfds 4bd6dd8617 Merge pull request #597 from rafccq/port-no-doors
"No Doors" option in multiplayer
2025-06-11 12:40:33 +02:00
fgsfds eabd7a438f Merge pull request #623 from rafccq/port-max-explosions
Maximum number of explosions now can be changed from the .ini file
2025-06-11 12:23:31 +02:00
fgsfds e8a69f39db port: fix deformation-related vertex explosions on 64-bit 2025-06-06 11:18:50 +02:00
fgsfds 38cb1557d0 cmake: enable compile_commands.json 2025-06-06 11:04:40 +02:00
Raf 97444de634 Merge branch 'fgs-port' into port-max-explosions 2025-06-04 01:21:03 -03:00
fgsfds d9185982f8 port: fix sun glare 2025-06-02 23:07:35 +02:00
fgsfds 790374e95f port: fix whitespace in input.c 2025-06-01 10:27:16 +02:00
fgsfds 9c98fe7976 port: fix inputMouseGetAbsScaledDelta 2025-06-01 10:23:56 +02:00
fgsfds 9bffab7e3e port: do not read past the end of EEPROM when scanning for headers 2025-05-31 13:24:13 +02:00
Raf 8037431686 port: moved the max explosions config to the .ini file 2025-05-30 01:25:18 -03:00
fgsfds a040b29d40 Merge pull request #621 from rafccq/port-enh-mpsetupfile
port-mp-setups: a bunch of bug fixes
2025-05-29 21:10:35 +02:00
Raf 5a3d45de65 port-mp-setups: spaces -> tabs (2) 2025-05-29 16:08:41 -03:00
Raf 5a90152991 port-mp-setups: spaces -> tabs (2) 2025-05-29 16:08:09 -03:00
Raf 8891bbf7ec port-mp-setups: spaces -> tabs 2025-05-29 16:05:25 -03:00
Raf abf2ae8115 Merge branch 'port-enh-mpsetupfile' of https://github.com/rafccq/perfect_dark into port-enh-mpsetupfile
# Conflicts:
#	src/game/filemgr.c
2025-05-29 15:33:58 -03:00
Raf 20bd9ddcbb port-mp-setups: a bunch of bug fixes
- only load the MP setup file when loading the agent, instead of when entering CS
- "clear default" was cause the game setup to become invalid upon re-entering it
- all challenges were showing the same text
2025-05-29 15:33:32 -03:00
Raf 1d7dd064fe port-mp-setups: a bunch of bug fixes
- only load the MP setup file when loading the agent, instead of when entering CS
- "clear default" was cause the game setup to become invalid upon re-entering it
- all challenges were showing the same text
2025-05-29 15:31:19 -03:00
fgsfds 629dbfe924 Merge pull request #613 from AL2009man/FOV-MouseSen-fix
Camera Sensitivity no longer tied to FOV Slider
2025-05-29 20:01:32 +02:00
fgsfds f72f93a270 Merge pull request #619 from AL2009man/PerfectQuakeDark2
Mouse Sensitivty cap increased to 30.00
2025-05-29 20:00:14 +02:00
AL2009man 57eead9078 cleaned up MouseGetScaledDelta and AbsScaledDelta
To prepare for the revised MouseScaledDelta: the current setup has been simplified for easier code reading
2025-05-29 00:07:33 -04:00
AL2009man 094d80a5cf fixed MouseSpeedX/Y config file number limit 2025-05-28 23:10:41 -04:00
AL2009man 11bf7aa638 Increased Mouse sensitivity to 30.00
this wil be more in line with id Tech's max mouse sens, which is also 30.00
2025-05-28 22:32:41 -04:00
Raf 79a47809da port-no-doors: another code quality improvement 2025-05-28 21:08:17 -03:00
Raf 33aa747386 port: enabled colors in the cmake build output 2025-05-28 21:00:16 -03:00
Raf a70868fba0 port-no-doors: moved new MP options to a new menu 2025-05-28 20:59:36 -03:00
Raf c866940873 port-no-doors: a couple code quality improvements 2025-05-28 20:57:21 -03:00
Raf 0973f70301 port-no-doors: reverted the menu changes 2025-05-28 20:55:01 -03:00
Raf 54b62c044f Merge branch 'port' into port-no-doors 2025-05-28 20:43:58 -03:00
fgsfds d5b4e0916c Merge pull request #618 from cylonicboom/pr/discover-dialogisopen
refactor(menu): rename unk5d5_06 and sp344 for clarity
2025-05-25 00:39:20 +02:00
Catherine Reprobate 45f25c704a refactor(menu): rename unk5d5_06 and sp344 for clarity
Backport from Friends of Joanna: renamed the bool member `unk5d5_06` in
the `menudata` struct to `isdialogopen` to clarify its purpose as a
dialog state flag. Also renamed the local bool variable `sp344` in
`menutick.c` to `isdialogopen` to reflect its relation to the struct
member. Updated all references for consistency and improved readability.
2025-05-24 13:38:43 -07:00
AL2009man d8aefc33fc fixed Sniper Rilfle zoom when using FOV higher than 60%
Removing the scaling entirely beraks Sniper Rifle zoom. So: we're switching back to FOV Scaling, but now it'll be based on `PLAYER_DEFAULT_FOV` instead of `60.0f`. This now ensures tha
2025-05-16 19:26:46 -04:00
AL2009man cdd116830d fixed tmp spacing 2025-05-16 00:50:57 -04:00
AL2009man 11d02dd8f2 last attempt on whitespace fix 2025-05-16 00:46:08 -04:00
AL2009man 73631e8d5f attempted whitespace fix 1 2025-05-16 00:42:34 -04:00
AL2009man a1136f4d61 fixed Mouse Sensitivity affecting FOV Slider
Your mouse sens scale should now behave exactly the same, regardless of FOV Slider
2025-05-16 00:36:17 -04:00
fgsfds 8bfaaf63ed Merge pull request #610 from joshuarwood/documented_zbuffer
Updated variable and function names for artifact handling
2025-05-12 16:43:07 +02:00
joshuarwood 2d59929261 syncing moved files 2025-05-11 12:23:32 -05:00
joshuarwood 86e6e54792 return ifdef to original position following the debugging tests 2025-05-11 12:22:01 -05:00
joshuarwood f12ae756ef rename game_13c510 files to artifact 2025-05-11 12:17:38 -05:00
joshuarwood 062de5bb7b clear up debugging statements 2025-05-11 11:59:11 -05:00
joshuarwood 400865ec25 added debugging to pin point seg fault 2025-05-03 20:17:29 -05:00
joshuarwood 0d6c557982 updated variable names to match Ryan Dwyer's work clarifying the zbuffer behavior 2025-05-03 19:57:52 -05:00
joshuarwood 75e34ace8c added Ryan Dwyer's comment describing how artifact handling behaves 2025-05-03 16:06:10 -05:00
joshuarwood a2428aac1e working to document format used for 16 bit depth integers 2025-05-02 11:53:02 -05:00
fgsfds 816d83a0b5 Merge pull request #605 from cylonicboom/pr/rename-unk008
rename `struct menudata.unk008|unk00c` properties
2025-04-28 09:23:05 +02:00
Catherine Reprobate 039eb8b562 rename struct menudata.unk00c-> prevmenudata 2025-04-27 16:01:10 -07:00
Catherine Reprobate 872aa3a4a4 rename struct menudata.unk008 -> prevmenuroot 2025-04-27 15:52:58 -07:00
fgsfds 4b8e1d52b5 port: move menuAlt functions to menu.c and make them global 2025-04-27 15:54:39 +02:00
fgsfds f96a03e60f port: clean up previous PR 2025-04-27 15:34:25 +02:00
fgsfds 9d2db1a346 Merge pull request #596 from rafccq/port-enh-mpsetupfile
Enhanced multiplayer game setup save files
2025-04-27 14:26:39 +02:00
fgsfds fc7141d0f2 Merge pull request #598 from AL2009man/PerfectQuakeDark
Mouse Sensitivity follows id Tech/Source sens scale
2025-04-27 13:46:01 +02:00
fgsfds f414e8a792 Merge pull request #601 from cylonicboom/pr/joyreset-on-controller-change
port: call `joyReset()` when changing controllers
2025-04-27 13:44:36 +02:00
Catherine Reprobate ab73fdcc30 fixup: include header for joyReset 2025-04-13 10:44:26 -07:00
Catherine Reprobate 30071e8f64 port: call joyReset() when changing controllers
This needs to be called for controller reassignments to take effect in
MP modes
2025-04-13 10:39:04 -07:00
AL2009man 9695856be6 updated player.c to account for 0.022f scale
while also changing input.c delta scale to ensure it has a divider
2025-04-11 19:24:25 -04:00
AL2009man 053f7dc8a5 Mouse Sensitivity follows Quake/id Tech mouse sens
this changes mouse sensitiivity scale to mirror id Tech's Mouse Sensitivity Scale. This also makes it easier for Steam Input users (Steam Deck and Steam Controller) to use Gyro To Mouse/Flick Stick's Natural Sensitivity Scale
2025-04-11 00:06:02 -04:00
Raf 52992009db port: no door option in multiplayer, moved the extra settings to a new sibling dialog 2025-04-04 01:49:15 +08:00
Raf 1555a4be84 missing semicolon after mkdir() in non-win platforms 2025-04-02 22:19:24 +08:00
Raf d4856a193b mpsetups: added weapon set num to the save file 2025-04-02 20:13:19 +08:00
Raf cb6dc1feab mpsetups: forgot to pop the dialog after import name conflict, removed debug print 2025-04-02 15:55:31 +08:00
Raf b93015c51c mpsetups: fixed reverse pitch/look ahead being reset when the mpsetups file is created for the first time 2025-04-02 00:33:45 +08:00
Raf 6198fbc479 mpsetups: a bunch of bug fixes
- "load settings" becoming invalid when entering and exiting the challenges screen
- when setting a setup as default, it would change the current setup
- larger window width causing the marquee text to be rendered off-bounds
- reduced the setup name's max length, as it wouldn't fit on the screen in some cases
2025-04-01 17:00:59 +08:00
Raf 0316317aa3 Merge branch 'fgs-port' into port-enh-mpsetupfile 2025-03-31 10:34:42 +08:00
Raf f9cfa0fa43 mpsetups: introduced "menu alt" button/key to toggle presets
Currently the "menu alt" (L/R buttons, or Ctrl/Alt keys) is fixed, but
we may make it bindable later
2025-03-31 10:34:25 +08:00
Raf 7a98095a0b mpsetups: bug fix - when deleting a setup that is behind the default setup in the list 2025-03-31 10:25:24 +08:00
Raf 8f477a36b6 mpsetups: convert existing setups from the eeprom, removed "combat settings" items from file menu
increased block size from 64 to 80 (it was insufficient)
2025-03-31 10:24:26 +08:00
Raf 4d4fa8f681 savebuffer: extended read/write to accept 64 bits, renamed a function, removed an unused function 2025-03-31 10:10:13 +08:00
fgsfds 0ac5fdd5c3 Merge pull request #593 from jonaeru/fix-mp-selectrandomweapon
Fix offset in weapon set by adding IR Scanner and Night Vision and Select Random Weapons feature
2025-03-30 18:44:18 +02:00
Jonaeru 33c5194a1b Fix "Select Dark" in Select Random Weapons feature to not select IR Scanner and Night Vision 2025-03-30 22:48:14 +09:00
Jonaeru edd58c8925 Fix offset in weapon set by adding IR Scanner and Night Vision 2025-03-30 22:31:51 +09:00
fgsfds e32d719c16 port: only enable SDL hints on SDL versions that support them 2025-03-29 12:48:38 +01:00
fgsfds be4d8330bd port: add settings for HIDAPI and raw input 2025-03-29 12:29:14 +01:00
fgsfds 91c207a51b Merge pull request #590 from AL2009man/SDLHint-Fix
SDL_SetHint Controller Update
2025-03-29 12:19:27 +01:00
fgsfds 0d76ad102f Merge pull request #589 from cylonicboom/pr/goggles-in-cs
Add Night Vision Goggles and IR Scanner to Combat Simulator
2025-03-29 12:03:54 +01:00
fgsfds 135c293656 Merge pull request #592 from peerchemist/port
Flatpak x86_64
2025-03-29 12:03:16 +01:00
Raf a1d6916871 mpsetups: manage default setup + save the selected random weapons 2025-03-29 18:34:01 +08:00
peerchemist 9a853077a0 correct Exec name 2025-03-29 11:15:57 +01:00
peerchemist dace9fd634 x86_64 2025-03-29 11:02:55 +01:00
Raf 9e19055348 mpsetups: fixed bugs caused by using a wrong constant + fixed the setup marquee display 2025-03-29 04:17:36 +08:00
Raf dcef8deed8 mpsetups: import/export settings 2025-03-29 02:57:55 +08:00
AL2009man c44704e2af added SDL Hint for Wii Controllers 2025-03-27 01:55:25 -04:00
AL2009man 1a5e42e55f changed note 2025-03-27 01:49:28 -04:00
AL2009man a26260e932 added SDL Hints field
For some reason: this sourceport isn't using SDL Hints. this is very crucial inorder to implement features sets like Gyro Aiming. Thus: most of the important hints will be forcefully enabled while improving Contorller compatibility when using RawInput
2025-03-27 01:47:49 -04:00
Raf 3d75365f2b mpsetups: increased max name length to 18 2025-03-27 01:01:46 +08:00
Raf ad9ed9ff3b mpsetupfile: scrapped groups, manage settings: rename/delete 2025-03-25 01:05:57 +08:00
Catherine Reprobate 4f55a41d99 add NVGs and IRGs to CS
- fixes n64-bug: NVGs and IR goggles should not be dual-wieldable
2025-03-23 12:48:16 -07:00
Catherine Reprobate 355f0ed0ee IR Goggle support for 4player and 1-2p draw fixes
- allocate memory for 4player's IR goggle scanlines
- fixes IR goggle alignment
- fixes IR lens for players 2 and 4
- fixes off-by-one rendering error for top two players (bottom of screen)
- fixes off-by-one rendering error for right-side players (right side of semicircle thing)
- fixes dark area flickering; use resolved shading for props if not wearing goggles
- port: fix IR goggle off-by-one draw issues
2025-03-23 12:47:06 -07:00
Raf f5d851f7c2 mpsetupfile (not 100% functional yet): load/save setup file, save new setups/groups, increased mp options/scenario data width 2025-03-24 03:33:34 +08:00
peerchemist 4019bd59cf Update io.github.fgsfdsfgs.perfect_dark.yaml 2025-03-18 09:13:23 +01:00
peerchemist 6c29e7ecc8 Update io.github.fgsfdsfgs.perfect_dark.sh 2025-03-18 09:00:38 +01:00
peerchemist e65f46d081 Update c-cpp.yml
It hardly makes sense to use 32bit binary for flatpak.
2025-03-18 08:51:17 +01:00
fgsfds 2ff8819265 Merge pull request #550 from ZenithMDC/slider-mouse-upgrades
Ergonomic upgrades for menu sliders while using the mouse
2025-03-16 09:03:23 +01:00
fgsfds 77d1ded519 Merge pull request #584 from SilentException/config-max-warning
Warn when CONFIG_MAX_SETTINGS limit is reached
2025-02-24 22:27:37 +01:00
SilentException 60b8e3b49e Log warning if configuration max settings is exceeded
+ snprintf instead of strncpy (null termination)
2025-02-24 21:35:02 +01:00
fgsfds 8b0b75d4ad port: increase CONFIG_MAX_SETTINGS 2025-02-24 20:26:38 +01:00
Matthew Coppola ea464ca6ac Allow dragging sliders with the mouse
Additional code was introduced to handle edge cases. Sliders are always
dimmed when clicked with the mouse, now. When the mouse button is
release, dimmed mode is turned off. This was done to prevent adjacent
slider items from being accidentally modified by moving the mouse over
them with the left mouse button held down, as well as to allow proper
functioning of deferred sliders with the mouse.
2025-02-24 00:05:51 -05:00
Matthew Coppola a9752198c3 Make mousescroll work effectively for fast sliders 2025-02-23 22:49:51 -05:00
Matthew Coppola fbd9ef002e Treat mousescroll as a mouse movement 2025-02-23 22:49:51 -05:00
Matthew Coppola e4972ddbe3 Allow adjusting sliders with mousescroll 2025-02-23 22:49:24 -05:00
fgsfds 8dbe6f2a63 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port 2025-02-22 13:51:02 +01:00
fgsfds 045c4c371a Revert "ci: temporarily disable flatpak autobuilds"
This reverts commit daade36e19.
2025-02-22 13:50:49 +01:00
fgsfds f4f1470e1e port: use a dynamic string for the vsync options 2025-02-22 13:48:25 +01:00
fgsfds 26251c0865 Update README.md 2025-02-22 13:28:23 +01:00
fgsfds ac4f317879 port: changes to the video settings PR:
- change FPS calculation to use average FPS, use real time instead of render time for interval timing

- remove Maximize Window (you already have a maximize button and it's saved to the INI)

- remove Display FPS Interval from settings (the average user won't care and whoever cares can change it in the INI)

- remove the tickrate override flag and implicit tickrate adjustment in the framerate limit option, instead add one checkbox to uncap tickrate (mostly because I'd like the game to default to the og 60 FPS cap since high FPS is still unstable)

- rearrange some options a bit
2025-02-22 13:22:00 +01:00
fgsfds e3104b7043 Merge pull request #538 from ZenithMDC/revamp-video-options
Allow changing video resolution at runtime + more
2025-02-22 11:26:43 +01:00
fgsfds 176b4282fc Merge pull request #577 from jonaeru/mp-random-weapon-filter
Add "Select Random Weapons" mp menu
2025-02-22 11:16:56 +01:00
fgsfds cd8f06d03a Merge pull request #578 from jonaeru/fix-friendly-fire
Fix to enable Friendly Fire option in Challenge
2025-02-22 11:15:38 +01:00
fgsfds 9cff3591dd port: add an option to make opposite c-buttons cancel each other
for #581
2025-02-22 10:49:48 +01:00
fgsfds daade36e19 ci: temporarily disable flatpak autobuilds
until this fucking action is fixed
2025-02-11 21:06:15 +01:00
fgsfds addc890628 ci: try to fix flatpak action 2025-02-11 20:47:52 +01:00
fgsfds 8a3dd74d5c port: add option to reload with use key in extcontrols 2025-02-11 20:02:35 +01:00
Jonaeru c0aa42759c fix "Select Random Weapons" mp menu, optionindex 2025-02-10 22:39:10 +09:00
Jonaeru b637c6aac6 Fix to enable Friendly Fire option in Challenge 2025-02-10 10:30:59 +09:00
Jonaeru 5cd436e848 Fix check status not being changed by Start button in Select Random Weapon Menu 2025-02-09 14:04:01 +09:00
Jonaeru d5225b7784 Fix Select Random Weapon Menu 2025-02-08 14:01:57 +09:00
Jonaeru 904faa5485 Add MP Select Random Weapon Menu 2025-02-08 14:01:22 +09:00
fgsfds f1084b6d93 ci: use ubuntu-22.04 for i686-linux because ubuntu-24.04 is wack 2025-01-25 12:00:48 +01:00
fgsfds 9a462d3ca8 port: log controller GUID to aid in binding generation 2025-01-25 11:55:50 +01:00
fgsfds 4f7817a0ca port: forgot the constant 2025-01-05 15:45:42 +01:00
fgsfds 5084b4be39 port: simplify the keyboard input a bit and match it to port-net's
backspace key now repeats properly

TYPE WITH KEYBOARD changes into a tooltip when typing

players with controllers are allowed to type, because that seems more convenient

players 2, 3 and 4 are allowed to type too if they hit the button, but only one player can have keyboard focus at a time
2025-01-05 15:27:45 +01:00
fgsfds a05c4290f5 Merge pull request #557 from ZenithMDC/text-input
Allow typing with keyboard in menuitemKeyboard
2025-01-05 13:44:43 +01:00
fgsfds 49cd478622 Merge pull request #564 from ZenithMDC/skip-credits
Allow skipping credits for the port
2024-12-29 15:05:55 +01:00
fgsfds 0443c708dd port: align size of bg light block to 4
this avoids unaligned accesses on ARM
2024-12-29 14:47:42 +01:00
fgsfds 7f105f1dcb port: on ARM, only enable DO_YIELD() if ARMv7 or ARM64 2024-12-29 13:56:44 +01:00
Matthew Coppola 721b9b004e Allow skipping credits for the port 2024-12-21 06:26:36 -05:00
fgsfds 23d5a5771a port: fix mouse X speed using wrong aspect in split screen 2024-12-20 13:38:19 +01:00
fgsfds 0701f43d6b Merge pull request #559 from cylonicboom/editorconfig
add editorconfig
2024-12-20 13:36:05 +01:00
fgsfds d5ae464f6d Merge pull request #561 from cylonicboom/rename-func0f0d5484
func0f0d5484 -> savebufferWriteData
2024-12-20 13:33:37 +01:00
Catherine Reprobate 701c854ced func0f0d5484 -> savebufferWriteData 2024-12-19 12:51:17 -08:00
Catherine Reprobate afd432444b add editorconfig 2024-12-19 10:14:50 -08:00
fgsfds 26b3b91433 Merge pull request #552 from ZenithMDC/resolution-independent-mouse-aim
Make mouse aim speed resolution-independent
2024-12-19 18:26:59 +01:00
Matthew Coppola 8945809c1f Factor in dstscroll to align mouse with chars in 3+ multiplayer 2024-12-17 17:40:10 -05:00
Matthew Coppola da07772b1c Allow typing with keyboard in menuitemKeyboard 2024-12-17 05:47:43 -05:00
fgsfds 1e76f6af69 port: actually parse allocation strings; double gfx buffer size on 64-bit 2024-12-17 10:44:33 +01:00
fgsfds a14e9ed97e port: retry creating SDL window when trying different GL versions 2024-12-11 14:06:44 +01:00
Matthew Coppola 615e9267d8 Make mouse aim speed resolution-independent 2024-12-10 17:36:57 -05:00
fgsfds 4f2b911802 Merge pull request #555 from ZenithMDC/fix-crash-on-copy
Prevent crash when copying player data
2024-12-09 23:34:30 +01:00
Matthew Coppola c43f550a7e Prevent crash when copying player data 2024-12-09 16:20:56 -05:00
fgsfds 2439eb6e8d Merge pull request #551 from ZenithMDC/increase-mouse-speed-precision
Increase precision for mouse speed options
2024-12-08 13:40:23 +01:00
fgsfds 903dd82ebf port: alternate fix for #548 2024-12-08 13:39:21 +01:00
Matthew Coppola cb449bf7ce Increase precision for mouse speed options 2024-12-06 22:40:57 -05:00
Matthew Coppola e2e5bc352d Call text_end (text0f153780) for correctness sake 2024-12-06 17:20:24 -05:00
Matthew Coppola 687b966c5e Allow overriding g_TickRateDiv at runtime 2024-12-06 17:20:24 -05:00
Matthew Coppola 0b8a333e2b Rearrange the menu, clean up, and change some things 2024-12-06 17:20:23 -05:00
Matthew Coppola b34bb01240 Actually sync fullscreen and maximized states with the backend 2024-12-06 17:20:23 -05:00
Matthew Coppola 1e2f6dcb91 Fix mouse input not updating deferred slider while in dimmed mode 2024-12-06 17:20:23 -05:00
Matthew Coppola 210b299bd4 Add Display FPS options to Extended Video Options
Also changed how the window title FPS works, which is now derived from
the difference in time between subsequent video frames.
2024-12-06 17:20:23 -05:00
Matthew Coppola 6de98cfcd4 Update GUI texture filtering setting immediately 2024-12-06 17:20:23 -05:00
Matthew Coppola d43c4c0cba Allow changing MSAA at runtime 2024-12-06 17:20:23 -05:00
Matthew Coppola 1d14877bec Allow changing vsync and framerate limit at runtime
Also implements a new menu item flag: MENUITEMFLAG_SLIDER_DEFERRED,
which only calls the MENUOP_GETSLIDER callback on entering dimmed mode,
storing its value for later ticks, and only calls the MENUOP_SET
callback on leaving dimmed mode. This was necessary to prevent the
framerate limit slider from immediately affecting the framerate, leading
to an annoying slow down as the value was decremented to 0.
2024-12-06 17:20:22 -05:00
Matthew Coppola 5aa1cc6117 Cache ints instead of strings for video modes 2024-12-06 17:20:22 -05:00
Matthew Coppola 1be0e3680b Add video option to center the window 2024-12-06 17:20:22 -05:00
Matthew Coppola 09b0a12b0a Allow changing video resolution at runtime + more
Fullscreen exclusive mode is togglable at runtime, as well, as a
dropdown menu with "borderless" and "exclusive" options. All variables
pertaining to video resolution, exclusive mode, and maximized state are
now synchronized. For instance, Alt+Enter will affect the state of the
fullscreen video option and maximizing the window via the title bar will
update the maximize window option accordingly.
2024-12-06 17:20:15 -05:00
fgsfds 05e462b680 Merge pull request #549 from ZenithMDC/fix-dialog-mousescroll
Forbid mousescroll if dialog is dimmed
2024-12-05 09:40:32 +01:00
Matthew Coppola a2e362caea Forbid mousescroll if dialog is dimmed 2024-12-04 21:23:21 -05:00
fgsfds 49ee5b7efb Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port 2024-12-04 16:28:15 +01:00
fgsfds a1ca69d9ee port: fix issues mentioned in #530 and #532 2024-12-04 16:27:53 +01:00
fgsfds 424d4de9ac Merge pull request #535 from ZenithMDC/fix-duel-momentum
Discard player momentum during autowalk sequences
2024-12-04 11:30:57 +01:00
fgsfds 0e1a7e136a port: fix uninitialized var in aiIfPresetsTargetIsNotMyTarget (fixes #542) 2024-12-04 10:42:48 +01:00
fgsfds 2386494030 port: 64-bit: fix mema end marker (fixes #545) 2024-12-02 13:43:28 +01:00
fgsfds 67675d8980 port: fix #541 2024-11-29 09:46:46 +01:00
fgsfds 9c4aded403 port: osx: restore 10.9 target version 2024-11-24 01:05:18 +01:00
fgsfds 92e1c4aa0b port: osx: temporarily bump target version to 10.13 to test something 2024-11-24 00:31:31 +01:00
fgsfds f53fb8e952 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port 2024-11-24 00:25:42 +01:00
fgsfds 0ad4492ff6 port: default to home directory for saves on OSX as well 2024-11-24 00:25:19 +01:00
fgsfds 33efd36278 readme: add note about save folder 2024-11-23 21:11:38 +01:00
fgsfds 37e69cb83d readme: add osx build instructions 2024-11-23 21:07:21 +01:00
fgsfds 5c5c33c116 readme: small style edit 2024-11-23 20:46:59 +01:00
fgsfds 13a3e0a0ea readme: specify OS versions 2024-11-23 20:46:17 +01:00
fgsfds ccb50c6021 readme: update supported platforms 2024-11-23 20:45:16 +01:00
fgsfds 563e8f9f64 port: osx: set minimum OS version to 11 for arm64 builds 2024-11-23 19:36:38 +01:00
fgsfds df3e0359b9 port: osx: bump OS target to 10.9, since some things in SDL2 won't work with lower 2024-11-23 19:21:25 +01:00
fgsfds 460cc25ef5 port: osx: bump OS target to 10.7, as current SDL2 does not support any lower 2024-11-23 19:13:41 +01:00
fgsfds 596dd7dd40 port: osx: build for MacOS 10.14 2024-11-23 19:05:51 +01:00
fgsfds b2338179d6 port: don't uncrouch in spaces where we don't fit when using extended controls 2024-11-23 12:14:03 +01:00
fgsfds 683d083fab port: don't round crosspos itself, round a copy instead 2024-11-23 09:54:43 +01:00
fgsfds f75a569075 Merge pull request #522 from ZenithMDC/centered-crosshairs
Center-align crosshairs, zoom range, and radar
2024-11-23 09:20:48 +01:00
fgsfds b97eaa9e12 port: simplify night vision check for prop flickering fix 2024-11-22 10:40:20 +01:00
fgsfds 3cadaecf96 Merge pull request #525 from cylonicboom/fix-mp-nvg
Fixes MP NVG flashing bug
2024-11-22 10:28:18 +01:00
fgsfds 4bc1a16d36 build: osx: set RPATH to executable path 2024-11-21 19:31:14 +01:00
fgsfds bc1f1c26db ci: osx: build with CMAKE_MACOSX_RPATH enabled 2024-11-20 13:59:06 +01:00
fgsfds d2d35263a4 port: sanitize controller names
because apparently some of them can't fucking resist putting a funny R or TM in there
2024-11-20 13:00:41 +01:00
fgsfds ba1b6c3232 port: turns out depth_clamp is in core GL since 3.2 2024-11-20 12:51:35 +01:00
fgsfds 3c020cad84 port: detect gl core and GLES3 at runtime; add hacks to make it work properly 2024-11-20 12:07:18 +01:00
fgsfds 140f6f24e8 ci: actually update osx builds to releases 2024-11-19 18:17:16 +01:00
fgsfds c7895d937f tools: fix the python warning about the \h 2024-11-19 18:15:05 +01:00
fgsfds 9f43c906db ci: osx: don't install packages already in runner; enable releases and port-net 2024-11-19 18:08:41 +01:00
fgsfds 31dbb5e7c6 ci: osx: actually install SDL2 2024-11-19 18:02:03 +01:00
fgsfds 7d8e755fc7 ci: forgor to checkout source 2024-11-19 17:58:21 +01:00
fgsfds 103fb0e0e9 ci: what the fuck? 2024-11-19 17:56:48 +01:00
fgsfds b220d73f2c ci: add osx autobuilds 2024-11-19 17:50:10 +01:00
fgsfds efda5a5f44 port: also try GL4.1 core; a little bit of cleanup 2024-11-19 17:37:19 +01:00
fgsfds 41d5630eec Merge pull request #534 from cylonicboom/port-osx
osx build
2024-11-19 17:28:02 +01:00
Catherine Reprobate cea20b6f31 osx build 2024-11-17 10:51:45 -08:00
fgsfds 06dcbcc1b1 port: rename random to rngRandom to avoid conflicts with libc 2024-11-17 11:03:57 +01:00
Matthew Coppola d7a612302e Discard player momentum during autowalk sequences
Prevents potential softlock during The Duel.
2024-11-17 03:56:20 -05:00
fgsfds d747588323 ci: only build the port branch for nswitch 2024-11-16 15:37:43 +01:00
fgsfds 363158a93d port: fix typo 2024-11-16 15:21:49 +01:00
fgsfds 7658a96c1c readme: clarify nswitch installation 2024-11-16 15:20:36 +01:00
fgsfds c332738f7a ci: fix typo 2024-11-16 15:08:51 +01:00
fgsfds 2542b21bfc ci: nswitch: add nswitch builds to releases 2024-11-16 15:07:31 +01:00
fgsfds ef8413ae58 ci: nswitch: put NROs into their subfolders 2024-11-16 15:05:54 +01:00
fgsfds 7969d84257 ci: nswitch: add autobuilds 2024-11-16 15:01:36 +01:00
fgsfds 3d8f63dbb6 port: use a separate fb for fullscreen menu background 2024-11-16 12:31:37 +01:00
fgsfds 08ec8e541b port: remove DUALFLIP from rocket launcher, nbomb, grenade and devastator
makes them look less broken when dual wielded
2024-11-16 12:16:52 +01:00
fgsfds 08afb2d90a readme: fix formatting 2024-11-15 19:13:53 +01:00
fgsfds d7e5ad5bc7 readme: clarify that these are commands 2024-11-15 19:12:09 +01:00
fgsfds 7830ccb88c readme: it's libnx, not switch-libnx 2024-11-15 19:10:59 +01:00
fgsfds 8075307e09 build: nswitch: use actual AND in the author string 2024-11-15 19:10:45 +01:00
Matthew Coppola fb18da239f Move subpixel offset code & fix radar UV map
The subpixel offset code has been moved into the draw_rectangle
function, so it can be applied to more than just the fill_rectangle
function.

The radar texture was displaced along its V component and has
been corrected. It has also been subpixel-adjusted to align with the
player's radar dot.
2024-11-15 03:16:33 -05:00
Matthew Coppola bc82328353 Improve crosshair position accuracy by rounding 2024-11-15 03:16:33 -05:00
Matthew Coppola 938223db28 Center Maian and Skedar tri sights 2024-11-15 03:16:32 -05:00
Matthew Coppola 942c966bf2 Replace centered rects with subpixel offsets 2024-11-15 03:16:32 -05:00
Matthew Coppola e0d59345c7 Center-align crosshairs and zoom range 2024-11-15 03:16:32 -05:00
fgsfds f514e25208 port: fix #219, #506 2024-11-15 01:32:21 +01:00
fgsfds 28fceb67de port: bring back the host_ structs for filemodel.c
this fixes the Pelagic 2 guard thing, but I still need to figure out how to get rid of them without breaking the shit out of everything
2024-11-15 00:42:04 +01:00
fgsfds 130b286d0d port: avoid stack corruption in bmoveProcessInput 2024-11-14 23:00:30 +01:00
fgsfds b88c3a120b port: add scopes to cases in preprocess to prevent older compilers from having a heart attack 2024-11-14 19:20:27 +01:00
fgsfds a6f5077609 port: 64-bit: fix crash site 2024-11-14 18:43:16 +01:00
fgsfds e2b708d442 port: set default opt level to -Og for now (see #529) 2024-11-14 18:38:20 +01:00
fgsfds 2cb29e91c6 port: only run the menu blur filter once 2024-11-13 14:04:36 +01:00
fgsfds 55cc2d8e72 port: nswitch: basic Nintendo Switch port 2024-11-13 12:50:42 +01:00
fgsfds 852349bbe0 mention python in the readme 2024-11-13 09:09:30 +01:00
fgsfds b408d54dfb port: cmake: remove console window on windows 2024-11-13 09:07:17 +01:00
fgsfds 5d9fe034ea tools: fix assetmgr on python <= 3.8 2024-11-13 08:55:04 +01:00
fgsfds 1d7c381ce2 port: cmake: fix stdc++ linking on windows; restore the icon 2024-11-13 08:50:35 +01:00
fgsfds 6c8e5ee4dc update README.md 2024-11-12 23:05:04 +01:00
fgsfds d37d9b7168 ci: move flatpak back to i686 for now 2024-11-12 22:50:36 +01:00
fgsfds fab41b6fcb ci: probably fix i686-linux builds; rename i386 back to i686 2024-11-12 22:34:44 +01:00
fgsfds ee7ce2d988 port: cmake: force disable gnu extensions 2024-11-12 22:19:49 +01:00
fgsfds 1a1accceca ci: update for cmake (i686-linux should be broken) 2024-11-12 22:15:28 +01:00
fgsfds 0bdf79cc51 port: build: move to CMake
god forgive me
2024-11-12 22:08:18 +01:00
fgsfds 91c43385dd update README.md 2024-11-12 14:34:40 +01:00
fgsfds 58e64ebfc9 port: flatpak: launch the x86_64 executable for now 2024-11-12 14:19:12 +01:00
fgsfds 36f9e59304 port: 64-bit: fix jpn builds 2024-11-12 14:05:43 +01:00
fgsfds 420a1b52c1 ci: re-enable CI (2) 2024-11-12 13:58:37 +01:00
fgsfds 345da23ebe ci: re-enable CI 2024-11-12 13:57:11 +01:00
fgsfds 3f887b2ecf port: 64-bit: shrink audio bank allocation after loading 2024-11-12 13:53:52 +01:00
fgsfds d5482f3453 port: build: name executables and build folders according to target platform 2024-11-12 13:53:30 +01:00
fgsfds fdbd1667ad port: build: name executables and build folders according to arch 2024-11-12 13:52:11 +01:00
fgsfds 421ac0af79 port: 64-bit: fix extra fields in modelrodata_type11 2024-11-12 13:18:02 +01:00
fgsfds 163dbf9495 port: 64-bit: get rid of host_ structs; further cleanup 2024-11-12 13:13:42 +01:00
fgsfds 2f221b9a1e port: 64-bit: fix warnings 2024-11-12 10:49:13 +01:00
fgsfds 1448cd597a port: 64-bit: more cleanup
replace the byte swapping macros with the ones from platform.h

rename and move things to match the rest of the code
2024-11-12 10:34:10 +01:00
fgsfds 68e3a79e47 port: 64-bit: replace another long 2024-11-12 10:11:23 +01:00
fgsfds 19ef4738b7 port: 64-bit: fix matrices on x86_64-linux 2024-11-11 20:44:27 +01:00
fgsfds 16f025cbbe port: 64-bit: fix pointer length in mp3.c 2024-11-10 15:25:47 +01:00
fgsfds 25cdfc991b port: 64-bit cleanup: don't use int128 to copy Gfx around 2024-11-10 15:24:26 +01:00
fgsfds 5c2082f58e port: 64-bit cleanup: remove FileType, use LOADTYPE instead 2024-11-10 14:02:04 +01:00
fgsfds 23539a02a5 port: 64-bit cleanup: remove exit()/fprintf() 2024-11-10 10:53:59 +01:00
fgsfds f37abc941e port: 64-bit cleanup: remove dead preprocess code 2024-11-10 10:41:15 +01:00
fgsfds 8468e69b9f Merge pull request #521 from rafccq/port-x64
64-bit port
2024-11-10 10:29:51 +01:00
Catherine Reprobate 8fe95d7d52 Fixes N64 MP NVG flashing bug 2024-11-09 00:10:09 -08:00
Raf 19167b8468 portx64: added back 32-bit targets to CI 2024-10-04 00:13:36 +08:00
Raf d5ee41fe5d Merge branch 'fgs-port' into port-x64
# Conflicts:
#	.github/workflows/c-cpp.yml
2024-10-03 23:58:40 +08:00
fgsfds 2a5c3a351e port: refactor gbcRomCheck a bit 2024-09-02 10:48:54 +02:00
fgsfds 2550b5a668 port: README: add icon credit 2024-09-02 10:27:38 +02:00
fgsfds 24d5679f4a port: add windows program icon 2024-09-02 10:26:38 +02:00
fgsfds a3d2b56dd9 port: flatpak: replace icon with the one suggested by NicNamSam in #238 2024-09-02 10:26:11 +02:00
fgsfds 34d3e082ec Merge pull request #501 from jonaeru/port-mpcopysimulantmenu
Add "Copy Simulant" mp menu
2024-09-02 09:55:04 +02:00
fgsfds a277ca7ee4 Merge pull request #499 from MaikelChan/transfer-pak
Check GameBoy Color ROM to emulate Transfer Pak
2024-09-02 09:54:36 +02:00
fgsfds af8e808e39 Merge pull request #502 from fpiesche/port
Add Flatpak build
2024-09-02 09:51:11 +02:00
Florian Piesche 8f445d344f Add .flatpak-builder to gitignore 2024-08-30 18:46:08 +01:00
Florian Piesche e9b946feb4 Fix executable detection 2024-08-30 18:45:55 +01:00
Florian Piesche 2d51c0a60a Switch to shell script to launch 2024-08-30 18:03:00 +01:00
Jonaeru cf13976db3 Add copy simulant mp menu 2024-08-31 00:46:04 +09:00
Florian Piesche 6344cc8914 Move actual flatpak bundle rather than parent directory 2024-08-30 12:52:14 +01:00
Florian Piesche b2657eb0c2 Use freedesktop 23.08 specifically 2024-08-30 12:29:31 +01:00
Florian Piesche 35d263e15b Use freedesktop container 2024-08-30 12:27:54 +01:00
Florian Piesche c224055ff7 Fix manifest file name. Duh. 2024-08-30 12:25:51 +01:00
Florian Piesche 096a833838 debug 2024-08-30 02:37:56 +01:00
Florian Piesche ee8d7a6e89 Build flatpak bundle manually 2024-08-30 02:30:00 +01:00
Florian Piesche 538385a991 Try workflow again 2024-08-30 02:13:07 +01:00
Florian Piesche b8348a45bc Try and debug workflow setup 2024-08-30 01:58:53 +01:00
Florian Piesche a6b516be15 Fix flatpak build step 2024-08-30 01:47:13 +01:00
Florian Piesche 9ac8af6639 Add comments for missing features in launcher script 2024-08-30 01:42:50 +01:00
Florian Piesche 28bdccd322 Add Flatpak build 2024-08-30 01:29:08 +01:00
MaikelChan 8865130c35 Added some instructions to README. 2024-08-25 21:42:54 +02:00
MaikelChan 153ca3341e Detect Perfect Dark GBC Rom, emulating Transfer Pak functionality. 2024-08-25 21:27:21 +02:00
Raf 8533189561 portx64: include "platform.h" wherever the flag PLATFORM_64bit is used, to avoid possible nasty surprises 2024-08-12 21:20:30 +08:00
Raf eabbdc612c portx64: fixes #5 - crossbow bolt beams not rendering correctly 2024-08-12 21:08:04 +08:00
Raf 5841fb9afa portx64: fixes #4 - jpn/pal versions crashing on startup 2024-08-12 18:56:49 +08:00
Raf 077cc67b79 portx64: fixes #3 - some weapons stuck after switching to 1st function
Tested in 32-bit as well
2024-08-12 16:35:20 +08:00
Raf 589bdf1cd9 portx64: fixes #2 - hoverbike not carrying over to crash-site 2024-08-12 16:33:55 +08:00
Raf 3524ec73b7 portx64: fixes #1 - muzzle flashes broken on some weapons 2024-08-12 16:32:49 +08:00
Raf ab514f39af Update c-cpp.yml
added missing dll: libgcc_s_seh-1.dll
2024-08-10 20:27:29 +08:00
Raf 8be982fdb6 Update c-cpp.yml 2024-08-10 17:31:41 +08:00
Raf ae2543de90 Update c-cpp.yml: fixed arch prefix (x86_64) everywhere 2024-08-10 17:19:56 +08:00
Raf 6a5d249e67 Update c-cpp.yml 2024-08-10 02:21:07 +08:00
Raf 4b44b5b4e3 Update c-cpp.yml 2024-08-10 01:18:49 +08:00
Raf 2fd1c49ef5 Update c-cpp.yml 2024-08-10 01:14:06 +08:00
Raf 22ad5a44db Merge branch 'port-x64' of https://github.com/rafccq/perfect_dark into port-x64 2024-08-09 23:21:57 +08:00
Raf e77b3172ed portx64: a bunch of gcc14 fixes
portx64: fixed pal

Update c-cpp.yml

portx64: fixed linux build

portx64: fixed linux build

ops

portx64: fixed linux build, one more time

portx64: fixed linux build, one more time
2024-08-09 22:37:23 +08:00
Raf a721349cff portx64: fixed linux build, one more time 2024-08-09 21:55:39 +08:00
Raf 40cc42a941 portx64: fixed linux build, one more time 2024-08-09 21:49:10 +08:00
Raf cec92dbcb6 portx64: fixed linux build
ops
2024-08-09 05:07:09 +08:00
Raf 2c4d3e7768 portx64: fixed linux build 2024-08-09 05:02:27 +08:00
Raf e09aebebe7 Update c-cpp.yml 2024-08-09 04:45:12 +08:00
Raf a5d9f02184 portx64: fixed pal 2024-08-09 04:22:57 +08:00
Raf d2dd109a05 portx64: a bunch of gcc14 fixes 2024-08-09 03:57:01 +08:00
Raf 01cbcd99cb portx64: fixed a bunch of instances of Wincompatible-pointer-types + filesetup.c: use ALIGN macro 2024-08-09 02:31:10 +08:00
Raf a9e82658fd portx64: a couple things breaking the build in github - actual fix, plus renamed more functions in filebg.c 2024-08-09 01:21:28 +08:00
Raf 5bee1b0cce portx64: a couple things breaking the build in github 2024-08-09 00:50:21 +08:00
Raf a11abc0511 portx64: forgot to commit the removal of pdextract files 2024-08-09 00:47:55 +08:00
Raf c36b6b286d Update c-cpp.yml 2024-08-09 00:36:42 +08:00
Raf 18fe7fd797 Update c-cpp.yml 2024-08-09 00:23:03 +08:00
Raf d6d4bc2c14 Update c-cpp.yml 2024-08-08 23:55:26 +08:00
Raf c519997b33 portx64: moved pdextract code to src/preprocess, renamed files and function names to follow the port standard 2024-08-08 22:00:08 +08:00
Raf 4d60c93beb portx64: romdata: proper estimated size for setup files, renamed getEstimatedFileSize function 2024-08-08 20:54:59 +08:00
Raf b44dbb16b5 Merge remote-tracking branch 'fgs/port' into port-x64 2024-08-08 17:17:20 +08:00
Raf 8b1e81f32a portx64: pd-extract,preprocess: renamed "_x64" functions, removed now unused preprocess functions, increased snd heap size (x86) 2024-08-08 17:15:33 +08:00
Raf 9e34f80a2c portx64: pd-extract audio: check for repeated pointers before converting 2024-08-08 04:13:08 +08:00
Raf c1c71ea21d portx64: pd-extract models: tons of fixes: data alignments, stargunfire, preprocess textures 2024-08-08 04:01:11 +08:00
fgsfds bdbf0ab789 Merge pull request #484 from MaikelChan/three_point_2
Three point mode and shader fixes
2024-08-06 16:46:35 +02:00
fgsfds ca76416e1c Merge pull request #487 from MaikelChan/mp-viewports
Fixed viewport calculations for models in menus, and other menu fixes
2024-08-06 16:46:19 +02:00
fgsfds b534a42685 Merge pull request #488 from MaikelChan/training-saving
Save data after successfully completing training mission
2024-08-06 16:44:15 +02:00
MaikelChan 6b71e622c7 Save data after successfully completing a mission in device / holo training. 2024-08-06 15:35:26 +02:00
MaikelChan 48c294fc24 Recalculate model position in character profile menu every tick, so it adjusts when resizing the window. 2024-08-06 14:21:36 +02:00
MaikelChan f0fe7f41f1 Forgot to remove something from previous commit. 2024-08-06 14:13:17 +02:00
MaikelChan 2844930a21 Recalculate model position in device training menu every tick, so it adjusts when resizing the window. 2024-08-06 14:10:43 +02:00
MaikelChan d36c55d048 - Fixed model position in device training menu. 2024-08-06 14:04:02 +02:00
MaikelChan f855dc32f1 Apply a small offset to the arrows in character selection so they don't get cut off by the scissor. 2024-08-06 13:17:43 +02:00
MaikelChan 08e2b49e88 Fixed viewport calculations of the character selection UIs from multiplayer. 2024-08-06 12:43:45 +02:00
MaikelChan 9cd978a7a9 Removed more APPLE checks. 2024-08-05 19:11:33 +02:00
MaikelChan a60880ef80 Three point and shader improvements
- Fixed blurry menu background being unfiltered when three point is enabled.
- Some shader code refactor to reduce the amount of __APPLE__ defines: use the SAMPLE_TEX macro to sample textures.
- Detach shaders before deleting them.
2024-08-05 17:09:00 +02:00
MaikelChan a4b5b110ec Don't perform a filter mode change if the new mode is the same as the previous one. 2024-08-05 16:33:55 +02:00
fgsfds 897020b3fd port: clean up depth_zfar remnants 2024-08-05 11:42:21 +02:00
fgsfds e85fdb3b9b port: exclude threepoint-related shader code when it's not enabled 2024-08-05 11:41:45 +02:00
fgsfds e3e72617a1 Merge pull request #483 from MaikelChan/three_point
Improvements to three point filtering
2024-08-05 10:38:15 +02:00
fgsfds bc365650ce Merge pull request #482 from MaikelChan/depth_clear
Implemented depth clear, and disabled some depth range functionality
2024-08-05 10:33:15 +02:00
MaikelChan 6fa78556f4 Implemented texture filtering setting with a dropdown showing all three options, and three point can be changed in real time. 2024-08-05 04:15:30 +02:00
MaikelChan 5fdeff6a82 Disabled depth range functionality. Doesn't seem needed anymore. 2024-08-04 22:10:46 +02:00
Raf 3573906eef portx64: pd-extract setup: fixed doorscale obj 2024-08-04 22:30:49 +08:00
Raf e36df05a4f portx64: pd-extract: renamed fin_marker 2024-08-04 22:29:13 +08:00
MaikelChan 673ba52cbd Not necessary to change depth range of bullet casings anymore. 2024-08-04 13:21:40 +02:00
MaikelChan 0ea8872471 Perform a depth only clear right before rendering the gun. 2024-08-04 13:14:03 +02:00
Raf 40273bdba1 portx64: romdata: check for PLATFORM_64BIT inside romdataGetEstimatedFileSize() 2024-08-04 18:37:01 +08:00
Raf e8006f3446 portx64: pd-extract util gbi: fixed gdl conversion so it works on x86
it works but is still a bit messy, may rewrite it later
2024-08-04 18:34:04 +08:00
Raf 373f08ca3e portx64: pd-extract setups: a few bug fixes and changed how lists are copied
- moved ptrmarkers out of ext_file_bg to common
- function to get ailist length
2024-08-04 18:26:09 +08:00
Raf 844d6c7ec8 portx64: pd-extract setups: a few bug fixes and changed how lists are copied 2024-08-04 18:19:41 +08:00
fgsfds b43c2ec617 Merge pull request #448 from blaiz/cloaking-respawn
Give Cloaking Device at respawn if cheat is active
2024-08-04 10:56:30 +02:00
fgsfds a8c68aed97 Merge pull request #476 from jonaeru/port-mpnoradar-player
Add "No Player on Radar" mp option
2024-08-04 10:56:02 +02:00
fgsfds 4c09de6de0 Merge pull request #480 from MaikelChan/depth_compare_fixes
Depth compare improvements based on GlideN64
2024-08-04 10:55:20 +02:00
MaikelChan 29d6392514 Forgot some extra checks. 2024-08-04 06:11:50 +02:00
MaikelChan b9f6961931 Depth compare improvements based on GlideN64. 2024-08-04 05:28:10 +02:00
Raf 949faf09d9 portx64: undo disable sound 2024-08-02 17:49:44 +08:00
Raf 5beef0916b portx64: warn if memory pool is full 2024-08-02 17:47:35 +08:00
Raf 89397bd566 portx64: makefile: added PLATFORM_64BIT define 2024-08-02 17:46:50 +08:00
Raf 288a007202 portx64: bug fix: mp3 code accessing out of bounds memory: increased alloc/audio heap size 2024-08-02 17:43:05 +08:00
Raf 50b912db98 portx64: bug fix: weatherResetRooms accessing invalid memory when returning to STAGE_TITLE 2024-08-02 17:37:33 +08:00
Raf 71dc521baa portx64: menu bug fix: code intermingling handlerdata_dropdown and handlerdata_list values 2024-08-02 17:36:49 +08:00
Raf 06a45738cc portx64: preprocess header left behind 2024-08-02 17:33:53 +08:00
Raf 5795634b9c portx64: files/romdata: getEstimatedFileSize() so we can preallocate enough memory for files in x64 2024-08-02 17:32:33 +08:00
Raf cec197e841 Merge branch 'port-x64' of https://github.com/rafccq/perfect_dark into port-x64 2024-08-02 17:26:20 +08:00
Raf 58c31075b0 portx64: pd-extract: replaced stdint types with ultratypes 2024-08-02 17:26:00 +08:00
Raf 167a4a5d81 portx64: pd-extract: replaced stdint types with ultratypes 2024-08-02 16:48:35 +08:00
Raf 06c01208d3 portx64: integrate pd-extract functions with romdata 2024-08-02 16:43:21 +08:00
Raf 86649345cd portx64: undo this nonsense 2024-07-30 17:56:40 +08:00
Raf 2e2dbfb578 portx64: pd-extract: setups
jesus didn't help in this off-by-one error hell
2024-07-30 17:56:15 +08:00
Raf 10a3992a62 portx64: pd-extract: bg (extract roomgfxdata) and some model fixes 2024-07-30 17:34:06 +08:00
Raf ef4b60d384 portx64: audio system changes 2024-07-30 16:57:17 +08:00
Raf 32faea2b95 portx64: gbi changes 2024-07-30 16:47:12 +08:00
Raf 8a94af6a1c portx64: and more s32 -> uintptr_t 2024-07-30 16:46:02 +08:00
Raf 315a5642da portx64: pd extract - font/anim/audio segments and tiles/pads files fixes 2024-07-23 01:58:47 +08:00
Raf 00c990eded portx64: lots of adjustments in memory allocations/data sizes/offsets etc 2024-07-23 01:52:35 +08:00
Jonaeru b6b7133e76 port: add no radar on player mp option 2024-07-22 22:44:00 +09:00
Raf b0e6e8f24f portx64: lots more u32 -> uintptr_t 2024-07-11 19:43:01 +08:00
Raf 4dbbcbeb58 portx64: changed pointers stored in u32 to uintptr_t
- adjusted hardcoded mask/hardcoded offsets used in memory operations (modelasm_c.c)
- makefile: enabled x64 support and added lib dependency
- title: increase alloc size
- tex: adjustment to calculations involving GDL sizes
2024-07-06 01:16:39 +08:00
Raf 8c8109e8cd Merge branch 'fgs-port' into port-x64 2024-06-02 20:48:29 +08:00
fgsfds b523b1e076 port: fix mouse controls in combat sim keyboard 2024-05-31 11:23:48 +02:00
fgsfds 07e6fdc1e0 port: add mouse lock mode option 2024-05-31 10:54:33 +02:00
Raf 3242105ef8 portx64: added pd-extract source 2024-05-26 16:10:24 +08:00
Raf 7c6508af28 Merge branch 'fgs-port' into port-x64
# Conflicts:
#	Makefile.port
2024-05-26 15:57:03 +08:00
Jonathan G. d7c4843eea Make "All Guns in Solo" cheat work in multiplayer 2024-05-24 17:27:52 -07:00
Jonathan G. 55ab679a81 port: give Cloaking Device at respawn if cheat is active 2024-05-19 23:51:40 -07:00
fgsfds de3b8ff548 port: revert multithreaded audio experiments
until I can figure out how to fix all the funny concurrency issues that cropped up
2024-05-19 19:44:34 +02:00
fgsfds dce96a4a3d port: add separate extra buttons for accept/cancel 2024-05-18 19:32:34 +02:00
fgsfds 08b4d780b7 port: temporary fix for the UI back button 2024-05-18 19:18:27 +02:00
fgsfds bc5911bfba port: formatting 2024-05-18 19:05:47 +02:00
fgsfds ada20c526a port: clean up previous commit 2024-05-18 19:00:40 +02:00
fgsfds 4c552a42f2 port: experimental multithreaded audio 2024-05-18 18:53:12 +02:00
fgsfds e8e513fecb port: possible fix for #401 2024-05-15 14:11:24 +02:00
fgsfds 4601a9c318 port: only respect friendly fire setting in team games 2024-05-15 13:39:12 +02:00
fgsfds 5c7d4ecf52 port: give correct ammo to bots when spawning armed; give at least one round when spawning armed 2024-05-15 12:29:39 +02:00
fgsfds 9edfd667b7 port: give start with weapon a better short name 2024-05-15 12:13:35 +02:00
fgsfds f3757e75e9 port: don't crash when spawn with weapon is on and that weapon is a shield 2024-05-15 12:10:17 +02:00
fgsfds a6e7d503e6 port: add mouse controls to sliders 2024-05-14 23:16:36 +02:00
fgsfds da8b9be09d port: completely disable back on WPNBACK if using mouse navigation 2024-05-14 22:59:20 +02:00
fgsfds 9530924c21 port: add mouse navigation toggle to options 2024-05-14 22:56:47 +02:00
fgsfds 2ba192d411 port: make menu mouse flag global 2024-05-14 22:53:02 +02:00
fgsfds bf8192ee84 Update README.md 2024-05-14 22:21:14 +02:00
fgsfds 45ec35172d ci: fix executable names on linux 2024-05-14 22:04:27 +02:00
fgsfds 926e4dce28 ci: autobuild pal and jpn and include them in release 2024-05-14 21:59:44 +02:00
fgsfds 548e2c1f0b port: only navigate with mouse if it's enabled in the dialog 2024-05-14 21:06:16 +02:00
fgsfds 85872d7e71 port: add mouse controls to virtual keyboard 2024-05-14 20:58:51 +02:00
fgsfds a83e0aa407 port: add mouse control to menus; mouse now unlocks when you pause 2024-05-14 20:28:59 +02:00
fgsfds 865ca682dc Update README.md 2024-05-14 11:58:04 +02:00
fgsfds dc9d0f3c9c ci: give write permission to release job 2024-05-14 11:50:07 +02:00
fgsfds 12d06001e7 Merge pull request #320 from djdv/port
Add CI action to publish development builds to GitHub releases
2024-05-14 11:42:17 +02:00
Raf 63c456a233 port-64: first changes, able to build 2024-01-27 18:25:55 +08:00
Dominic Della Valle 2ef2427419 ci: publish builds to a release tag ci-dev-build
This reserves the tag `ci-dev-build` for use by the CI.
2023-12-23 12:33:17 -05:00
Dominic Della Valle 5fcf1083d2 ci: update GitHub actions uses deps to latest 2023-12-23 12:33:17 -05:00
222 changed files with 14405 additions and 7423 deletions

No files matched your search

+32
View File
@@ -0,0 +1,32 @@
# EditorConfig is awesome: https://EditorConfig.org
# Top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Matches all C source files
[*.c]
indent_style = tab
tab_width = 2
charset = utf-8
trim_trailing_whitespace = true
# Matches all header files
[*.h]
indent_style = tab
tab_width = 2
charset = utf-8
trim_trailing_whitespace = true
# Matches Makefiles
[Makefile]
indent_style = tab
# Matches Markdown files
[*.md]
max_line_length = off
trim_trailing_whitespace = false
+268 -13
View File
@@ -25,44 +25,299 @@ jobs:
mingw-w64-i686-toolchain
mingw-w64-i686-SDL2
mingw-w64-i686-zlib
mingw-w64-i686-cmake
- name: Checkout repository
uses: actions/checkout@v3
- name: Build pd.exe
run: make -f Makefile.port -j
uses: actions/checkout@v4
- name: Build pd.i686.exe
run: cmake -G"Unix Makefiles" -Bbuild . && cmake --build build -j
- name: Build pd.pal.i686.exe
run: cmake -G"Unix Makefiles" -Bbuild_pal -DROMID=pal-final . && cmake --build build_pal -j
- name: Build pd.jpn.i686.exe
run: cmake -G"Unix Makefiles" -Bbuild_jpn -DROMID=jpn-final . && cmake --build build_jpn -j
- name: Prepare artifact for packaging
run: |
mkdir -p bin/data
cp build/ntsc-final-port/pd.exe bin/
cp build/pd.i686.exe bin/
cp build_pal/pd.pal.i686.exe bin/
cp build_jpn/pd.jpn.i686.exe bin/
cp /mingw32/bin/{SDL2.dll,zlib1.dll,libgcc_s_dw2-1.dll,libwinpthread-1.dll} bin/
touch bin/data/put_your_rom_here.txt
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: pd-i686-windows
path: bin/
retention-days: 0
build-i686-linux:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Install dependencies
run: |
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install git gcc g++ gcc-multilib g++-multilib make libsdl2-dev zlib1g-dev libsdl2-dev:i386 zlib1g-dev:i386
sudo apt-get install git gcc g++ gcc-multilib g++-multilib make libsdl2-dev zlib1g-dev libsdl2-dev:i386 zlib1g-dev:i386 cmake
- name: Checkout repository
uses: actions/checkout@v3
- name: Build pd.exe
run: make -f Makefile.port TARGET_PLATFORM=i686-linux -j2
uses: actions/checkout@v4
- name: Build pd.i686
run: cmake -G"Unix Makefiles" -Bbuild -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 . && cmake --build build -j
- name: Build pd.pal.i686
run: cmake -G"Unix Makefiles" -Bbuild_pal -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 -DROMID=pal-final . && cmake --build build_pal -j
- name: Build pd.jpn.i686
run: cmake -G"Unix Makefiles" -Bbuild_jpn -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 -DROMID=jpn-final . && cmake --build build_jpn -j
- name: Prepare artifact for packaging
run: |
mkdir -p bin/data
cp build/ntsc-final-port/pd.exe bin/pd
cp build/pd.i686 bin/
cp build_pal/pd.pal.i686 bin/
cp build_jpn/pd.jpn.i686 bin/
touch bin/data/put_your_rom_here.txt
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: pd-i686-linux
path: bin/
retention-days: 0
build-x86_64-windows:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
steps:
- name: Install MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: >-
git
make
mingw-w64-x86_64-toolchain
mingw-w64-x86_64-python
mingw-w64-x86_64-SDL2
mingw-w64-x86_64-zlib
mingw-w64-x86_64-cmake
- name: Checkout repository
uses: actions/checkout@v4
- name: Build pd.x86_64.exe
run: cmake -G"Unix Makefiles" -Bbuild . && cmake --build build -j
- name: Build pd.pal.x86_64.exe
run: cmake -G"Unix Makefiles" -Bbuild_pal -DROMID=pal-final . && cmake --build build_pal -j
- name: Build pd.jpn.x86_64.exe
run: cmake -G"Unix Makefiles" -Bbuild_jpn -DROMID=jpn-final . && cmake --build build_jpn -j
- name: Prepare artifact for packaging
run: |
mkdir -p bin/data
cp build/pd.x86_64.exe bin/
cp build_pal/pd.pal.x86_64.exe bin/
cp build_jpn/pd.jpn.x86_64.exe bin/
cp /mingw64/bin/{SDL2.dll,zlib1.dll,libwinpthread-1.dll,libgcc_s_seh-1.dll} bin/
touch bin/data/put_your_rom_here.txt
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: pd-x86_64-windows
path: bin/
retention-days: 0
build-x86_64-linux:
runs-on: ubuntu-latest
steps:
- name: Install dependencies
run: |
sudo dpkg --add-architecture amd64
sudo apt-get update
sudo apt-get install git gcc g++ gcc-multilib g++-multilib make libsdl2-dev zlib1g-dev libsdl2-2.0-0 cmake
- name: Checkout repository
uses: actions/checkout@v4
- name: Build pd.x86_64
run: cmake -G"Unix Makefiles" -Bbuild . && cmake --build build -j
- name: Build pd.pal.x86_64
run: cmake -G"Unix Makefiles" -Bbuild_pal -DROMID=pal-final . && cmake --build build_pal -j
- name: Build pd.jpn.x86_64
run: cmake -G"Unix Makefiles" -Bbuild_jpn -DROMID=jpn-final . && cmake --build build_jpn -j
- name: Prepare artifact for packaging
run: |
mkdir -p bin/data
cp build/pd.x86_64 bin/
cp build_pal/pd.pal.x86_64 bin/
cp build_jpn/pd.jpn.x86_64 bin/
touch bin/data/put_your_rom_here.txt
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: pd-x86_64-linux
path: bin/
retention-days: 0
build-x86_64-osx:
runs-on: macos-14
steps:
- name: Install dependencies
run: |
brew install zlib
wget http://libsdl.org/release/SDL2-2.30.9.dmg -O SDL2.dmg
hdiutil mount SDL2.dmg
sudo cp -vr /Volumes/SDL2/SDL2.framework /Library/Frameworks
- name: Checkout repository
uses: actions/checkout@v4
- name: Build pd.x86_64
run: |
cmake -G"Unix Makefiles" -Bbuild -DCMAKE_OSX_ARCHITECTURES=x86_64 .
cmake --build build --target pd -j4 --clean-first
- name: Build pd.pal.x86_64
run: |
cmake -G"Unix Makefiles" -Bbuild_pal -DCMAKE_OSX_ARCHITECTURES=x86_64 -DROMID=pal-final .
cmake --build build_pal --target pd -j4 --clean-first
- name: Build pd.jpn.x86_64
run: |
cmake -G"Unix Makefiles" -Bbuild_jpn -DCMAKE_OSX_ARCHITECTURES=x86_64 -DROMID=jpn-final .
cmake --build build_jpn --target pd -j4 --clean-first
- name: Prepare artifact for packaging
run: |
mkdir -p bin/data
cp build/pd.x86_64 bin/
cp build_pal/pd.pal.x86_64 bin/
cp build_jpn/pd.jpn.x86_64 bin/
cp -vr /Library/Frameworks/SDL2.framework bin/
touch bin/data/put_your_rom_here.txt
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: pd-x86_64-osx
path: bin/
retention-days: 0
build-arm64-osx:
runs-on: macos-14
steps:
- name: Install dependencies
run: |
brew install zlib
wget http://libsdl.org/release/SDL2-2.30.9.dmg -O SDL2.dmg
hdiutil mount SDL2.dmg
sudo cp -vr /Volumes/SDL2/SDL2.framework /Library/Frameworks
- name: Checkout repository
uses: actions/checkout@v4
- name: Build pd.arm64
run: |
cmake -G"Unix Makefiles" -Bbuild -DCMAKE_OSX_ARCHITECTURES=arm64 .
cmake --build build --target pd -j4 --clean-first
- name: Build pd.pal.arm64
run: |
cmake -G"Unix Makefiles" -Bbuild_pal -DCMAKE_OSX_ARCHITECTURES=arm64 -DROMID=pal-final .
cmake --build build_pal --target pd -j4 --clean-first
- name: Build pd.jpn.arm64
run: |
cmake -G"Unix Makefiles" -Bbuild_jpn -DCMAKE_OSX_ARCHITECTURES=arm64 -DROMID=jpn-final .
cmake --build build_jpn --target pd -j4 --clean-first
- name: Prepare artifact for packaging
run: |
mkdir -p bin/data
cp build/pd.arm64 bin/
cp build_pal/pd.pal.arm64 bin/
cp build_jpn/pd.jpn.arm64 bin/
cp -vr /Library/Frameworks/SDL2.framework bin/
touch bin/data/put_your_rom_here.txt
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: pd-arm64-osx
path: bin/
retention-days: 0
build-arm64-nswitch:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/port'
steps:
- name: Install host dependencies
run: |
sudo apt-get update
sudo apt-get install git make cmake curl
- name: Install devkitA64 docker image
run: sudo docker pull devkitpro/devkita64:latest
- name: Checkout repository
uses: actions/checkout@v4
- name: Build pd.arm64.nro
run: sudo docker run --name pd --rm -v `pwd`:`pwd` -w `pwd` devkitpro/devkita64:latest bash ./tools/buildscripts/nswitch_docker.sh build
- name: Build pd.pal.arm64.nro
run: sudo docker run --name pd --rm -v `pwd`:`pwd` -w `pwd` devkitpro/devkita64:latest bash ./tools/buildscripts/nswitch_docker.sh build_pal -DROMID=pal-final
- name: Build pd.jpn.arm64.nro
run: sudo docker run --name pd --rm -v `pwd`:`pwd` -w `pwd` devkitpro/devkita64:latest bash ./tools/buildscripts/nswitch_docker.sh build_jpn -DROMID=jpn-final
- name: Prepare artifact for packaging
run: |
mkdir -p bin/perfectdark/data
mkdir -p bin/perfectdark_pal/data
mkdir -p bin/perfectdark_jpn/data
cp build/pd.arm64.nro bin/perfectdark/
cp build_pal/pd.pal.arm64.nro bin/perfectdark_pal/
cp build_jpn/pd.jpn.arm64.nro bin/perfectdark_jpn/
touch bin/perfectdark/data/put_your_rom_here.txt
touch bin/perfectdark_pal/data/put_your_rom_here.txt
touch bin/perfectdark_jpn/data/put_your_rom_here.txt
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: pd-arm64-nswitch
path: bin/
retention-days: 0
build-flatpak-bundle:
name: "Build flatpak bundle"
runs-on: ubuntu-latest
needs: [build-x86_64-linux]
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:freedesktop-25.08
options: --privileged
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: pd-x86_64-linux
path: dist/linux/bin/
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6
with:
bundle: io.github.perfect_dark_pc_port.perfect_dark.flatpak
manifest-path: dist/linux/io.github.perfect_dark_pc_port.perfect_dark.yaml
cache-key: flatpak-builder-${{ github.sha }}
upload-artifact: false
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: io.github.perfect_dark_pc_port.perfect_dark.flatpak
path: io.github.perfect_dark_pc_port.perfect_dark.flatpak
retention-days: 0
publish-latest-build:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/port'
needs: [build-i686-windows, build-i686-linux, build-x86_64-windows, build-x86_64-linux, build-arm64-nswitch, build-x86_64-osx, build-arm64-osx, build-flatpak-bundle]
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
path: ci-artifacts
- name: Publish latest dev-build
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
mkdir ci-release
pushd ci-artifacts
tar czf ../ci-release/pd-i686-linux.tar.gz pd-i686-linux
tar czf ../ci-release/pd-x86_64-linux.tar.gz pd-x86_64-linux
tar cJf ../ci-release/pd-x86_64-osx.tar.xz pd-x86_64-osx
tar cJf ../ci-release/pd-arm64-osx.tar.xz pd-arm64-osx
zip -r ../ci-release/pd-i686-windows.zip pd-i686-windows
zip -r ../ci-release/pd-x86_64-windows.zip pd-x86_64-windows
zip -r ../ci-release/pd-arm64-nswitch.zip pd-arm64-nswitch
mv io.github.perfect_dark_pc_port.perfect_dark.flatpak/io.github.perfect_dark_pc_port.perfect_dark.flatpak ../ci-release/
popd
git tag --force ci-dev-build port
git push --force origin ci-dev-build
gh release upload --clobber ci-dev-build ci-release/*
+4
View File
@@ -4,6 +4,7 @@
*.exe
pd.*.z64
build
.flatpak-builder
extracted
src/assets/*/*.bin
src/assets/*/*.ctl
@@ -22,3 +23,6 @@ src/assets/*/textures/*.bin
src/generated
tools/mkrom/mkrom
/.vs
CppProperties.json
.idea
cmake-build-debug
+14
View File
@@ -0,0 +1,14 @@
{
"clang-format.enable": false,
"C_Cpp.clang_format_style": "none",
"[c]": {
"editor.formatOnSave": false,
"editor.formatOnPaste": false,
"editor.formatOnType": false
},
"[cpp]": {
"editor.formatOnSave": false,
"editor.formatOnPaste": false,
"editor.formatOnType": false
}
}
+360
View File
@@ -0,0 +1,360 @@
cmake_minimum_required(VERSION 3.16)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
if(APPLE)
if(CMAKE_OSX_ARCHITECTURES MATCHES "arm64")
# ARM Macs start at OS 11.
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Minimum OS X deployment version")
else()
# SDL2 requires at least this version for everything to work properly.
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version")
endif()
endif()
project(pd C CXX)
include(TargetArch)
include(FindPkgConfig)
include(AssetUtils)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# On first build set the build type to RelWithDebInfo if it's not already set
if (NOT EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE)
endif()
endif()
# Options
set(ROMID "ntsc-final" CACHE STRING "Which ROM to build an executable for: ntsc-final, pal-final or jpn-final")
option(FORCE_CROSSCOMPILE "Force cross compiling" NO)
# Determine target arch
target_architecture(TARGET_ARCH)
if(TARGET_ARCH STREQUAL "i386")
# for historical reasons
set(TARGET_ARCH "i686")
endif()
# TODO
set(TARGET_IS_BIG_ENDIAN FALSE)
if((TARGET_ARCH MATCHES "unknown") OR (TARGET_ARCH STREQUAL ""))
message(FATAL_ERROR "Unknown target arch")
elseif(TARGET_ARCH MATCHES "64")
set(TARGET_IS_64BIT TRUE)
else()
set(TARGET_IS_64BIT FALSE)
endif()
message(STATUS "Target arch: ${TARGET_ARCH}")
# Determine target OS and platform identifier ($arch-$os)
if(WIN32)
# Windows
set(TARGET_OS "windows")
elseif(APPLE)
# OSX
set(TARGET_OS "osx")
elseif(NINTENDO_SWITCH)
# Switch
set(TARGET_OS "nswitch")
elseif(UNIX)
# Generic *nix; assume Linux
set(TARGET_OS "linux")
else()
# ???
message(FATAL_ERROR "Unknown target OS or compiler")
endif()
set(TARGET_PLATFORM "${TARGET_ARCH}-${TARGET_OS}")
message(STATUS "Target platform: ${TARGET_PLATFORM}")
# Calculate version info and binary name
set(VERSION_IS_PAL 0)
if(ROMID STREQUAL "ntsc-final")
set(VERSION 2)
set(BIN_REGION "")
elseif(ROMID STREQUAL "pal-final")
set(VERSION 4)
set(BIN_REGION ".pal")
set(VERSION_IS_PAL 1)
elseif(ROMID STREQUAL "jpn-final")
set(VERSION 5)
set(BIN_REGION ".jpn")
else()
message(FATAL_ERROR "Unknown ROM ID: ${ROMID}")
endif()
# git commit hash
execute_process(
COMMAND git rev-parse --short HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE VERSION_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# git branch name
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE VERSION_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(VERSION_TARGET "${TARGET_PLATFORM}")
set(VERSION_ARCH "${TARGET_ARCH}")
set(VERSION_ROMID "${ROMID}")
set(VERSION_BUILD "${CMAKE_BUILD_TYPE}")
if((VERSION_BRANCH STREQUAL "") OR (VERSION_BRANCH STREQUAL "HEAD"))
set(VERSION_BRANCH "port-custom")
endif()
message(STATUS "Version: ${VERSION_ROMID}, hash ${VERSION_HASH}, branch ${VERSION_BRANCH}")
configure_file("${CMAKE_SOURCE_DIR}/port/include/versioninfo.h.in" "${CMAKE_BINARY_DIR}/port/include/versioninfo.h" @ONLY)
set(ASSET_DIR "src/assets/${ROMID}")
set(GENERATED_DIR "src/generated/${ROMID}")
set(ENV{ROMID} ${ROMID})
# Build folder postfix
set(BUILD_ID "${VERSION_ROMID}-${VERSION_TARGET}")
# Compiler defs
add_definitions(
-DMATCHING=0
-DPIRACYCHECKS=0
-DROM_SIZE=32
-DAVOID_UB=1
-D_LANGUAGE_C=1
-DPAL=${VERSION_IS_PAL}
-DVERSION=${VERSION}
)
if(TARGET_IS_64BIT)
add_definitions(-DPLATFORM_64BIT=1)
endif()
# Compiler flags
# Include directories
include_directories("${CMAKE_SOURCE_DIR}/include")
include_directories("${CMAKE_SOURCE_DIR}/include/PR")
include_directories("${CMAKE_SOURCE_DIR}/src/include")
include_directories("${CMAKE_BINARY_DIR}/src/generated/${ROMID}")
include_directories("${CMAKE_SOURCE_DIR}/src/lib/ultra/audio")
include_directories("${CMAKE_SOURCE_DIR}/port/include")
include_directories("${CMAKE_BINARY_DIR}/port/include")
# Set Release optimization to -Og until I fix the -O2 issues
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug"))
add_compile_options(-Og)
endif()
# Common CFLAGS
add_compile_options(
-fno-inline-functions
-fno-strict-aliasing
-funsigned-char
-fwrapv
-include "versioninfo.h"
)
# Common warning flags
add_compile_options(
-Wall
-Wno-address
-Wno-int-in-bool-context
-Wno-misleading-indentation
-Wno-missing-braces
-Wno-multichar
-Wno-tautological-compare
-Wno-unused-but-set-variable
-Wno-unused-value
-Wno-unused-variable
-fdiagnostics-color=always
)
# C specific flags
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wno-pointer-sign>)
# C++ specific flags
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-Wno-unused-function>)
# Platform-specific flags
if (APPLE)
# Make it look for libs in the executable folder manually since CMake's rpath system is wack
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rpath @executable_path")
else()
# This warning is not recognized by XCode/Clang for some reason.
add_compile_options(-Wno-format-truncation)
endif()
# Dependencies
set(LIBS )
# SDL2
find_package(SDL2 REQUIRED)
if(NINTENDO_SWITCH)
if(NOT SDL2_LIBRARY OR NOT SDL2_INCLUDE_DIR)
# sometimes FindSDL2 just wants us to suffer and does not set these
set(SDL2_LIBRARY "SDL2")
set(SDL2_INCLUDE_DIR "${DEVKITPRO}/portlibs/switch/include/SDL2")
endif()
endif()
include_directories(SYSTEM "${SDL2_INCLUDE_DIR}")
list(APPEND LIBS "${SDL2_LIBRARY}")
# ZLib
find_package(ZLIB REQUIRED)
if(ZLIB_INCLUDE_DIR)
include_directories(SYSTEM "${ZLIB_INCLUDE_DIR}")
endif()
list(APPEND LIBS "${ZLIB_LIBRARY}")
# GL
if(NOT GL_LIBRARY)
if(WIN32)
set(GL_LIBRARY opengl32)
elseif(NINTENDO_SWITCH)
set(GL_LIBRARY EGL glapi drm_nouveau)
elseif(APPLE)
set(GL_LIBRARY "-framework OpenGL")
else()
set(GL_LIBRARY GL)
endif()
endif()
list(APPEND LIBS "${GL_LIBRARY}")
# Platform-specific extra libs
if(NOT EXTRA_LIBRARIES)
if(WIN32)
set(EXTRA_LIBRARIES dbghelp -static-libstdc++)
elseif(NINTENDO_SWITCH)
set(EXTRA_LIBRARIES stdc++ pthread)
else()
set(EXTRA_LIBRARIES stdc++ m dl)
endif()
endif()
list(APPEND LIBS "${EXTRA_LIBRARIES}")
# Sources
file(GLOB_RECURSE SRC_PORT "${CMAKE_SOURCE_DIR}/port/*.c")
file(GLOB_RECURSE SRC_PORT_CXX "${CMAKE_SOURCE_DIR}/port/*.cpp")
file(GLOB_RECURSE SRC_GAME "${CMAKE_SOURCE_DIR}/src/game/*.c")
file(GLOB SRC_LIB_MP3 "${CMAKE_SOURCE_DIR}/src/lib/mp3/*.c")
file(GLOB SRC_LIB_NAUDIO "${CMAKE_SOURCE_DIR}/src/lib/naudio/*.c")
file(GLOB SRC_LIB_ULTRA_AUDIO "${CMAKE_SOURCE_DIR}/src/lib/ultra/audio/*.c")
file(GLOB SRC_LIB_GU "${CMAKE_SOURCE_DIR}/src/lib/ultra/gu/*.c")
set(SRC_LIB
src/lib/ultra/io/vimodentsclan1.c
src/lib/ultra/io/vimodepallan1.c
src/lib/ultra/io/vimodempallan1.c
src/lib/ultra/io/vitbl.c
src/lib/ailist.c
src/lib/anim.c
src/lib/args.c
src/lib/audiodma.c
src/lib/audiomgr.c
src/lib/base.c
src/lib/collision.c
src/lib/debughud.c
src/lib/dma.c
src/lib/fault.c
src/lib/joy.c
src/lib/lib_2f490_c.c
src/lib/lib_2fc60.c
src/lib/lib_3e3e0.c
src/lib/lib_04f60nb.c
src/lib/lib_17ce0.c
src/lib/lib_034d0.c
src/lib/lib_39c80.c
src/lib/lib_15850.c
src/lib/mema.c
src/lib/memp.c
src/lib/model.c
src/lib/modelasm_c.c
src/lib/mp3.c
src/lib/mtx_c.c
src/lib/mtx.c
src/lib/music.c
src/lib/path.c
src/lib/profile.c
src/lib/rdp.c
src/lib/rmon.c
src/lib/rng_c.c
src/lib/rzip_c.c
src/lib/snd.c
src/lib/speaker.c
src/lib/varsinit.c
src/lib/vi.c
src/textureconfig.c
)
list(PREPEND SRC_LIB "${CMAKE_SOURCE_DIR}")
set(SRC
${SRC_GAME}
${SRC_PORT}
${SRC_PORT_CXX}
${SRC_LIB_MP3}
${SRC_LIB_NAUDIO}
${SRC_LIB_ULTRA_AUDIO}
${SRC_LIB_GU}
${SRC_LIB}
)
if(WIN32)
list(APPEND SRC "${CMAKE_SOURCE_DIR}/dist/windows/icon.rc")
endif()
# Asset files
generate_asset_headers("lang/" "${CMAKE_SOURCE_DIR}/tools/assetmgr/mklang" "en" JSON_HEADERS)
generate_asset_headers("pads/" "${CMAKE_SOURCE_DIR}/tools/assetmgr/mkpads" "" JSON_HEADERS)
generate_asset_headers("tiles/" "${CMAKE_SOURCE_DIR}/tools/assetmgr/mktiles" "" JSON_HEADERS)
generate_asset_headers("animations.json" "${CMAKE_SOURCE_DIR}/tools/assetmgr/mkanims" "" JSON_HEADERS)
generate_asset_headers("sequences.json" "${CMAKE_SOURCE_DIR}/tools/assetmgr/mksequences" "" JSON_HEADERS)
generate_asset_headers("textures.json" "${CMAKE_SOURCE_DIR}/tools/assetmgr/mktextures" "" JSON_HEADERS)
add_custom_target(pd_headers ALL DEPENDS ${JSON_HEADERS})
# Game target
set(BIN_NAME "pd${BIN_REGION}.${TARGET_ARCH}")
add_executable(pd ${SRC})
add_dependencies(pd pd_headers)
target_link_libraries(pd ${LIBS})
set_target_properties(pd PROPERTIES OUTPUT_NAME "${BIN_NAME}")
if(WIN32)
set_target_properties(pd PROPERTIES WIN32_EXECUTABLE TRUE)
endif()
# Additional commands for specific platforms.
if(NINTENDO_SWITCH)
add_custom_command(TARGET pd POST_BUILD
COMMAND nacptool --create "Perfect Dark" "fgsfds and contributors" "${VERSION_ROMID}/${VERSION_BRANCH}/${VERSION_HASH}" "${BIN_NAME}.nacp"
COMMAND aarch64-none-elf-strip -o ${CMAKE_BINARY_DIR}/${BIN_NAME}.stripped.elf ${CMAKE_BINARY_DIR}/${BIN_NAME}.elf
COMMAND elf2nro ${CMAKE_BINARY_DIR}/${BIN_NAME}.stripped.elf ${CMAKE_BINARY_DIR}/${BIN_NAME}.nro --icon=${CMAKE_SOURCE_DIR}/dist/nswitch/icon.jpg --nacp=${BIN_NAME}.nacp
)
endif()
-812
View File
@@ -1,812 +0,0 @@
################################################################################
# Options
# ROMID - The ROM version to build.
#
# Can be set in your environment using
# $ export ROMID=...
#
# Supported values:
# * ntsc-beta
# * ntsc-1.0
# * ntsc-final
# * pal-beta
# * pal-final
# * jpn-final
ROMID ?= ntsc-final
# MATCHING - Whether to build a matching ROM (1) or a custom one (0).
#
# Build a matching ROM to prove that the decompilation is accurate.
#
# If enabled, all further options are ignored and are set automatically.
MATCHING = 1
# COMPILER - Choose which compiler to use.
#
# A matching build uses ido. For non-matching builds, use gcc for performance.
#
# gcc is currently only supported when ROMID is ntsc-1.0 or ntsc-final.
#
# Supported values: ido, gcc
COMPILER = gcc
# GCC_OPT_LVL - the optimisation level if building with gcc.
#
# Supported values: -O0, -O1, -O2, -Os
GCC_OPT_LVL = -Os
# PAL - Whether to use the PAL television standard (1) or NTSC (0).
#
# PAL runs at 50Hz while NTSC is 60Hz, and PAL uses different screen dimensions.
PAL = 0
# ROMALLOCATION
#
# The lib, data and game segments are compressed in the final ROM.
#
# These options define how much space is allocated for the compressed segments.
#
# If any value is not big enough, the build system will tell you which one needs
# to be changed and what to change it to.
ROMALLOCATION_DATA = 0x015000
ROMALLOCATION_LIB = 0x038800
ROMALLOCATION_GAME = 0x144ee0
# ROM_SIZE - The desired ROM size in megabytes.
#
# All versions of the retail ROM are 32MB.
#
# If this is too low you might get this error from ld:
# "final link failed: memory exhausted"
ROM_SIZE := 32
# DEBUG - Enable (1) or disable (0) the debug menu and crash screen.
#
# When enabled, press C-up and C-down simultaneously to toggle the debug menu.
# Note that some emulators have problems displaying the crash screen text.
DEBUG = 0
################################################################################
# The VERSION constant is used in the source to handle version-specific code.
ifeq ($(ROMID), ntsc-beta)
VERSION = 0
endif
ifeq ($(ROMID), ntsc-1.0)
VERSION = 1
endif
ifeq ($(ROMID), ntsc-final)
VERSION = 2
endif
ifeq ($(ROMID), pal-beta)
VERSION = 3
endif
ifeq ($(ROMID), pal-final)
VERSION = 4
endif
ifeq ($(ROMID), jpn-final)
VERSION = 5
endif
# Set runtime piracy checks off. We turn this on for matching builds if needed.
PIRACYCHECKS = 0
# A magic value that's only used to produce a matching ROM.
# It's required because old-school zlib was influenced by uninitialised data.
# ZIPMAGIC is the value of the uninitialised data. We set it per version for
# matching builds, otherwise 0 is fine.
ZIPMAGIC = 0x0000
# This is also a value that's only used to produce a matching ROM.
# The final ROM has some duplicate bytes, and there doesn't seem to be any logic
# for determining how many bytes are duplicated.
COPYLEN = 2
# If a matching build has been requested, override directives as needed.
ifeq ($(MATCHING), 1)
COMPILER = ido
ROMALLOCATION_DATA = 0x015000
ROMALLOCATION_LIB = 0x038800
ROM_SIZE = 32
DEBUG = 0
ifeq ($(ROMID), ntsc-beta)
PAL = 0
PIRACYCHECKS = 0
ROMALLOCATION_DATA = 0x012000
ROMALLOCATION_LIB = 0x02f800
ROMALLOCATION_GAME = 0x105000
DEBUG = 1
endif
ifeq ($(ROMID), ntsc-1.0)
PAL = 0
PIRACYCHECKS = 1
ROMALLOCATION_GAME = 0x144ee0
ZIPMAGIC = 0xffff
endif
ifeq ($(ROMID), ntsc-final)
PAL = 0
PIRACYCHECKS = 1
ROMALLOCATION_GAME = 0x144ee0
ZIPMAGIC = 0xffff
endif
ifeq ($(ROMID), pal-beta)
PAL = 1
PIRACYCHECKS = 1
ROMALLOCATION_GAME = 0x1306f0
ZIPMAGIC = 0x0c00
COPYLEN = 6
DEBUG = 1
endif
ifeq ($(ROMID), pal-final)
PAL = 1
PIRACYCHECKS = 1
ROMALLOCATION_GAME = 0x1306f0
ZIPMAGIC = 0xaf00
endif
ifeq ($(ROMID), jpn-final)
PAL = 0
PIRACYCHECKS = 1
ROMALLOCATION_GAME = 0x1296f0
ZIPMAGIC = 0x0002
COPYLEN = 4
endif
endif
DEFINES := \
VERSION=$(VERSION) \
MATCHING=$(MATCHING) \
PAL=$(PAL) \
PIRACYCHECKS=$(PIRACYCHECKS) \
ROM_SIZE=$(ROM_SIZE) \
PLATFORM_N64=1
ifeq ($(DEBUG),1)
DEFINES := $(DEFINES) DEBUG=1
endif
C_DEFINES := $(foreach d,$(DEFINES),-D$(d))
AS_DEFINES := $(foreach d,$(DEFINES),--defsym $(d)) --defsym _LANGUAGE_ASSEMBLY=1
A_DIR := src/assets/$(ROMID)
B_DIR := build/$(ROMID)
E_DIR := extracted/$(ROMID)
ifneq ($(strip $(MIPS_BINUTILS_PREFIX)),)
TOOLCHAIN := $(MIPS_BINUTILS_PREFIX)
else ifeq ($(shell type mips-elf-ld >/dev/null 2>/dev/null; echo $$?), 0)
TOOLCHAIN := mips-elf
else ifeq ($(shell type mips-linux-gnu-ld >/dev/null 2>/dev/null; echo $$?), 0)
TOOLCHAIN := mips-linux-gnu
else ifeq ($(shell type mips64-elf-ld >/dev/null 2>/dev/null; echo $$?), 0)
TOOLCHAIN := mips64-elf
else ifeq ($(shell type mips64-linux-gnu-ld >/dev/null 2>/dev/null; echo $$?), 0)
TOOLCHAIN := mips64-linux-gnu
else
$(error You need to install a suitable MIPS binutils toolchain (eg. mips-elf-ld))
endif
# Asset files are files which are included in the "files" segment of the ROM.
# This excludes animations, fonts, SFX, MIDI and textures.
# And because setup files are part of the files segment they are included here,
# despite them being written in C.
#
# Create names such as $(B_DIR)/assets/files/PfooZ.
# These names (with .o added) will be dependenices for ld.
ASSET_FILES := \
$(patsubst $(A_DIR)/files/audio/%.mp3, $(B_DIR)/assets/files/A%M, $(shell find $(A_DIR) -path '*/files/audio/*.mp3')) \
$(patsubst $(A_DIR)/files/chrs/%.bin, $(B_DIR)/assets/files/C%Z, $(shell find $(A_DIR) -path '*/files/chrs/*.bin')) \
$(patsubst $(A_DIR)/files/guns/%.bin, $(B_DIR)/assets/files/G%Z, $(shell find $(A_DIR) -path '*/files/guns/*.bin')) \
$(patsubst $(A_DIR)/files/props/%.bin, $(B_DIR)/assets/files/P%Z, $(shell find $(A_DIR) -path '*/files/props/*.bin')) \
$(patsubst src/setups/%.c, $(B_DIR)/assets/files/U%Z, $(shell find src/setups -name '*.c')) \
$(patsubst $(A_DIR)/files/bgdata/%.seg, $(B_DIR)/assets/files/bgdata/%.seg, $(shell find $(A_DIR) -path '*/files/bgdata/*.seg')) \
$(B_DIR)/assets/files/ob/ob_mid.seg.o
LANG_JSON_FILES := $(shell find $(A_DIR) -path '*/lang/*.json')
PADS_JSON_FILES := $(shell find $(A_DIR) -path '*/pads/*.json')
TILES_JSON_FILES := $(shell find $(A_DIR) -path '*/tiles/*.json')
LANG_O_FILES := \
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%E.o, $(LANG_JSON_FILES)) \
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%J.o, $(LANG_JSON_FILES)) \
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%P.o, $(LANG_JSON_FILES)) \
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%_str_f.o, $(LANG_JSON_FILES)) \
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%_str_g.o, $(LANG_JSON_FILES)) \
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%_str_i.o, $(LANG_JSON_FILES)) \
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%_str_s.o, $(LANG_JSON_FILES))
PADS_O_FILES := $(patsubst $(A_DIR)/pads/%.json, $(B_DIR)/assets/files/bgdata/bg_%_padsZ.o, $(PADS_JSON_FILES))
TILES_O_FILES := $(patsubst $(A_DIR)/tiles/%.json, $(B_DIR)/assets/files/bgdata/bg_%_tilesZ.o, $(TILES_JSON_FILES))
C_FILES := $(shell find src/lib src/game src/inflate -name '*.c')
S_FILES := $(shell find src/lib src/game src/preamble -name '*.s')
C_O_FILES := $(patsubst src/%.c, $(B_DIR)/%.o, $(C_FILES))
S_O_FILES := $(patsubst src/%.s, $(B_DIR)/%.o, $(S_FILES))
O_FILES := \
$(C_O_FILES) \
$(S_O_FILES) \
$(patsubst %, %.o, $(ASSET_FILES)) \
$(LANG_O_FILES) \
$(PADS_O_FILES) \
$(TILES_O_FILES) \
$(B_DIR)/assets/animations.o \
$(B_DIR)/assets/copyrightZ.o \
$(B_DIR)/assets/files/list.o \
$(B_DIR)/assets/fonts/bankgothic.o \
$(B_DIR)/assets/fonts/handelgothiclg.o \
$(B_DIR)/assets/fonts/handelgothicmd.o \
$(B_DIR)/assets/fonts/handelgothicsm.o \
$(B_DIR)/assets/fonts/handelgothicxs.o \
$(B_DIR)/assets/fonts/numeric.o \
$(B_DIR)/assets/fonts/ocralg.o \
$(B_DIR)/assets/fonts/ocramd.o \
$(B_DIR)/assets/fonts/tahoma.o \
$(B_DIR)/assets/fonts/zurich.o \
$(B_DIR)/assets/mpstrings/mpstringsE.o \
$(B_DIR)/assets/mpstrings/mpstringsF.o \
$(B_DIR)/assets/mpstrings/mpstringsG.o \
$(B_DIR)/assets/mpstrings/mpstringsI.o \
$(B_DIR)/assets/mpstrings/mpstringsJ.o \
$(B_DIR)/assets/mpstrings/mpstringsP.o \
$(B_DIR)/assets/mpstrings/mpstringsS.o \
$(B_DIR)/assets/seq.ctl.o \
$(B_DIR)/assets/seq.tbl.o \
$(B_DIR)/assets/sequences.o \
$(B_DIR)/assets/sfx.ctl.o \
$(B_DIR)/assets/sfx.tbl.o \
$(B_DIR)/assets/textureslist.o \
$(B_DIR)/bootloader.o \
$(B_DIR)/firingrange.o \
$(B_DIR)/getitle.o \
$(B_DIR)/mpconfigs.o \
$(B_DIR)/romheader.o \
$(B_DIR)/rsp/asp.data.o \
$(B_DIR)/rsp/asp.text.o \
$(B_DIR)/rsp/gsp.data.o \
$(B_DIR)/rsp/gsp.text.o \
$(B_DIR)/rsp/rspboot.text.o \
$(B_DIR)/textureconfig.o
# ntsc-beta doesn't have this segment
ifneq ($(ROMID), ntsc-beta)
O_FILES := $(O_FILES) $(B_DIR)/assets/accessingpakZ.o
endif
ifeq ($(ROMID), jpn-final)
O_FILES := $(O_FILES) $(B_DIR)/assets/fonts/jpn.o
else
O_FILES := $(O_FILES) \
$(B_DIR)/assets/fonts/jpnsingle.o \
$(B_DIR)/assets/fonts/jpnmulti.o
endif
INCLUDES = \
-I include \
-I include/PR \
-I src/include \
-I src/include/lib/libc \
-I src/generated/$(ROMID) \
-I src/lib/ultra/audio \
AS := $(TOOLCHAIN)-as
ASFLAGS = -march=vr4300 -mabi=32 $(INCLUDES) $(AS_DEFINES)
ifeq ($(COMPILER), ido)
RECOMP_FILES := \
build/recomp/5.3/as1 \
build/recomp/5.3/cc \
build/recomp/5.3/cfe \
build/recomp/5.3/err.english.cc \
build/recomp/5.3/ugen \
build/recomp/5.3/ujoin \
build/recomp/5.3/uld \
build/recomp/5.3/umerge \
build/recomp/5.3/uopt \
build/recomp/5.3/usplit \
build/recomp/7.1/as1 \
build/recomp/7.1/cc \
build/recomp/7.1/cfe \
build/recomp/7.1/err.english.cc \
build/recomp/7.1/ugen \
build/recomp/7.1/uopt
LOOPUNROLL_C_FILES := \
src/lib/ultra/gu/frustum.c \
src/lib/ultra/gu/mtxutil.c \
src/lib/ultra/gu/ortho.c \
src/lib/ultra/io/conteepread.c \
src/lib/ultra/io/conteepwrite.c \
src/lib/ultra/io/contpfs.c \
src/lib/ultra/io/contramread.c \
src/lib/ultra/io/contramwrite.c \
src/lib/ultra/io/gbpakgetstatus.c \
src/lib/ultra/io/gbpakreadid.c \
src/lib/ultra/io/motor.c \
src/lib/ultra/io/pfschecker.c \
src/lib/ultra/io/pfsfreeblocks.c \
src/lib/ultra/io/pfsgetstatus.c \
src/lib/ultra/io/pfsinitpak2.c
MIPS3_C_FILES := \
src/lib/rng_c.c \
src/lib/ultra/libc/ll.c \
src/lib/ultra/libc/llcvt.c
G_C_FILES := \
$(shell find src/lib/ultra/audio -name '*.c') \
$(shell find src/lib/naudio -name '*.c') \
$(shell find src/lib/mp3 -name '*.c') \
src/lib/lib_2fc60.c \
src/lib/lib_317f0.c \
src/lib/lib_39c80.c \
src/lib/lib_3e3e0.c \
src/lib/mp3.c \
src/lib/speaker.c
O1_C_FILES := \
src/lib/lib_04f60nb.c \
src/lib/ultra/io/ai.c \
src/lib/ultra/io/aisetnextbuf.c \
src/lib/ultra/io/conteeplongread.c \
src/lib/ultra/io/contquery.c \
src/lib/ultra/io/controller.c \
src/lib/ultra/io/dpctr.c \
src/lib/ultra/io/pigetcmdq.c \
src/lib/ultra/io/pidma.c \
src/lib/ultra/io/si.c \
src/lib/ultra/io/sp.c \
src/lib/ultra/io/spsetpc.c \
src/lib/ultra/io/sptaskyielded.c \
src/lib/ultra/io/vi.c \
src/lib/ultra/io/viblack.c \
src/lib/ultra/io/vigetcurrframebuf.c \
src/lib/ultra/io/vigetnextframebuf.c \
src/lib/ultra/io/visetevent.c \
src/lib/ultra/io/visetmode.c \
src/lib/ultra/io/visetxscale.c \
src/lib/ultra/io/visetyscale.c \
src/lib/ultra/io/viswapbuf.c \
src/lib/ultra/libc/ll.c \
src/lib/ultra/libc/llcvt.c \
src/lib/ultra/os/atomic.c \
src/lib/ultra/os/createmesgqueue.c \
src/lib/ultra/os/destroythread.c \
src/lib/ultra/os/getmemsize.c \
src/lib/ultra/os/gettime.c \
src/lib/ultra/os/initialize2.c \
src/lib/ultra/os/jammesg.c \
src/lib/ultra/os/recvmesg.c \
src/lib/ultra/os/resetglobalintmask.c \
src/lib/ultra/os/sendmesg.c \
src/lib/ultra/os/seteventmesg.c \
src/lib/ultra/os/setglobalintmask.c \
src/lib/ultra/os/setthreadpri.c \
src/lib/ultra/os/settimer.c \
src/lib/ultra/os/startthread.c \
src/lib/ultra/os/stopthread.c \
src/lib/ultra/os/stoptimer.c \
src/lib/ultra/os/thread.c \
src/lib/ultra/os/timerintr.c \
src/lib/ultra/os/virtualtophysical.c \
src/lib/ultra/os/yieldthread.c
ifeq ($(ROMID), ntsc-beta)
O1_C_FILES := $(O1_C_FILES) src/lib/ultra/io/pfsisplug.c
endif
O3_C_FILES := \
src/lib/ultra/gu/align.c \
src/lib/ultra/gu/frustum.c \
src/lib/ultra/gu/ortho.c \
src/lib/ultra/gu/scale.c \
src/lib/ultra/libc/xprintf.c
IDO71_C_FILES := \
$(shell find src/lib/ultra/audio -name '*.c') \
$(shell find src/lib/naudio -name '*.c') \
$(shell find src/lib/mp3 -name '*.c') \
src/lib/lib_2fc60.c \
src/lib/lib_39c80.c
LOOPUNROLL_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(LOOPUNROLL_C_FILES))
MIPS3_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(MIPS3_C_FILES))
G_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(G_C_FILES))
O1_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(O1_C_FILES))
O3_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(O3_C_FILES))
IDO71_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(IDO71_C_FILES))
LOOPUNROLL := -Wo,-loopunroll,0
MIPSISET := -mips2
OPT_LVL := -O2
CC := build/recomp/5.3/cc
$(LOOPUNROLL_O_FILES): LOOPUNROLL :=
$(MIPS3_O_FILES): MIPSISET := -mips3
$(G_O_FILES): OPT_LVL := -g
$(O1_O_FILES): OPT_LVL := -O1
$(O3_O_FILES): OPT_LVL := -O3
$(IDO71_O_FILES): CC := build/recomp/7.1/cc
CFLAGS = $(C_DEFINES) $(INCLUDES) \
$(LOOPUNROLL) \
-Wab,-r4300_mul \
-non_shared \
-Olimit 2000 \
-G 0 \
-Xcpluscomm \
-w2 \
-Wab,-w \
-woff 581,649,819,820,821,838,852 \
$(MIPSISET) -32
# Files containing GLOBAL_ASM must be built with the asm_processor
ifeq ($(MATCHING), 1)
GLOBALASM_C_FILES != grep -rl 'GLOBAL_ASM(' $(C_FILES)
GLOBALASM_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(GLOBALASM_C_FILES))
$(GLOBALASM_O_FILES): CC := /usr/bin/env python3 tools/asm_processor/build.py $(CC) -- $(TOOLCHAIN)-as $(ASFLAGS) --
endif
else ifeq ($(COMPILER), gcc)
CC := $(TOOLCHAIN)-gcc
$(C_O_FILES): OPT_LVL := $(GCC_OPT_LVL)
C_DEFINES += -DAVOID_UB
CFLAGS := $(C_DEFINES) $(INCLUDES) \
-EB \
-march=vr4300 \
-mabi=32 \
-mfix4300 \
-mdivide-breaks \
-mno-abicalls \
-ffreestanding \
-fno-builtin \
-fno-common \
-fno-inline-functions \
-fno-merge-constants \
-fno-strict-aliasing \
-fno-zero-initialized-in-bss \
-funsigned-char \
-fwrapv \
-Wall \
-Werror \
-Wno-address \
-Wno-aggressive-loop-optimizations \
-Wno-array-bounds \
-Wno-int-in-bool-context \
-Wno-int-to-pointer-cast \
-Wno-maybe-uninitialized \
-Wno-misleading-indentation \
-Wno-missing-braces \
-Wno-multichar \
-Wno-pointer-sign \
-Wno-pointer-to-int-cast \
-Wno-tautological-compare \
-Wno-uninitialized \
-Wno-unused-but-set-variable \
-Wno-unused-value \
-Wno-unused-variable \
-G 0
$(B_DIR)/lib/ultra/libc/xldtob.o: CFLAGS += -ffast-math -fno-unsafe-math-optimizations
else
$(error The COMPILER option must be "ido" or "gcc")
endif
# Make ROMID available as an environment variable to all tooling.
# (We use this a lot)
export ROMID
default: rom
################################################################################
# Recomp
# ------------------------------------------------------------------------------
# The ido-static-recomp project is installed as a git submodule at tools/recomp.
# The IRIX binaries are taken from that project and they are recompiled to
# build/recomp/<version>/
tools/recomp/recomp.cpp:
@echo "Please install ido-static-recomp by running:"
@echo
@echo " git submodule update --init --recursive"
@echo
@exit 1
build/recomp/recomp: tools/recomp/recomp.cpp
@mkdir -p build/recomp/5.3
@mkdir -p build/recomp/7.1
g++ tools/recomp/recomp.cpp -o build/recomp/recomp -g -lcapstone
build/recomp/5.3/ugen:
@mkdir -p build/recomp/5.3
g++ tools/recomp/recomp.cpp -o build/recomp/recomp-ugen53 -g -lcapstone -Dugen53
./build/recomp/recomp-ugen53 tools/recomp/ido/5.3/usr/lib/ugen > build/recomp/5.3/ugen.c
gcc tools/recomp/libc_impl.c build/recomp/5.3/ugen.c -Itools/recomp -o build/recomp/5.3/ugen -O2 -fno-strict-aliasing -lm -no-pie -DIDO53
build/recomp/5.3/cc: build/recomp/recomp
./build/recomp/recomp tools/recomp/ido/5.3/usr/bin/cc > build/recomp/5.3/cc.c
gcc tools/recomp/libc_impl.c build/recomp/5.3/cc.c -Itools/recomp -o build/recomp/5.3/cc -O2 -fno-strict-aliasing -lm -no-pie -DIDO53
build/recomp/5.3/%: build/recomp/recomp
./build/recomp/recomp tools/recomp/ido/5.3/usr/lib/$* > build/recomp/5.3/$*.c
gcc tools/recomp/libc_impl.c build/recomp/5.3/$*.c -Itools/recomp -o build/recomp/5.3/$* -O2 -fno-strict-aliasing -lm -no-pie -DIDO53
build/recomp/7.1/cc: build/recomp/recomp
./build/recomp/recomp tools/recomp/ido/7.1/usr/bin/cc > build/recomp/7.1/cc.c
gcc tools/recomp/libc_impl.c build/recomp/7.1/cc.c -Itools/recomp -o build/recomp/7.1/cc -O2 -fno-strict-aliasing -lm -no-pie -DIDO71
build/recomp/7.1/%: build/recomp/recomp
./build/recomp/recomp tools/recomp/ido/7.1/usr/lib/$* > build/recomp/7.1/$*.c
gcc tools/recomp/libc_impl.c build/recomp/7.1/$*.c -Itools/recomp -o build/recomp/7.1/$* -O2 -fno-strict-aliasing -lm -no-pie -DIDO71
build/recomp/%/err.english.cc:
@mkdir -p build/recomp/$?
cp tools/err.english.cc build/recomp/$*
################################################################################
# ROM Finalisation Stages
# Link all objects together with ld to make stage1.elf. In this stage, the game,
# lib and data segments are uncompressed and placed past the end of the ROM.
$(B_DIR)/stage1.elf: $(O_FILES) ld/pd.ld
cpp -DROMID=$(ROMID) -DVERSION=$(VERSION) -DROMALLOCATION_DATA=$(ROMALLOCATION_DATA) -DROMALLOCATION_LIB=$(ROMALLOCATION_LIB) -DROMALLOCATION_GAME=$(ROMALLOCATION_GAME) -DROM_SIZE=$(ROM_SIZE) -P ld/pd.ld -o $(B_DIR)/pd.ld
$(TOOLCHAIN)-ld --no-check-sections -z muldefs -T $(B_DIR)/pd.ld --print-map -o $@ > $(B_DIR)/pd.map
$(B_DIR)/stage1.bin: $(B_DIR)/stage1.elf
$(TOOLCHAIN)-objcopy $< $@ -O binary
# Build the final ROM from stage1.bin using mkrom
# mkrom handles calculating the piracy checksums, zipping segments and
# calculating the ROM checksum.
$(B_DIR)/pd.z64: $(B_DIR)/stage1.bin tools/mkrom/mkrom
tools/mkrom/mkrom $(B_DIR)/stage1.bin $(B_DIR)/pd.map $(PIRACYCHECKS) $(ZIPMAGIC) $(COPYLEN) $@
@echo -e "\033[0;32mROM written to $@\033[0m"
tools/mkrom/mkrom:
$(MAKE) -C tools/mkrom
################################################################################
# Testing Related
# ---------------------
# This works a little backwards, in that the ROM has to be built to at least
# stage 2, then extract-segment is used to slice out the segments.
CHECK_FILES := $(shell awk '{print $$2}' checksums.$(ROMID).md5)
test: $(CHECK_FILES)
@md5sum --quiet -c checksums.$(ROMID).md5
$(B_DIR)/segments/%.bin: $(B_DIR)/pd.z64
@B_DIR=$(B_DIR) tools/extract-segment $*
################################################################################
# Raw data segments
$(B_DIR)/assets/fonts/%.o: $(A_DIR)/fonts/%.bin
mkdir -p $(B_DIR)/assets/fonts
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
$(B_DIR)/getitle.o: $(E_DIR)/getitle.bin
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
$(B_DIR)/assets/seq.ctl.o: $(A_DIR)/seq.ctl
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
$(B_DIR)/assets/seq.tbl.o: $(A_DIR)/seq.tbl
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
$(B_DIR)/assets/sfx.ctl.o: $(A_DIR)/sfx.ctl
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
$(B_DIR)/assets/sfx.tbl.o: $(A_DIR)/sfx.tbl
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
################################################################################
# Asset Manager
ASSETMGR_O_FILES := \
$(B_DIR)/assets/animations.o \
$(LANG_O_FILES) \
$(PADS_O_FILES) \
$(TILES_O_FILES) \
$(B_DIR)/assets/sequences.o \
$(B_DIR)/assets/textureslist.o \
# Anims
$(B_DIR)/assets/animations.o: $(A_DIR)/animations.json
tools/assetmgr/mkanims
# Lang
$(B_DIR)/assets/files/L%E.o: $(A_DIR)/lang/%.json
tools/assetmgr/mklang $< en
$(B_DIR)/assets/files/L%J.o: $(A_DIR)/lang/%.json
tools/assetmgr/mklang $< jp
$(B_DIR)/assets/files/L%P.o: $(A_DIR)/lang/%.json
tools/assetmgr/mklang $< gb
$(B_DIR)/assets/files/L%_str_f.o: $(A_DIR)/lang/%.json
tools/assetmgr/mklang $< fr
$(B_DIR)/assets/files/L%_str_g.o: $(A_DIR)/lang/%.json
tools/assetmgr/mklang $< de
$(B_DIR)/assets/files/L%_str_i.o: $(A_DIR)/lang/%.json
tools/assetmgr/mklang $< it
$(B_DIR)/assets/files/L%_str_s.o: $(A_DIR)/lang/%.json
tools/assetmgr/mklang $< es
# Pads
$(B_DIR)/assets/files/bgdata/bg_%_padsZ.o: $(A_DIR)/pads/%.json
tools/assetmgr/mkpads $<
# Pads - but this is the zipped non-obj, for make test
$(B_DIR)/assets/files/bgdata/bg_%_padsZ: $(A_DIR)/pads/%.json
tools/assetmgr/mkpads $<
# Sequences
$(B_DIR)/assets/sequences.o: $(A_DIR)/sequences.json
tools/assetmgr/mksequences
# Textures
$(B_DIR)/assets/textureslist.o: $(A_DIR)/textures.json
tools/assetmgr/mktextures
# Tiles
$(B_DIR)/assets/files/bgdata/bg_%_tilesZ.o: $(A_DIR)/tiles/%.json
tools/assetmgr/mktiles $<
# Tiles - but this is the zipped non-obj, for make test
$(B_DIR)/assets/files/bgdata/bg_%_tilesZ: $(A_DIR)/tiles/%.json
tools/assetmgr/mktiles $<
################################################################################
# Files
# Audio
$(B_DIR)/assets/files/A%M: $(A_DIR)/files/audio/%.mp3
@mkdir -p $(B_DIR)/assets/files
cp $< $@
# BG segs
$(B_DIR)/assets/files/bgdata/bg_%.seg: $(A_DIR)/files/bgdata/bg_%.seg
@mkdir -p $(B_DIR)/assets/files/bgdata
cp $< $@
# Chrs
$(B_DIR)/assets/files/C%Z: $(A_DIR)/files/chrs/%.bin
@mkdir -p $(B_DIR)/assets/files
tools/rarezip $< > $@
# Guns
$(B_DIR)/assets/files/G%Z: $(A_DIR)/files/guns/%.bin
@mkdir -p $(B_DIR)/assets/files
tools/rarezip $< > $@
# OB seg
$(B_DIR)/assets/files/ob/ob_mid.seg.o: $(B_DIR)/assets/files/ob/ob_mid.seg
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
$(B_DIR)/assets/files/ob/ob_mid.seg:
@mkdir -p $(B_DIR)/assets/files/ob
> $@
# Props
$(B_DIR)/assets/files/P%Z: $(A_DIR)/files/props/%.bin
tools/rarezip $< > $@
# Stage setups
# $(A_DIR)/files/setup/foo.c
# -> B_DIR/assets/files/setup/foo.o (done here)
# -> B_DIR/assets/files/setup/foo.elf (done here)
# -> B_DIR/assets/files/setup/foo.bin (done here)
# -> B_DIR/assets/files/UsetupfooZ (done here)
# -> B_DIR/assets/files/UsetupfooZ.o (done elsewhere)
$(B_DIR)/assets/files/setup/%.o: src/setups/%.c $(ASSETMGR_O_FILES) $(RECOMP_FILES)
@mkdir -p $(dir $@)
$(CC) -c $(CFLAGS) -o $@ $<
$(B_DIR)/assets/files/setup/%.elf: $(B_DIR)/assets/files/setup/%.o
TOOLCHAIN=$(TOOLCHAIN) tools/mksimpleelf $< $@
$(B_DIR)/files/setup/%.bin: $(B_DIR)/assets/files/setup/%.elf
@mkdir -p $(dir $@)
$(TOOLCHAIN)-objcopy $< $@ -O binary
$(B_DIR)/assets/files/U%Z: $(B_DIR)/files/setup/%.bin
tools/rarezip $< > $@
# General target to convert any finalised file into a raw object for ld
$(B_DIR)/assets/files/%.o: $(B_DIR)/assets/files/%
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
$(B_DIR)/assets/files/%.bin: $(B_DIR)/assets/files/%.elf
$(TOOLCHAIN)-objcopy $< $@ -O binary
################################################################################
# Miscellaneous
$(B_DIR)/bootloader.o: $(E_DIR)/bootloader.bin
@mkdir -p $(dir $@)
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
$(B_DIR)/romheader.o: src/romheader/romheader.s
$(TOOLCHAIN)-as --defsym VERSION=$(VERSION) -march=vr4300 -mabi=32 -I src/include -EB -o $@ $<
$(B_DIR)/assets/accessingpakZ: $(A_DIR)/accessingpak.bin
tools/rarezip $< > $@
$(B_DIR)/assets/copyrightZ: $(A_DIR)/copyright.bin
tools/rarezip $< > $@
$(B_DIR)/assets/accessingpakZ.o: $(B_DIR)/assets/accessingpakZ
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
$(B_DIR)/assets/copyrightZ.o: $(B_DIR)/assets/copyrightZ
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
$(B_DIR)/rsp/%.text.bin $(B_DIR)/rsp/%.data.bin: src/rsp/%.s
@mkdir -p $(dir $@)
armips -strequ CODE_FILE $(B_DIR)/rsp/$*.text.bin -strequ DATA_FILE $(B_DIR)/rsp/$*.data.bin $<
$(B_DIR)/rsp/%.o: $(B_DIR)/rsp/%.bin
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
ifeq ($(COMPILER), ido)
$(B_DIR)/lib/rng_c.o: src/lib/rng_c.c $(ASSETMGR_O_FILES) $(RECOMP_FILES)
@mkdir -p $(dir $@)
$(CC) -c $(CFLAGS) $(OPT_LVL) -o $@ $<
tools/patchmips3 $@ || rm $@
$(B_DIR)/lib/ultra/libc/llcvt.o: src/lib/ultra/libc/llcvt.c $(ASSETMGR_O_FILES) $(RECOMP_FILES)
@mkdir -p $(dir $@)
$(CC) -c $(CFLAGS) $(OPT_LVL) -o $@ $<
tools/patchmips3 $@ || rm $@
$(B_DIR)/lib/ultra/libc/ll.o: src/lib/ultra/libc/ll.c $(ASSETMGR_O_FILES) $(RECOMP_FILES)
@mkdir -p $(dir $@)
$(CC) -c $(CFLAGS) $(OPT_LVL) $< -o $@
tools/patchmips3 $@ || rm $@
endif
$(B_DIR)/%.o: src/%.c $(ASSETMGR_O_FILES) $(RECOMP_FILES)
@mkdir -p $(dir $@)
$(CC) -c $(CFLAGS) $(OPT_LVL) -o $@ $<
$(B_DIR)/%.o: src/%.s
@mkdir -p $(dir $@)
cpp -P -Wno-trigraphs -I include -I include/PR -I src/include $(C_DEFINES) -D_LANGUAGE_ASSEMBLY -D_MIPSEB $< | $(AS) $(ASFLAGS) -o $@
$(B_DIR)/assets/%.o: $(A_DIR)/%.c $(RECOMP_FILES)
@mkdir -p $(dir $@)
$(CC) -c $(CFLAGS) -o $@ $<
extract:
ROMID=$(ROMID) tools/extract
rom: $(B_DIR)/pd.z64
clean:
rm -rf build/$(ROMID) src/generated/$(ROMID)
allclean:
rm -rf build/* src/generated
codeclean:
find $(B_DIR)/game $(B_DIR)/inflate $(B_DIR)/lib -name '*.o' -delete
-336
View File
@@ -1,336 +0,0 @@
# Options.
# HOST_PLATFORM - Which platform we're building on.
#
# Determined automatically if not specified on command line.
#
# Supported values:
# * i686-windows
# * i686-linux
HOST_PLATFORM ?=
# TARGET_PLATFORM - Which platform to build for.
#
# Determined from HOST_PLATFORM if not specified on command line.
#
# Supported values:
# * i686-windows
# * i686-linux
TARGET_PLATFORM ?=
# ROMID - The ROM version to use.
#
# Can be set in your environment using
# $ export ROMID=...
#
# Supported values:
# * ntsc-final
# * pal-final
# * jpn-final
ROMID ?= ntsc-final
# GCC_OPT_LVL - the optimisation level if building with gcc.
#
# Supported values: -O0, -O1, -O2, -O3, -Os, -Og
GCC_OPT_LVL = -Og
# ROM_SIZE - The desired ROM size in megabytes.
#
# All versions of the retail ROM are 32MB.
#
# If this is too low you might get this error from ld:
# "final link failed: memory exhausted"
ROM_SIZE := 32
# DEBUG - Enable (1) or disable (0) the debug menu and crash screen.
#
# When enabled, press C-up and C-down simultaneously to toggle the debug menu.
# Note that some emulators have problems displaying the crash screen text.
DEBUG = 0
################################################################################
# Detect host platform if not specified.
ifeq ($(HOST_PLATFORM),)
ifeq ($(OS),Windows_NT)
# assume msys for now
UNAME_OS := $(shell uname -s)
ifneq (,$(findstring MINGW64,$(UNAME_OS)))
HOST_PLATFORM := x86_64-windows
else
HOST_PLATFORM := i686-windows
endif
else # TODO
UNAME_ARCH := $(shell uname -m)
UNAME_OS := $(shell uname -s)
UNAME_OS := $(shell echo $(UNAME_OS) | tr A-Z a-z)
HOST_PLATFORM := $(UNAME_ARCH)-$(UNAME_OS)
endif
endif
# Set target platform to host platform if not specified.
ifeq ($(TARGET_PLATFORM),)
TARGET_PLATFORM := $(HOST_PLATFORM)
endif
ifeq (,$(findstring clean,$(MAKECMDGOALS)))
$(info Host platform: $(HOST_PLATFORM))
$(info Target platform: $(TARGET_PLATFORM))
endif
# Set whether the target arch is 64- or 32-bit.
ifneq (,$(findstring 64,$(TARGET_PLATFORM))$(findstring armv8,$(TARGET_PLATFORM)))
# TODO: we're not 64-bit compatible yet, error out if building the actual game
ifeq (,$(findstring clean,$(MAKECMDGOALS)))
$(error 64-bit target platforms are not supported yet)
endif
TARGET_64BIT = 1
else # TODO
TARGET_64BIT = 0
endif
# Set whether the target is big-endian or little-endian.
TARGET_BIG_ENDIAN = 0 # TODO
# The VERSION constant is used in the source to handle version-specific code.
ifeq ($(ROMID),ntsc-final)
BIN_NAME = pd.exe
VERSION = 2
IS_PAL = 0
else ifeq ($(ROMID),pal-final)
BIN_NAME = pd.pal.exe
VERSION = 4
IS_PAL = 1
else ifeq ($(ROMID),jpn-final)
BIN_NAME = pd.jpn.exe
VERSION = 5
IS_PAL = 0
else
$(error ROM version $(VERSION) is not supported)
endif
VERSION_HASH := $(shell git rev-parse --short HEAD)
VERSION_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
VERSION_TARGET := $(TARGET_PLATFORM)
VERSION_ROMID := $(ROMID)
ifeq ($(VERSION_BRANCH),)
VERSION_BRANCH := port-custom
endif
ifeq ($(VERSION_BRANCH),HEAD)
VERSION_BRANCH := port-custom
endif
DEFINES := \
VERSION=$(VERSION) \
VERSION_HASH=\"$(VERSION_HASH)\" \
VERSION_TARGET=\"$(VERSION_TARGET)\" \
VERSION_ROMID=\"$(VERSION_ROMID)\" \
VERSION_BRANCH=\"$(VERSION_BRANCH)\" \
MATCHING=0 \
PAL=$(IS_PAL) \
PIRACYCHECKS=0 \
ROM_SIZE=$(ROM_SIZE) \
_LANGUAGE_C=1
ifeq ($(DEBUG),1)
DEFINES := $(DEFINES) DEBUG=1
endif
C_DEFINES := $(foreach d,$(DEFINES),-D$(d))
A_DIR := src/assets/$(ROMID)
B_DIR := build/$(ROMID)-port
G_DIR := src/generated/$(ROMID)
ifneq (,$(findstring windows,$(TARGET_PLATFORM)))
TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I)
TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lz -lopengl32 -ldbghelp
# on windows/mingw we need this to be built with a 32-bit compiler so it finds the correct libs
TOOLCHAIN ?= i686-w64-mingw32-
# on GCC link libstdc++ statically
ifeq (,$(findstring clang,$(CC))$(findstring clang,$(CXX)))
TARGET_LDFLAGS += -static-libstdc++
else
TARGET_LDFLAGS += -lstdc++
endif
else # assume *nix
TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I)
TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lGL -lz -ldl
ifneq (,$(findstring arm,$(TARGET_PLATFORM))$(findstring aarch,$(TARGET_PLATFORM)))
# linux on arm or aarch64
# TODO: detect soft/hardfloat abi
TOOLCHAIN ?= arm-linux-gnueabihf-
endif
endif
# On x86_64 gcc add -m32 to CFLAGS if building a 32-bit executable.
ifneq (,$(findstring x86_64,$(HOST_PLATFORM))$(findstring x86_64,$(TOOLCHAIN)))
ifneq (1,$(TARGET_64BIT))
TARGET_CFLAGS += -m32
endif
endif
# These are still used in the port, but only to generate headers.
JSON_FILES := $(shell find $(A_DIR) -path '*/lang/*.json')
JSON_FILES += $(shell find $(A_DIR) -path '*/pads/*.json')
JSON_FILES += $(shell find $(A_DIR) -path '*/tiles/*.json')
JSON_FILES += $(wildcard $(A_DIR)/*.json)
JSON_HEADERS := $(patsubst $(A_DIR)/%.json, $(G_DIR)/%.h, $(JSON_FILES))
C_FILES := $(shell find src/game port -name '*.c')
C_FILES := $(C_FILES) \
$(wildcard src/lib/mp3/*.c) \
$(wildcard src/lib/naudio/*.c) \
$(wildcard src/lib/ultra/audio/*.c) \
$(wildcard src/lib/ultra/gu/*.c) \
src/lib/ultra/io/vimodentsclan1.c \
src/lib/ultra/io/vimodepallan1.c \
src/lib/ultra/io/vimodempallan1.c \
src/lib/ultra/io/vitbl.c \
$(wildcard src/lib/a*.c) \
src/lib/base.c \
src/lib/collision.c \
src/lib/debughud.c \
src/lib/dma.c \
src/lib/fault.c \
src/lib/joy.c \
$(wildcard src/lib/lib_*.c) \
src/lib/mema.c \
src/lib/memp.c \
src/lib/model.c \
src/lib/modelasm_c.c \
src/lib/mp3.c \
src/lib/mtx_c.c \
src/lib/mtx.c \
src/lib/music.c \
src/lib/path.c \
src/lib/profile.c \
src/lib/rdp.c \
src/lib/rmon.c \
src/lib/rng_c.c \
src/lib/rzip_c.c \
src/lib/snd.c \
src/lib/speaker.c \
src/lib/varsinit.c \
src/lib/vi.c \
src/textureconfig.c
CXX_FILES :=$(shell find port -name '*.cpp')
C_O_FILES := $(patsubst %.c, $(B_DIR)/%.o, $(C_FILES))
CXX_O_FILES := $(patsubst %.cpp, $(B_DIR)/%.o, $(CXX_FILES))
O_FILES := $(C_O_FILES) $(CXX_O_FILES)
INCLUDES = \
-I include \
-I include/PR \
-I src/include \
-I src/generated/$(ROMID) \
-I src/lib/ultra/audio \
-I port/include
TOOLCHAIN ?=
CC ?= $(TOOLCHAIN)gcc
CXX ?= $(TOOLCHAIN)g++
ifneq (,$(CXX_O_FILES))
LD := $(CXX)
else
LD := $(CC)
endif
$(C_O_FILES): OPT_LVL := $(GCC_OPT_LVL)
COMMON_CFLAGS := $(C_DEFINES) -DAVOID_UB=1 $(INCLUDES) $(TARGET_CFLAGS) -g \
-fno-inline-functions \
-fno-strict-aliasing \
-funsigned-char \
-fwrapv \
-Wall \
-Wno-address \
-Wno-int-in-bool-context \
-Wno-misleading-indentation \
-Wno-missing-braces \
-Wno-multichar \
-Wno-tautological-compare \
-Wno-unused-but-set-variable \
-Wno-unused-value \
-Wno-unused-variable \
-Wno-format-truncation
CFLAGS := -std=c11 $(COMMON_CFLAGS) -Wno-pointer-sign
CXXFLAGS := -std=c++20 $(COMMON_CFLAGS) -Wno-unused-function
LDFLAGS := $(TARGET_LDFLAGS)
# Make ROMID available as an environment variable to all tooling.
# (We use this a lot)
export ROMID
BIN := $(B_DIR)/$(BIN_NAME)
default: $(BIN)
################################################################################
# Asset Manager header generation
# Anims
$(G_DIR)/animations.h: $(A_DIR)/animations.json
tools/assetmgr/mkanims --headers-only
# Lang
$(G_DIR)/lang/%.h: $(A_DIR)/lang/%.json
tools/assetmgr/mklang $< en --headers-only
# Pads
$(G_DIR)/pads/%.h: $(A_DIR)/pads/%.json
tools/assetmgr/mkpads $< --headers-only
# Sequences
$(G_DIR)/sequences.h: $(A_DIR)/sequences.json
tools/assetmgr/mksequences --headers-only
# Textures
$(G_DIR)/textures.h: $(A_DIR)/textures.json
tools/assetmgr/mktextures --headers-only
# Tiles
$(G_DIR)/tiles/%.h: $(A_DIR)/tiles/%.json
tools/assetmgr/mktiles $< --headers-only
################################################################################
# Generic compilation rules
$(BIN): $(O_FILES)
$(LD) $(COMMON_CFLAGS) $(OPT_LVL) -o $(BIN) $^ $(LDFLAGS)
ifneq ($(CV2PDB),)
$(CV2PDB) $(BIN)
endif
$(B_DIR)/%.o: %.c $(JSON_HEADERS)
@mkdir -p $(dir $@)
$(CC) -c $(CFLAGS) $(OPT_LVL) -o $@ $<
$(B_DIR)/%.o: %.cpp $(JSON_HEADERS)
@mkdir -p $(dir $@)
$(CXX) -c $(CXXFLAGS) $(OPT_LVL) -o $@ $<
################################################################################
# Clean rules
clean:
rm -rf build/$(ROMID)-port
allclean:
rm -rf build/*
rm -rf src/generated
codeclean:
find $(B_DIR)/ -name '*.o' -delete
+110 -30
View File
@@ -31,18 +31,24 @@ There are minor graphics- and gameplay-related issues, and possibly occasional c
* basic mod support, currently enough to load a few custom levels;
* slightly expanded memory heap size;
* experimental high framerate support (up to 240 FPS):
* set `Game.TickRateDivisor` to `0` in `pd.ini` to activate;
* enable `Uncap Tickrate` in `Extended Video Options` to activate;
* in practice the game will have issues running faster than ~165 FPS, so use VSync or `Video.FramerateLimit` to cap it.
* emulate the Transfer Pak functionality the game has on the Nintendo 64 to unlock some cheats automatically.
Currently only 32-bit platforms are supported, namely x86 Windows and Linux.
Note that 32-bit binaries will still work on 64-bit versions of those platforms,
though you might have to install some additional libraries.
**The following platforms are officially supported and tested:**
* Windows 7+: i686, x86_64
* Linux: i686, x86_64
* MacOS: x86_64 (OS 10.9+), arm64 (OS 11.0+)
* Nintendo Switch: arm64
## Download
Latest [automatic builds](https://github.com/fgsfdsfgs/perfect_dark/actions) for supported platforms:
* [i686-windows](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port/pd-i686-windows.zip)
* [i686-linux](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port/pd-i686-linux.zip)
Latest [automatic builds](https://github.com/fgsfdsfgs/perfect_dark/releases/tag/ci-dev-build) for supported platforms:
* [x86_64-windows](https://github.com/fgsfdsfgs/perfect_dark/releases/download/ci-dev-build/pd-x86_64-windows.zip)
* [i686-windows](https://github.com/fgsfdsfgs/perfect_dark/releases/download/ci-dev-build/pd-i686-windows.zip)
* [x86_64-linux](https://github.com/fgsfdsfgs/perfect_dark/releases/download/ci-dev-build/pd-x86_64-linux.tar.gz)
* [i686-linux](https://github.com/fgsfdsfgs/perfect_dark/releases/download/ci-dev-build/pd-i686-linux.tar.gz)
* [arm64-nswitch](https://github.com/fgsfdsfgs/perfect_dark/releases/download/ci-dev-build/pd-arm64-nswitch.zip)
If you are looking for netplay builds (the `port-net` branch), see [this link](https://github.com/fgsfdsfgs/perfect_dark/blob/port-net/README.md#download).
@@ -50,13 +56,29 @@ If you are looking for netplay builds (the `port-net` branch), see [this link](h
You must already have a Perfect Dark ROM to run the game, as specified above.
1. Create a directory named `data` next to `pd.exe`.
2. Put your Perfect Dark ROM named `pd.ntsc-final.z64` into it.
3. Run `pd.exe`.
This assumes that you're using an x86_64 build. If you aren't, replace `x86_64` below with your arch (e.g. `i686`).
1. Create a directory named `data` next to `pd.x86_64` if it's not there.
2. Put your Perfect Dark NTSC ROM named `pd.ntsc-final.z64` into it.
3. Run the `pd.x86_64` executable.
If you want to use a PAL or JPN ROM instead, put them into the `data` directory and run the appropriate executable:
* PAL: ROM name `pd.pal-final.z64`, executable name `pd.pal.x86_64`.
* JPN: ROM name `pd.jpn-final.z64`, executable name `pd.jpn.x86_64`.
Optionally, you can also put your Perfect Dark for GameBoy Color ROM named `pd.gbc` in the `data` directory if you want to emulate having the Nintendo 64's Transfer Pak and unlock some cheats automatically.
Optionally, you can move the data folder to `~/.local/share/perfectdark` on Linux or `~/Library/Application Support/perfectdark` on MacOS.
Additional information can be found in the [wiki](https://github.com/fgsfdsfgs/perfect_dark/wiki).
A GPU supporting OpenGL 3.0 or above is required to run the port.
A GPU supporting OpenGL 3.0/ES3.0 or above is required to run the port.
### Installing the Nintendo Switch version
The Nintendo Switch build ZIP comes with all 3 regions in different folders: `perfectdark`, `perfectdark_pal` and `perfectdark_jpn`.
Take the folder for the region you want and put it into the `/switch` folder on your SD card, then put your ROM into the `data` folder inside of the folder you extracted as described above.
## Controls
@@ -76,7 +98,7 @@ Controls can be rebound in `pd.ini`. Default control scheme is as follows:
| Aim mode | RMB/Z | LT | R Trigger |
| Use / Cancel | E | N/A | B |
| Use / Accept | N/A | A | A |
| Crouch cycle | N/A | L3 | `0x80000000` (Extra) |
| Crouch cycle | N/A | LS Click | `0x80000000` (Extra) |
| Half-Crouch | Shift | N/A | `0x40000000` (Extra) |
| Full-Crouch | Control | N/A | `0x20000000` (Extra) |
| Reload | R | X | X `(0x40)` |
@@ -92,43 +114,101 @@ Controls can be rebound in `pd.ini`. Default control scheme is as follows:
### Windows
1. Install [MSYS2](https://www.msys2.org).
2. Open the `MINGW32` prompt. (**NOTE:** _not_ the `MSYS` prompt or the `MINGW64` prompt)
2. Open the `MINGW64` prompt if building for x86_64, or the `MINGW32` prompt if building for i686. (**NOTE:** _do not_ use the `MSYS` prompt)
3. Install dependencies:
`pacman -S mingw-w64-i686-toolchain mingw-w64-i686-SDL2 mingw-w64-i686-zlib make git`
`pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-SDL2 mingw-w64-x86_64-zlib mingw-w64-x86_64-cmake mingw-w64-x86_64-python3 mingw-w64-i686-toolchain mingw-w64-i686-SDL2 mingw-w64-i686-zlib mingw-w64-i686-cmake mingw-w64-i686-python3 make git`
4. Get the source code:
`git clone --recursive https://github.com/fgsfdsfgs/perfect_dark.git && cd perfect_dark`
5. Run `make -f Makefile.port`.
* Add ` ROMID=pal-final` or ` ROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.
6. The resulting executable will be at `build/ntsc-final-port/pd.exe`.
7. If you don't know where you downloaded the source to, you can run `explorer .` to open the current directory.
5. Run `cmake -G"Unix Makefiles" -Bbuild .`.
* Add ` -DROMID=pal-final` or ` -DROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.\
6. Run `cmake --build build -j4 -- -O`.
7. The resulting executable will be at `build/pd.x86_64.exe` (or at `build/pd.i686.exe` if building for i686).
8. If you don't know where you downloaded the source to, you can run `explorer .` to open the current directory.
### Linux
1. Ensure you have gcc, g++ (version 10.0+) and 32-bit versions of SDL2 (version 2.0.12+), libGL and ZLib installed on your system.
* On a 64-bit system you also need to have `gcc-multilib` and `g++-multilib` (or your distro's analogues) installed.
1. Ensure you have gcc, g++ (version 10.0+), make, cmake, git, python3 and SDL2 (version 2.0.12+), libGL and ZLib installed on your system.
* If you wish to crosscompile, you will also need to have libraries and compilers for the target platform installed, e.g. `gcc-multilib` and `g++-multilib` for x86_64 -> i686 crosscompilation.
2. Get the source code:
`git clone --recursive https://github.com/fgsfdsfgs/perfect_dark.git && cd perfect_dark`
3. Run the following command:
* On a 64-bit system: ```make -f Makefile.port TARGET_PLATFORM=i686-linux```
* On a 32-bit system: ```make -f Makefile.port```
* Add ` ROMID=pal-final` or ` ROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.
4. The resulting executable will be at `build/ntsc-final-port/pd.exe`.
* ```cmake -G"Unix Makefiles" -Bbuild .```
* Add ` -DROMID=pal-final` or ` -DROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.
* Add ` -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32` at the end of the command if you want to crosscompile from x86_64 to x86.
4. Run `cmake --build build -j4`.
5. The resulting executable will be at `build/pd.<arch>` (for example `build/pd.x86_64`).
Currently only `i686-linux` and `i686-windows` are supported, using `gcc -m32` and `i686-w64-mingw32-gcc` as compilers, respectively.
Alternate compilers can be specified by passing `TOOLCHAIN=i686-whatever-` as a command line argument.
### MacOS
You can build an executable with PAL or JPN ROM support by adding `ROMID=pal-final` or `ROMID=jpn-final` to the `make` command.
You will need to provide a `jpn-final` or `pal-final` ROM to run those, named `pd.jpn-final.z64` or `pd.pal-final.z64`.
1. Set up Homebrew.
2. Install dependencies:
* Execute command: `brew install cmake gcc python3 zlib git`
3. Install SDL2:
* Execute commands:
```
wget http://libsdl.org/release/SDL2-2.30.9.dmg -O SDL2.dmg
hdiutil mount SDL2.dmg
sudo cp -vr /Volumes/SDL2/SDL2.framework /Library/Frameworks
hdiutil detach /Volumes/SDL2
```
* This installs SDL2 system-wide and this is how the automatic builds are done. The game will also look for it in the executable path, so you could
download it locally instead.
4. Get the source code:
`git clone --recursive https://github.com/fgsfdsfgs/perfect_dark.git && cd perfect_dark`
5. Configure:
* Execute command: `cmake -G"Unix Makefiles" -Bbuild -DCMAKE_OSX_ARCHITECTURES=x86_64 .`
* Replace `x86_64` with `arm64` if building for an ARM64 Mac.
* Add ` -DROMID=pal-final` or ` -DROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.
6. Build:
* Execute command: `cmake --build build --target pd -j4 --clean-first`
7. The resulting executable will be at `build/pd.<arch>` (for example `build/pd.x86_64`).
* You might need to execute `chmod +x build/pd.x86-64` before you can run it.
It might be possible to build a 32-bit ARM executable, but this has not been tested.
### Nintendo Switch
1. Set up the [devkitA64 environment](https://devkitpro.org/wiki/Getting_Started).
* On Windows you can do it under MSYS2 or WSL, usually MSYS2 is recommended.
* If using MSYS2, make sure to use the **MSYS2** shell, **not** MINGW32 or MINGW64.
2. Install host dependencies:
* On MSYS2: execute command `pacman -Syuu && pacman -S git make cmake python3`
* On Linux: use your package manager as normal to install the above dependencies.
3. Install Switch toolchain and dependencies:
* Execute commands:
```
dkp-pacman -Syuu
dkp-pacman -S devkitA64 libnx switch-zlib switch-sdl2 switch-cmake dkp-toolchain-vars
```
* If in MSYS2 or `dkp-pacman` doesn't work, replace it with just `pacman`.
4. Get the source code:
`git clone --recursive https://github.com/fgsfdsfgs/perfect_dark.git && cd perfect_dark`
5. Ensure devkitA64 environment variables are set:
* Execute command: `source /opt/devkitpro/switchvars.sh`
* If your `$DEVKITPRO` path is different, substitute that instead or set the variables manually.
6. Configure:
* Execute command: `aarch64-none-elf-cmake -G"Unix Makefiles" -Bbuild .`
* Add ` -DROMID=pal-final` or ` -DROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.
7. Build:
* Execute command: `make -C build -j4`
8. The resulting executable will be at `build/pd.arm64.nro`.
### Notes
Alternate compilers or toolchains can be specified by passing `-DCMAKE_TOOLCHAIN_FILE=whatever` as normal. The port does not build with Visual Studio.
You will need to provide a `jpn-final` or `pal-final` ROM to run executables built for those regions, named `pd.jpn-final.z64` or `pd.pal-final.z64`.
It might be possible to build and run the game on platforms that are not specified in the supported platforms list (e.g. Linux on armv7), but this has not been tested.
## Credits
* the original [decompilation project](https://github.com/n64decomp/perfect_dark) authors;
* Ryan Dwyer for the above, additional help, and `pd-extract`;
* doomhack for the only other publicly available [PD porting effort](https://github.com/doomhack/perfect_dark) I could find;
* [sm64-port](https://github.com/sm64-port/sm64-port) authors for the audio mixer and some other changes;
* [Ship of Harkinian team](https://github.com/Kenix3/libultraship/tree/main/src/graphic/Fast3D), Emill and MaikelChan for the libultraship version of fast3d that this port uses;
* [Ship of Harkinian team](https://github.com/Kenix3/libultraship/tree/main/src/fast), Emill and MaikelChan for the libultraship version of fast3d that this port uses;
* lieff for [minimp3](https://github.com/lieff/minimp3);
* Mouse Injector and 1964GEPD authors for some of the 60FPS- and mouselook-related fixes;
* Raf for the 64-bit port;
* NicNamSam for the icon;
* everyone who has submitted pull requests and issues to this repository and tested the port;
* probably more I'm forgetting.
+27
View File
@@ -0,0 +1,27 @@
# execute a header generator (execcmd) for every json file in jsonpath, collect headers in headerlist
# note that this reads ROMID
macro(generate_asset_headers jsonpath execcmd extraarg headerlist)
set(TMP_JSON "")
if (${jsonpath} MATCHES "\.json")
# is a json file
list(APPEND TMP_JSON "${CMAKE_SOURCE_DIR}/${ASSET_DIR}/${jsonpath}")
else()
# is a directory
file(GLOB TMP_JSON "${CMAKE_SOURCE_DIR}/${ASSET_DIR}/${jsonpath}*.json")
endif()
foreach(JSON ${TMP_JSON})
unset(HEADERNAME)
string(REPLACE ".json" ".h" HEADERNAME ${JSON})
string(REPLACE "${CMAKE_SOURCE_DIR}/${ASSET_DIR}" "${CMAKE_BINARY_DIR}/${GENERATED_DIR}" HEADERNAME ${HEADERNAME})
add_custom_command(
OUTPUT ${HEADERNAME}
DEPENDS ${JSON}
COMMAND ${execcmd} ${JSON} ${extraarg} --headers-only --romid=${ROMID}
)
list(APPEND ${headerlist} "${HEADERNAME}")
endforeach()
unset(TMP_JSON)
endmacro()
+172
View File
@@ -0,0 +1,172 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
# Locate SDL2 library
# This module defines
# SDL2_LIBRARY, the name of the library to link against
# SDL2_FOUND, if false, do not try to link to SDL2
# SDL2_INCLUDE_DIR, where to find SDL.h
#
# This module responds to the the flag:
# SDL2_BUILDING_LIBRARY
# If this is defined, then no SDL2_main will be linked in because
# only applications need main().
# Otherwise, it is assumed you are building an application and this
# module will attempt to locate and set the the proper link flags
# as part of the returned SDL2_LIBRARY variable.
#
# Don't forget to include SDL2main.h and SDL2main.m your project for the
# OS X framework based version. (Other versions link to -lSDL2main which
# this module will try to find on your behalf.) Also for OS X, this
# module will automatically add the -framework Cocoa on your behalf.
#
#
# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration
# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library
# (SDL2.dll, libsdl2.so, SDL2.framework, etc).
# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again.
# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value
# as appropriate. These values are used to generate the final SDL2_LIBRARY
# variable, but when these values are unset, SDL2_LIBRARY does not get created.
#
#
# $SDL2DIR is an environment variable that would
# correspond to the ./configure --prefix=$SDL2DIR
# used in building SDL2.
# l.e.galup 9-20-02
#
# Modified by Eric Wing.
# Added code to assist with automated building by using environmental variables
# and providing a more controlled/consistent search behavior.
# Added new modifications to recognize OS X frameworks and
# additional Unix paths (FreeBSD, etc).
# Also corrected the header search path to follow "proper" SDL2 guidelines.
# Added a search for SDL2main which is needed by some platforms.
# Added a search for threads which is needed by some platforms.
# Added needed compile switches for MinGW.
#
# On OSX, this will prefer the Framework version (if found) over others.
# People will have to manually change the cache values of
# SDL2_LIBRARY to override this selection or set the CMake environment
# CMAKE_INCLUDE_PATH to modify the search paths.
#
# Note that the header path has changed from SDL2/SDL.h to just SDL.h
# This needed to change because "proper" SDL2 convention
# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
# reasons because not all systems place things in SDL2/ (see FreeBSD).
#
# Ported by Johnny Patterson. This is a literal port for SDL2 of the FindSDL.cmake
# module with the minor edit of changing "SDL" to "SDL2" where necessary. This
# was not created for redistribution, and exists temporarily pending official
# SDL2 CMake modules.
FIND_PATH(SDL2_INCLUDE_DIR SDL.h
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES include/SDL2 include
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local/include/SDL2
/usr/include/SDL2
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
/boot/system/develop/headers/SDL2 #Hiaku OS
)
#MESSAGE("SDL2_INCLUDE_DIR is ${SDL2_INCLUDE_DIR}")
FIND_LIBRARY(SDL2_LIBRARY_TEMP
NAMES SDL2
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES lib64 lib
PATHS
/sw
/opt/local
/opt/csw
/opt
/system/lib #Hiaku OS
)
#MESSAGE("SDL2_LIBRARY_TEMP is ${SDL2_LIBRARY_TEMP}")
IF(NOT SDL2_BUILDING_LIBRARY)
IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
# Non-OS X framework versions expect you to also dynamically link to
# SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms
# seem to provide SDL2main for compatibility even though they don't
# necessarily need it.
FIND_LIBRARY(SDL2MAIN_LIBRARY
NAMES SDL2main
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES lib64 lib
PATHS
/sw
/opt/local
/opt/csw
/opt
)
ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
ENDIF(NOT SDL2_BUILDING_LIBRARY)
# SDL2 may require threads on your system.
# The Apple build may not need an explicit flag because one of the
# frameworks may already provide it.
# But for non-OSX systems, I will use the CMake Threads package.
IF(NOT APPLE)
FIND_PACKAGE(Threads)
ENDIF(NOT APPLE)
# MinGW needs an additional library, mwindows
# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows
# (Actually on second look, I think it only needs one of the m* libraries.)
IF(MINGW)
SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
ENDIF(MINGW)
SET(SDL2_FOUND "NO")
IF(SDL2_LIBRARY_TEMP)
# For SDL2main
IF(NOT SDL2_BUILDING_LIBRARY)
IF(SDL2MAIN_LIBRARY)
SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP})
ENDIF(SDL2MAIN_LIBRARY)
ENDIF(NOT SDL2_BUILDING_LIBRARY)
# For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa.
# CMake doesn't display the -framework Cocoa string in the UI even
# though it actually is there if I modify a pre-used variable.
# I think it has something to do with the CACHE STRING.
# So I use a temporary variable until the end so I can set the
# "real" variable in one-shot.
IF(APPLE)
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
ENDIF(APPLE)
# For threads, as mentioned Apple doesn't need this.
# In fact, there seems to be a problem if I used the Threads package
# and try using this line, so I'm just skipping it entirely for OS X.
IF(NOT APPLE)
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
ENDIF(NOT APPLE)
# For MinGW library
IF(MINGW)
SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
ENDIF(MINGW)
# Set the final string here so the GUI reflects the final state.
SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found")
# Set the temp variable to INTERNAL so it is not seen in the CMake GUI
SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "")
SET(SDL2_FOUND "YES")
ENDIF(SDL2_LIBRARY_TEMP)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2
REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)
+165
View File
@@ -0,0 +1,165 @@
# Copyright (c) 2012 Petroules Corporation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
# OF SUCH DAMAGE.
# Based on the Qt 5 processor detection code, so should be very accurate
# https://qt.gitorious.org/qt/qtbase/blobs/master/src/corelib/global/qprocessordetection.h
# Currently handles arm (v5, v6, v7), x86 (32/64), ia64, and ppc (32/64)
# Regarding POWER/PowerPC, just as is noted in the Qt source,
# "There are many more known variants/revisions that we do not handle/detect."
set(archdetect_c_code "
#if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM64) || defined (__aarch64__)
#if defined(__ARM_ARCH_7__) \\
|| defined(__ARM_ARCH_7A__) \\
|| defined(__ARM_ARCH_7R__) \\
|| defined(__ARM_ARCH_7M__) \\
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7)
#error cmake_ARCH armv7
#elif defined(__ARM_ARCH_6__) \\
|| defined(__ARM_ARCH_6J__) \\
|| defined(__ARM_ARCH_6T2__) \\
|| defined(__ARM_ARCH_6Z__) \\
|| defined(__ARM_ARCH_6K__) \\
|| defined(__ARM_ARCH_6ZK__) \\
|| defined(__ARM_ARCH_6M__) \\
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6)
#error cmake_ARCH armv6
#elif defined(__ARM_ARCH_5TEJ__) \\
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5)
#error cmake_ARCH armv5
#elif defined(_M_ARM64) || defined (__aarch64__)
#error cmake_ARCH arm64
#else
#error cmake_ARCH arm
#endif
#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
#error cmake_ARCH i386
#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
#error cmake_ARCH x86_64
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
#error cmake_ARCH ia64
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\
|| defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\
|| defined(_M_MPPC) || defined(_M_PPC)
#if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__)
#error cmake_ARCH ppc64
#else
#error cmake_ARCH ppc
#endif
#endif
#error cmake_ARCH unknown
")
# Set ppc_support to TRUE before including this file or ppc and ppc64
# will be treated as invalid architectures since they are no longer supported by Apple
function(target_architecture output_var)
if(APPLE AND CMAKE_OSX_ARCHITECTURES)
# On OS X we use CMAKE_OSX_ARCHITECTURES *if* it was set
# First let's normalize the order of the values
# Note that it's not possible to compile PowerPC applications if you are using
# the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we
# disable it by default
# See this page for more information:
# http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4
# Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime.
# On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise.
foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES})
if("${osx_arch}" STREQUAL "ppc" AND ppc_support)
set(osx_arch_ppc TRUE)
elseif("${osx_arch}" STREQUAL "i386")
set(osx_arch_i386 TRUE)
elseif("${osx_arch}" STREQUAL "x86_64")
set(osx_arch_x86_64 TRUE)
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
set(osx_arch_ppc64 TRUE)
elseif("${osx_arch}" STREQUAL "arm64")
set(osx_arch_arm64 TRUE)
else()
message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}")
endif()
endforeach()
# Now add all the architectures in our normalized order
if(osx_arch_ppc)
list(APPEND ARCH ppc)
endif()
if(osx_arch_i386)
list(APPEND ARCH i386)
endif()
if(osx_arch_x86_64)
list(APPEND ARCH x86_64)
endif()
if(osx_arch_ppc64)
list(APPEND ARCH ppc64)
endif()
if(osx_arch_arm64)
list(APPEND ARCH arm64)
endif()
else()
file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}")
enable_language(C)
# Detect the architecture in a rather creative way...
# This compiles a small C program which is a series of ifdefs that selects a
# particular #error preprocessor directive whose message string contains the
# target architecture. The program will always fail to compile (both because
# file is not a valid C program, and obviously because of the presence of the
# #error preprocessor directives... but by exploiting the preprocessor in this
# way, we can detect the correct target architecture even when cross-compiling,
# since the program itself never needs to be run (only the compiler/preprocessor)
try_run(
run_result_unused
compile_result_unused
"${CMAKE_BINARY_DIR}"
"${CMAKE_BINARY_DIR}/arch.c"
COMPILE_OUTPUT_VARIABLE ARCH
CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
)
# Parse the architecture name from the compiler output
string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}")
# Get rid of the value marker leaving just the architecture name
string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}")
# If we are compiling with an unknown architecture this variable should
# already be set to "unknown" but in the case that it's empty (i.e. due
# to a typo in the code), then set it to unknown
if (NOT ARCH)
set(ARCH unknown)
endif()
endif()
set(${output_var} "${ARCH}" PARENT_SCOPE)
endfunction()
+9
View File
@@ -0,0 +1,9 @@
[Desktop Entry]
Name=Perfect Dark
Comment=Modern source port of Perfect Dark
Exec=io.github.perfect_dark_pc_port.perfect_dark.sh
Icon=io.github.perfect_dark_pc_port.perfect_dark
Terminal=false
Type=Application
Categories=Game;ActionGame;
StartupNotify=false
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>io.github.perfect_dark_pc_port.perfect_dark</id>
<name>Perfect Dark</name>
<developer id="io.github.perfect_dark_pc_port.perfect_dark">
<name>Perfect Dark Contributors</name>
<url>https://github.com/fgsfdsfgs/perfect_dark/graphs/contributors</url>
</developer>
<launchable type="desktop-id">io.github.perfect_dark_pc_port.perfect_dark.desktop</launchable>
<summary>Modern cross-platform port of Perfect Dark</summary>
<metadata_license>CC0-1.0</metadata_license>
<project_license>MIT</project_license>
<url type="homepage">https://github.com/fgsfdsfgs/perfect_dark/</url>
<description>
<p>This is a port of Ryan Dywer's decompilation of classic N64 shooter Perfect Dark to modern systems.</p>
</description>
<!--
<screenshots>
<screenshot type="default">
<image type="source"></image>
<caption>Screenshot</caption>
</screenshot>
<screenshots>
-->
<categories>
<category>Game</category>
<category>ActionGame</category>
<category>Shooter</category>
</categories>
<keywords>
<keyword>n64</keyword>
<keyword>scifi</keyword>
<keyword>cyberpunk</keyword>
<keyword>retro</keyword>
<keyword>sourceport</keyword>
<keyword>port</keyword>
</keywords>
<releases>
<release version="latest" date="2024-05-14"/>
</releases>
<content_rating type="oars-1.1">
<content_attribute id="violence-realistic">moderate</content_attribute>
<content_attribute id="violence-bloodshed">mild</content_attribute>
</content_rating>
<update_contact>https://github.com/fgsfdsfgs/perfect_dark/</update_contact>
</component>
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

@@ -0,0 +1,39 @@
#!/bin/sh
# Create user data directories if necessary
userdirs=( roms saves mods )
for path in "${userdirs[@]}"; do
if [ ! -d "${XDG_DATA_HOME}/${path}" ]; then
mkdir -p "${XDG_DATA_HOME}/${path}"
fi
done
# Default to pd as executable but switch to jpn/pal if the NTSC rom
# is missing but JPN/PAL are present.
# TODO: Other arch
executable="pd.x86_64"
if [ -f ${XDG_DATA_HOME}/roms/pd.ntsc-final.z64 ] | \
[ -f ${XDG_DATA_HOME}/roms/pd.ntsc-1.0.z64 ]; then
executable="pd.x86_64"
elif [ -f ${XDG_DATA_HOME}/roms/pd.jpn-final.z64 ]; then
executable="pd.jpn.x86_64"
elif [ -f ${XDG_DATA_HOME}/roms/pd.pal-final.z64 ]; then
executable="pd.pal.x86_64"
fi
# If first parameter passed to this script is one of the pd executables,
# run that regardless of ROM auto-detection above and pass the remaining
# parameters to it; otherwise pass all arguments to the executable selected
# above
case $1 in
"pd."*)
executable=$1
params="${@:2}"
;;
*)
params="$@"
;;
esac
# Run game
$executable --basedir ${XDG_DATA_HOME}/roms --savedir ${XDG_DATA_HOME}/saves $params
@@ -0,0 +1,41 @@
app-id: io.github.perfect_dark_pc_port.perfect_dark
runtime: org.freedesktop.Platform
runtime-version: "25.08"
sdk: org.freedesktop.Sdk
command: io.github.perfect_dark_pc_port.perfect_dark.sh
finish-args:
- --device=all
- --share=ipc
- --socket=x11
# Audio
- --socket=pulseaudio
# Enable network for multiplayer
- --share=network
modules:
- name: perfect_dark
buildsystem: simple
sources:
- type: file
path: bin/pd.x86_64
- type: file
path: bin/pd.jpn.x86_64
- type: file
path: bin/pd.pal.x86_64
- type: file
path: io.github.perfect_dark_pc_port.perfect_dark.sh
- type: file
path: io.github.perfect_dark_pc_port.perfect_dark.png
- type: file
path: io.github.perfect_dark_pc_port.perfect_dark.metainfo.xml
- type: file
path: io.github.perfect_dark_pc_port.perfect_dark.desktop
build-commands: []
post-install:
# Install the binaries
- install -Dm 755 -t /app/bin/ pd.*
- install -Dm 755 ${FLATPAK_ID}.sh /app/bin/${FLATPAK_ID}.sh
- install -Dm 644 ${FLATPAK_ID}.desktop /app/share/applications/${FLATPAK_ID}.desktop
- install -Dm 644 ${FLATPAK_ID}.metainfo.xml /app/share/metainfo/${FLATPAK_ID}.metainfo.xml
- install -Dm 644 ${FLATPAK_ID}.png /app/share/icons/hicolor/256x256/apps/${FLATPAK_ID}.png
+2
View File
@@ -0,0 +1,2 @@
# Switch (SDL_GetPlatform is not changed in switch-sdl2)
000038f853776974636820436f6e7400,Switch Controller,a:b0,b:b1,back:b11,dpdown:b15,dpleft:b12,dpright:b14,dpup:b13,leftshoulder:b6,leftstick:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Unknown (see SDL_platform.h),
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

+1
View File
@@ -0,0 +1 @@
id ICON icon.ico
+1
View File
@@ -22,6 +22,7 @@
#define __R4300_H__
#include <PR/ultratypes.h>
#include "platform.h"
/*
* Segment base addresses and sizes
+62 -30
View File
@@ -22,6 +22,12 @@
#include <PR/ultratypes.h>
#include "gbiex.h"
#include <stdint.h>
#ifndef PLATFORM_N64
#include "platform.h"
#endif
/*
* To use the F3DEX ucodes, define F3DEX_GBI before include this file.
@@ -594,10 +600,10 @@
#define G_BL_0 3
#define GBL_c1(m1a, m1b, m2a, m2b) \
(m1a) << 30 | (m1b) << 26 | (m2a) << 22 | (m2b) << 18
(u32)(m1a) << 30 | (u32)(m1b) << 26 | (u32)(m2a) << 22 | (u32)(m2b) << 18
#define GBL_c2(m1a, m1b, m2a, m2b) \
(m1a) << 28 | (m1b) << 24 | (m2a) << 20 | (m2b) << 16
(u32)(m1a) << 28 | (u32)(m1b) << 24 | (u32)(m2a) << 20 | (u32)(m2b) << 16
#define RM_AA_ZB_OPA_SURF(clk) \
AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \
@@ -1053,7 +1059,7 @@ typedef struct {
// 4x4 float matrix
typedef float Mtx_t[4][4];
#else
typedef long Mtx_t[4][4];
typedef int32_t Mtx_t[4][4];
#endif
typedef union {
@@ -1306,6 +1312,14 @@ typedef union {
/*
* Graphics DMA Packet
*/
#ifdef PLATFORM_64BIT
typedef struct {
intptr_t par : 24;
intptr_t cmd : 8;
intptr_t len : 32;
uintptr_t addr;
} Gdma;
#else
typedef struct {
#ifdef PLATFORM_BIG_ENDIAN
int cmd:8;
@@ -1319,6 +1333,7 @@ typedef struct {
unsigned int addr;
#endif
} Gdma;
#endif
/*
* Graphics Immediate Mode Packet types
@@ -1357,6 +1372,9 @@ typedef struct {
unsigned char z4:4;
unsigned char pad:8;
unsigned char cmd:8;
#ifdef PLATFORM_64BIT
unsigned char pad2[4];
#endif
unsigned char x1:4;
unsigned char y1:4;
unsigned char x2:4;
@@ -1365,6 +1383,9 @@ typedef struct {
unsigned char y3:4;
unsigned char x4:4;
unsigned char y4:4;
#ifdef PLATFORM_64BIT
unsigned char pad3[4];
#endif
#endif
} Gtri4;
@@ -1538,8 +1559,8 @@ typedef struct {
* Generic Gfx Packet
*/
typedef struct {
unsigned int w0;
unsigned int w1;
uintptr_t w0;
uintptr_t w1;
} Gwords;
// xxxxxxxx 11223344 44555566 66666777
@@ -1596,7 +1617,11 @@ typedef struct {
*/
typedef union {
Gwords words;
#ifdef PLATFORM_64BIT
u8 bytes[16];
#else
u8 bytes[8];
#endif
Gdma dma;
Gvtx vtx;
Gtri tri;
@@ -1619,12 +1644,19 @@ typedef union {
Gloadtlut loadtlut;
#endif
GunkC0 unkc0;
#ifdef PLATFORM_64BIT
long long int force_structure_alignment[2];
#else
long long int force_structure_alignment;
#endif
} Gfx;
#ifdef PLATFORM_BIG_ENDIAN
#define GFX_W0_BYTE(i) (i)
#define GFX_W1_BYTE(i) (4 + (i))
#elif PLATFORM_64BIT
#define GFX_W0_BYTE(i) (3 - (i))
#define GFX_W1_BYTE(i) (11 - (i))
#else
#define GFX_W0_BYTE(i) (3 - (i))
#define GFX_W1_BYTE(i) (7 - (i))
@@ -1642,12 +1674,12 @@ typedef union {
Gfx *_g = (Gfx *)(pkt); \
\
_g->words.w0 = _SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24); \
_g->words.w1 = (unsigned int)(s); \
_g->words.w1 = (uintptr_t)(s); \
}
#define gsDma0p(c, s, l) \
{ \
_SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24), (unsigned int)(s) \
_SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24), (uintptr_t)(s) \
}
#define gDma1p(pkt, c, s, l, p) \
@@ -1656,14 +1688,14 @@ typedef union {
\
_g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | \
_SHIFTL((l), 0, 16)); \
_g->words.w1 = (unsigned int)(s); \
_g->words.w1 = (uintptr_t)(s); \
}
#define gsDma1p(c, s, l, p) \
{ \
(_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | \
_SHIFTL((l), 0, 16)), \
(unsigned int)(s) \
(uintptr_t)(s) \
}
#define gDma2p(pkt, c, adrs, len, idx, ofs) \
@@ -1671,14 +1703,14 @@ typedef union {
Gfx *_g = (Gfx *)(pkt); \
_g->words.w0 = (_SHIFTL((c),24,8)|_SHIFTL(((len)-1)/8,19,5)| \
_SHIFTL((ofs)/8,8,8)|_SHIFTL((idx),0,8)); \
_g->words.w1 = (unsigned int)(adrs); \
_g->words.w1 = (uintptr_t)(adrs); \
}
#define gsDma2p(c, adrs, len, idx, ofs) \
{ \
(_SHIFTL((c),24,8)|_SHIFTL(((len)-1)/8,19,5)| \
_SHIFTL((ofs)/8,8,8)|_SHIFTL((idx),0,8)), \
(unsigned int)(adrs) \
(uintptr_t)(adrs) \
}
#define gSPNoOp(pkt) gDma0p(pkt, G_SPNOOP, 0, 0)
@@ -1727,12 +1759,12 @@ typedef union {
Gfx *_g = (Gfx *)(pkt); \
\
_g->words.w0 = _SHIFTL((c), 24, 8); \
_g->words.w1 = (unsigned int)(p0); \
_g->words.w1 = (uintptr_t)(p0); \
}
#define gsImmp1(c, p0) \
{ \
_SHIFTL((c), 24, 8), (unsigned int)(p0) \
_SHIFTL((c), 24, 8), (uintptr_t)(p0) \
}
#define gImmp2(pkt, c, p0, p1) \
@@ -1769,13 +1801,13 @@ typedef union {
\
_g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | \
_SHIFTL((p1), 0, 8)); \
_g->words.w1 = (unsigned int) (dat); \
_g->words.w1 = (uintptr_t) (dat); \
}
#define gsImmp21(c, p0, p1, dat) \
{ \
_SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | _SHIFTL((p1), 0, 8), \
(unsigned int) (dat) \
(uintptr_t) (dat) \
}
#define gMoveWd(pkt, index, offset, data) \
@@ -1918,7 +1950,7 @@ typedef union {
\
_g->words.w0 = _SHIFTL(G_CULLDL, 24, 8) | \
((0x0f & (vstart))*40); \
_g->words.w1 = (unsigned int)((0x0f & ((vend)+1))*40); \
_g->words.w1 = (uintptr_t)((0x0f & ((vend)+1))*40); \
}
// Removed in PD
@@ -2239,12 +2271,12 @@ typedef union {
Gfx *_g = (Gfx *)(pkt); \
\
_g->words.w0 = _SHIFTL(G_SETGEOMETRYMODE, 24, 8); \
_g->words.w1 = (unsigned int)(word); \
_g->words.w1 = (uintptr_t)(word); \
}
#define gsSPSetGeometryMode(word) \
{ \
_SHIFTL(G_SETGEOMETRYMODE, 24, 8), (unsigned int)(word) \
_SHIFTL(G_SETGEOMETRYMODE, 24, 8), (uintptr_t)(word) \
}
#define gSPClearGeometryMode(pkt, word) \
@@ -2252,12 +2284,12 @@ typedef union {
Gfx *_g = (Gfx *)(pkt); \
\
_g->words.w0 = _SHIFTL(G_CLEARGEOMETRYMODE, 24, 8); \
_g->words.w1 = (unsigned int)(word); \
_g->words.w1 = (uintptr_t)(word); \
}
#define gsSPClearGeometryMode(word) \
{ \
_SHIFTL(G_CLEARGEOMETRYMODE, 24, 8), (unsigned int)(word) \
_SHIFTL(G_CLEARGEOMETRYMODE, 24, 8), (uintptr_t)(word) \
}
#define gSPSetOtherMode(pkt, cmd, sft, len, data) \
@@ -2266,13 +2298,13 @@ typedef union {
\
_g->words.w0 = (_SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | \
_SHIFTL(len, 0, 8)); \
_g->words.w1 = (unsigned int)(data); \
_g->words.w1 = (uintptr_t)(data); \
}
#define gsSPSetOtherMode(cmd, sft, len, data) \
{ \
_SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | _SHIFTL(len, 0, 8), \
(unsigned int)(data) \
(uintptr_t)(data) \
}
/*
@@ -2323,14 +2355,14 @@ typedef union {
\
_g->words.w0 = _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | \
_SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12); \
_g->words.w1 = (unsigned int)(i); \
_g->words.w1 = (uintptr_t)(i); \
}
#define gsSetImage(cmd, fmt, siz, width, i) \
{ \
_SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | \
_SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12), \
(unsigned int)(i) \
(uintptr_t)(i) \
}
#define gDPSetColorImage(pkt, f, s, w, i) gSetImage(pkt, G_SETCIMG, f, s, w, i)
@@ -2356,13 +2388,13 @@ typedef union {
Gfx *_g = (Gfx *)(pkt); \
\
_g->words.w0 = _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24); \
_g->words.w1 = (unsigned int)(muxs1); \
_g->words.w1 = (uintptr_t)(muxs1); \
}
#define gsDPSetCombine(muxs0, muxs1) \
{ \
_SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24), \
(unsigned int)(muxs1) \
(uintptr_t)(muxs1) \
}
#define GCCc0w0(saRGB0, mRGB0, saA0, mA0) \
@@ -2435,12 +2467,12 @@ typedef union {
Gfx *_g = (Gfx *)(pkt); \
\
_g->words.w0 = _SHIFTL(c, 24, 8); \
_g->words.w1 = (unsigned int)(d); \
_g->words.w1 = (uintptr_t)(d); \
}
#define gsDPSetColor(c, d) \
{ \
_SHIFTL(c, 24, 8), (unsigned int)(d) \
_SHIFTL(c, 24, 8), (uintptr_t)(d) \
}
#define DPRGBColor(pkt, cmd, r, g, b, a) \
@@ -2521,13 +2553,13 @@ typedef union {
Gfx *_g = (Gfx *)(pkt); \
\
_g->words.w0 = _SHIFTL(G_RDPSETOTHERMODE,24,8)|_SHIFTL(mode0,0,24); \
_g->words.w1 = (unsigned int)(mode1); \
_g->words.w1 = (uintptr_t)(mode1); \
}
#define gsDPSetOtherMode(mode0, mode1) \
{ \
_SHIFTL(G_RDPSETOTHERMODE,24,8)|_SHIFTL(mode0,0,24), \
(unsigned int)(mode1) \
(uintptr_t)(mode1) \
}
/*
+1 -1
View File
@@ -35,7 +35,7 @@
#define OS_M_PI 3.14159265358979323846
#define M_DTOR (3.14159265358979323846/180.0)
#define FTOFIX32(x) (long)((x) * (float)0x00010000)
#define FTOFIX32(x) (int)((x) * (float)0x00010000)
#define FIX32TOF(x) ((float)(x) * (1.0f / (float)0x00010000))
#define FTOFRAC8(x) ((int) MIN(((x) * (128.0f)), 127.0f) & 0xff)
+12 -1
View File
@@ -28,6 +28,7 @@ extern "C" {
#include <PR/ultratypes.h>
#include <PR/mbi.h>
#include "platform.h"
struct var8009c340 {
u8 surround;
@@ -256,7 +257,7 @@ typedef struct {
ALOscStop stopOsc;
ALSeqMarker *loopStart;
ALSeqMarker *loopEnd;
s32 loopCount; /* -1 = loop forever, 0 = no loop */
intptr_t loopCount; /* -1 = loop forever, 0 = no loop */
u8 unk88;
u8 unk89;
} N_ALSeqPlayer;
@@ -284,9 +285,19 @@ typedef struct {
ALOscInit initOsc;
ALOscUpdate updateOsc;
ALOscStop stopOsc;
#ifdef PLATFORM_64BIT
s32 _pad1_;
f32 unk7c;
s32 _pad2_;
f32 unk80;
#else
f32 unk7c;
f32 unk80;
#endif
void *queue;
u8 unk88;
u8 unk89;
} N_ALCSPlayer;
+6
View File
@@ -31,10 +31,14 @@
#define _OS_LIBC_H_
#include "os_pfs.h"
#include "platform.h"
#ifndef PLATFORM_N64
#include <stdio.h>
#endif
#ifdef PLATFORM_OSX
#include <strings.h>
#endif
#ifdef _LANGUAGE_C_PLUS_PLUS
extern "C" {
@@ -84,9 +88,11 @@ extern "C" {
/* byte string operations */
#ifndef PLATFORM_OSX
extern void bcopy(const void *, void *, size_t);
extern int bcmp(const void *, const void *, size_t);
extern void bzero(void *, size_t);
#endif
/* Printf */
+2 -2
View File
@@ -37,7 +37,7 @@ extern "C" {
#include <PR/ultratypes.h>
#include "os_thread.h"
#include "os_message.h"
#include <stdint.h>
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
@@ -198,7 +198,7 @@ extern u32 osPiGetStatus(void);
extern s32 osPiGetDeviceType(void);
extern s32 osPiWriteIo(u32, u32);
extern s32 osPiReadIo(u32, u32 *);
extern s32 osPiStartDma(OSIoMesg *, s32, s32, u32, void *, u32,
extern s32 osPiStartDma(OSIoMesg *, s32, s32, uintptr_t, void *, u32,
OSMesgQueue *);
extern void osCreatePiManager(OSPri, OSMesgQueue *, OSMesg *, s32);
+3 -3
View File
@@ -44,15 +44,15 @@ void gfx_start_frame(void);
void gfx_run(Gfx* commands);
void gfx_end_frame(void);
void gfx_set_target_fps(int);
void gfx_set_maximum_frame_latency(int latency);
void gfx_set_texture_filter(enum FilteringMode mode);
void gfx_set_mipmap_filter(enum MipmapFilteringMode mode);
void gfx_texture_cache_clear(void);
void gfx_texture_cache_delete(const uint8_t *orig_addr);
void gfx_texture_cache_delete_range(const uint8_t *start, const uint8_t *end);
int gfx_create_framebuffer(uint32_t width, uint32_t height, int upscale, int autoresize);
void gfx_resize_framebuffer(int fb, uint32_t width, uint32_t height, int upscale, int autoresize);
void gfx_set_framebuffer(int fb, float noise_scale) ;
void gfx_reset_framebuffer(void);
void gfx_copy_framebuffer(int fb_dst, int fb_src, int left, int top, int use_back);
void gfx_get_pixel_depth_prepare(float x, float y);
uint16_t gfx_get_pixel_depth(float x, float y);
#endif
+498 -201
View File
File diff suppressed because it is too large. Load diff
+142 -102
View File
@@ -125,8 +125,6 @@ static struct RSP {
float aspect_ofs;
float aspect_scale;
float depth_zfar;
struct {
// U0.16
uint16_t s, t;
@@ -194,12 +192,13 @@ static struct RDP {
bool viewport_or_scissor_changed;
void* z_buf_address;
void* color_image_address;
int16_t subpixel_ofs_x;
int16_t subpixel_ofs_y;
} rdp;
static struct RenderingState {
uint8_t depth_test_and_mask; // 1: depth test, 2: depth mask
float depth_zfar;
bool decal_mode;
uint8_t depth_mode;
bool alpha_blend;
bool modulate;
struct XYWidthHeight viewport, scissor;
@@ -523,7 +522,7 @@ static bool gfx_texture_cache_lookup(int i, const TextureCacheKey& key) {
TextureCacheNode** n = &rendering_state.textures[i];
if (it != gfx_texture_cache.map.end()) {
gfx_rapi->select_texture(i, it->second.texture_id);
gfx_rapi->select_texture(i, it->second.texture_id, it->second.linear_filter);
*n = &*it;
gfx_texture_cache.lru.splice(gfx_texture_cache.lru.end(), gfx_texture_cache.lru,
it->second.lru_location); // move to back
@@ -551,8 +550,8 @@ static bool gfx_texture_cache_lookup(int i, const TextureCacheKey& key) {
node->second.texture_id = texture_id;
node->second.lru_location = gfx_texture_cache.lru.insert(gfx_texture_cache.lru.end(), { it });
gfx_rapi->select_texture(i, texture_id);
gfx_rapi->set_sampler_parameters(i, false, 0, 0);
gfx_rapi->select_texture(i, texture_id, false);
gfx_rapi->set_sampler_parameters(i, false, 0, 0, rdp.tex_lod);
*n = node;
return false;
}
@@ -586,8 +585,30 @@ void gfx_texture_cache_delete(const uint8_t* orig_addr) {
}
}
static void import_texture_rgba16(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
void gfx_texture_cache_delete_range(const uint8_t* start, const uint8_t* end) {
gfx_flush();
for (int i = 0; i < 2; ++i) {
if (rendering_state.textures[i]
&& rendering_state.textures[i]->first.texture_addr >= start
&& rendering_state.textures[i]->first.texture_addr < end) {
rdp.textures_changed[i] = true;
rendering_state.textures[i] = nullptr;
}
}
for (auto it = gfx_texture_cache.map.begin(); it != gfx_texture_cache.map.end(); ) {
if (it->first.texture_addr >= start && it->first.texture_addr < end) {
gfx_texture_cache.lru.erase(it->second.lru_location);
gfx_texture_cache.free_texture_ids.push_back(it->second.texture_id);
it = gfx_texture_cache.map.erase(it);
} else {
++it;
}
}
}
static void import_texture_rgba16(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
const uint8_t* addr = loaded_texture.addr;
const uint32_t size_bytes = loaded_texture.size_bytes;
const uint32_t full_image_line_size_bytes =
@@ -613,11 +634,11 @@ static void import_texture_rgba16(int tile, const LoadedTexture& loaded_texture,
const uint32_t width = rdp.texture_tile[tile].line_size_bytes / 2;
const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes;
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
}
static void import_texture_rgba32(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
static void import_texture_rgba32(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
const uint8_t* addr = loaded_texture.addr;
const uint32_t size_bytes = loaded_texture.size_bytes;
@@ -634,11 +655,11 @@ static void import_texture_rgba32(int tile, const LoadedTexture& loaded_texture,
const uint32_t width = rdp.texture_tile[tile].line_size_bytes / 2;
const uint32_t height = (size_bytes / 2) / rdp.texture_tile[tile].line_size_bytes;
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
// DumpTexture(loaded_texture.otr_path, addr, width, height);
}
static void import_texture_ia4(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
static void import_texture_ia4(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
const uint8_t* addr = loaded_texture.addr;
const uint32_t size_bytes = loaded_texture.size_bytes;
@@ -663,11 +684,11 @@ static void import_texture_ia4(int tile, const LoadedTexture& loaded_texture, bo
const uint32_t width = rdp.texture_tile[tile].line_size_bytes * 2;
const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes;
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
}
static void import_texture_ia8(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
static void import_texture_ia8(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
const uint8_t* addr = loaded_texture.addr;
const uint32_t size_bytes = loaded_texture.size_bytes;
@@ -689,11 +710,11 @@ static void import_texture_ia8(int tile, const LoadedTexture& loaded_texture, bo
const uint32_t width = rdp.texture_tile[tile].line_size_bytes;
const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes;
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
}
static void import_texture_ia16(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
static void import_texture_ia16(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
const uint8_t* addr = loaded_texture.addr;
const uint32_t size_bytes = loaded_texture.size_bytes;
@@ -715,11 +736,11 @@ static void import_texture_ia16(int tile, const LoadedTexture& loaded_texture, b
const uint32_t width = rdp.texture_tile[tile].line_size_bytes / 2;
const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes;
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
}
static void import_texture_i4(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
static void import_texture_i4(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
const uint8_t* addr = loaded_texture.addr;
const uint32_t size_bytes = loaded_texture.size_bytes;
@@ -742,11 +763,11 @@ static void import_texture_i4(int tile, const LoadedTexture& loaded_texture, boo
const uint32_t width = rdp.texture_tile[tile].line_size_bytes * 2;
const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes;
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
}
static void import_texture_i8(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
static void import_texture_i8(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
const uint8_t* addr = loaded_texture.addr;
const uint32_t size_bytes = loaded_texture.size_bytes;
@@ -767,7 +788,7 @@ static void import_texture_i8(int tile, const LoadedTexture& loaded_texture, boo
const uint32_t width = rdp.texture_tile[tile].line_size_bytes;
const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes;
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
}
@@ -792,8 +813,8 @@ static inline void palette_to_rgba32(const uint16_t palentry, uint8_t *rgba32_bu
}
}
static void import_texture_ci4(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
static void import_texture_ci4(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
const uint8_t* addr = loaded_texture.addr;
const uint32_t size_bytes = loaded_texture.size_bytes;
const uint32_t full_image_line_size_bytes =
@@ -817,11 +838,11 @@ static void import_texture_ci4(int tile, const LoadedTexture& loaded_texture, bo
const uint32_t width = result_line_size * 2;
const uint32_t height = size_bytes / result_line_size;
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
}
static void import_texture_ci8(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
static void import_texture_ci8(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
const uint8_t* addr = loaded_texture.addr;
const uint32_t size_bytes = loaded_texture.size_bytes;
const uint32_t full_image_line_size_bytes =
@@ -843,8 +864,7 @@ static void import_texture_ci8(int tile, const LoadedTexture& loaded_texture, bo
const uint32_t width = result_line_size;
const uint32_t height = size_bytes / result_line_size;
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
}
static void import_texture(int i, int tile, bool importReplacement) {
@@ -886,35 +906,35 @@ static void import_texture(int i, int tile, bool importReplacement) {
if (fmt == G_IM_FMT_RGBA) {
if (siz == G_IM_SIZ_16b) {
import_texture_rgba16(tile, loaded_texture, importReplacement);
import_texture_rgba16(tile, loaded_texture, rdp.tex_lod);
} else if (siz == G_IM_SIZ_32b) {
import_texture_rgba32(tile, loaded_texture, importReplacement);
import_texture_rgba32(tile, loaded_texture, rdp.tex_lod);
} else {
sysFatalError("Bad size for RGBA texture in tile %d: %02x", tile, siz);
}
} else if (fmt == G_IM_FMT_IA) {
if (siz == G_IM_SIZ_4b) {
import_texture_ia4(tile, loaded_texture, importReplacement);
import_texture_ia4(tile, loaded_texture, rdp.tex_lod);
} else if (siz == G_IM_SIZ_8b) {
import_texture_ia8(tile, loaded_texture, importReplacement);
import_texture_ia8(tile, loaded_texture, rdp.tex_lod);
} else if (siz == G_IM_SIZ_16b) {
import_texture_ia16(tile, loaded_texture, importReplacement);
import_texture_ia16(tile, loaded_texture, rdp.tex_lod);
} else {
sysFatalError("Bad size for IA texture in tile %d: %02x", tile, siz);
}
} else if (fmt == G_IM_FMT_CI) {
if (siz == G_IM_SIZ_4b) {
import_texture_ci4(tile, loaded_texture, importReplacement);
import_texture_ci4(tile, loaded_texture, rdp.tex_lod);
} else if (siz == G_IM_SIZ_8b) {
import_texture_ci8(tile, loaded_texture, importReplacement);
import_texture_ci8(tile, loaded_texture, rdp.tex_lod);
} else {
sysFatalError("Bad size for CI texture in tile %d: %02x", tile, siz);
}
} else if (fmt == G_IM_FMT_I) {
if (siz == G_IM_SIZ_4b) {
import_texture_i4(tile, loaded_texture, importReplacement);
import_texture_i4(tile, loaded_texture, rdp.tex_lod);
} else if (siz == G_IM_SIZ_8b) {
import_texture_i8(tile, loaded_texture, importReplacement);
import_texture_i8(tile, loaded_texture, rdp.tex_lod);
} else {
sysFatalError("Bad size for I texture in tile %d: %02x", tile, siz);
}
@@ -1240,25 +1260,18 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo
}
}
bool depth_test = (rsp.geometry_mode & G_ZBUFFER) == G_ZBUFFER;
bool depth_mask = (rdp.other_mode_l & Z_UPD) == Z_UPD;
uint8_t depth_test_and_mask = (depth_test ? 1 : 0) | (depth_mask ? 2 : 0);
if (depth_test_and_mask != rendering_state.depth_test_and_mask) {
gfx_flush();
gfx_rapi->set_depth_test_and_mask(depth_test, depth_mask);
rendering_state.depth_test_and_mask = depth_test_and_mask;
}
if (rsp.depth_zfar != rendering_state.depth_zfar) {
gfx_flush();
gfx_rapi->set_depth_range(0.0f, rsp.depth_zfar);
rendering_state.depth_zfar = rsp.depth_zfar;
}
bool depth_test = ((rsp.geometry_mode & G_ZBUFFER) == G_ZBUFFER || (rdp.other_mode_l & G_ZS_PRIM) == G_ZS_PRIM) &&
((rdp.other_mode_h & G_CYC_1CYCLE) == G_CYC_1CYCLE || (rdp.other_mode_h & G_CYC_2CYCLE) == G_CYC_2CYCLE);
bool depth_update = (rdp.other_mode_l & Z_UPD) == Z_UPD;
bool depth_compare = (rdp.other_mode_l & Z_CMP) == Z_CMP;
bool depth_source_prim = (rdp.other_mode_l & G_ZS_PRIM) == G_ZS_PRIM /* && gDP.primDepth.z == 1.0f */;
uint16_t zmode = rdp.other_mode_l & ZMODE_DEC;
uint8_t depth_mode = (depth_test ? 1 : 0) | (depth_update ? 2 : 0) | (depth_compare ? 4 : 0) | (depth_source_prim ? 8 : 0) | (zmode >> 6);
bool zmode_decal = (rdp.other_mode_l & ZMODE_DEC) == ZMODE_DEC;
if (zmode_decal != rendering_state.decal_mode) {
if (depth_mode != rendering_state.depth_mode) {
gfx_flush();
gfx_rapi->set_zmode_decal(zmode_decal);
rendering_state.decal_mode = zmode_decal;
gfx_rapi->set_depth_mode(depth_test, depth_update, depth_compare, depth_source_prim, zmode);
rendering_state.depth_mode = depth_mode;
}
if (rdp.viewport_or_scissor_changed) {
@@ -1391,7 +1404,7 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo
if (linear_filter != rendering_state.textures[i]->second.linear_filter ||
cms != rendering_state.textures[i]->second.cms || cmt != rendering_state.textures[i]->second.cmt) {
gfx_flush();
gfx_rapi->set_sampler_parameters(i, linear_filter, cms, cmt);
gfx_rapi->set_sampler_parameters(i, linear_filter, cms, cmt, rdp.tex_lod);
rendering_state.textures[i]->second.linear_filter = linear_filter;
rendering_state.textures[i]->second.cms = cms;
rendering_state.textures[i]->second.cmt = cmt;
@@ -1584,7 +1597,7 @@ static inline void gfx_sp_tri4(Gfx *cmd) {
uint8_t x = C1(0, 4);
uint8_t y = C1(4, 4);
uint8_t z = C0(0, 4);
if(x || y || z) {
gfx_sp_tri1(x, y, z, false);
}
@@ -1648,34 +1661,34 @@ static void gfx_sp_extra_geometry_mode(uint32_t clear, uint32_t set) {
}
static void gfx_adjust_viewport_or_scissor(XYWidthHeight* area, bool preserve_aspect = false) {
if (!fbActive) {
area->width *= RATIO_X;
area->x *= RATIO_X;
area->height *= RATIO_Y;
area->y = SCREEN_HEIGHT - area->y;
area->y *= RATIO_Y;
if (preserve_aspect) {
// preserve native aspect ratio
const float ratio = gfx_current_native_aspect / gfx_current_dimensions.aspect_ratio;
const float midx = gfx_current_dimensions.width * 0.5f;
area->x = midx + (area->x - midx) * ratio;
area->x += rsp.aspect_ofs * gfx_current_dimensions.width * 0.5f;
area->width *= ratio;
}
// HACK: assume all target framebuffers have the same aspect
// Use floor/ceil to ensure scissor fully contains the logical region
// and prevents sub-pixel gaps at viewport edges
float x1 = area->x * RATIO_X;
float y1 = (SCREEN_HEIGHT - area->y) * RATIO_Y;
float x2 = (area->x + area->width) * RATIO_X;
float y2 = (SCREEN_HEIGHT - area->y + area->height) * RATIO_Y;
area->x = std::floor(x1);
area->y = std::floor(y1);
area->width = std::ceil(x2) - area->x;
area->height = std::ceil(y2) - area->y;
if (preserve_aspect) {
// preserve native aspect ratio
const float ratio = gfx_current_native_aspect / gfx_current_dimensions.aspect_ratio;
const float midx = gfx_current_dimensions.width * 0.5f;
area->x = midx + (area->x - midx) * ratio;
area->x += rsp.aspect_ofs * gfx_current_dimensions.width * 0.5f;
area->width *= ratio;
}
if (!game_renders_to_framebuffer ||
(gfx_msaa_level > 1 && gfx_current_dimensions.width == gfx_current_game_window_viewport.width &&
gfx_current_dimensions.height == gfx_current_game_window_viewport.height)) {
area->x += gfx_current_game_window_viewport.x;
area->y += gfx_current_window_dimensions.height -
(gfx_current_game_window_viewport.y + gfx_current_game_window_viewport.height);
}
} else {
area->width *= RATIO_Y;
area->height *= RATIO_Y;
area->x *= RATIO_Y;
area->y = active_fb->second.orig_height - area->y;
area->y *= RATIO_Y;
if (!game_renders_to_framebuffer ||
(gfx_msaa_level > 1 && gfx_current_dimensions.width == gfx_current_game_window_viewport.width &&
gfx_current_dimensions.height == gfx_current_game_window_viewport.height)) {
area->x += gfx_current_game_window_viewport.x;
area->y += gfx_current_window_dimensions.height -
(gfx_current_game_window_viewport.y + gfx_current_game_window_viewport.height);
}
}
@@ -1733,18 +1746,6 @@ static void gfx_sp_moveword(uint8_t index, uint16_t offset, uintptr_t data) {
case G_MW_SEGMENT:
segmentPointers[(offset >> 2) & 0xff] = data;
break;
case G_MW_PERSPNORM:
// the default z range is around [100, 10000]
// data is 2 / (znear + zfar) represented as a 0.16 fixed point
// => (znear + zfar) = (2 / (data / 65536)) = 131072 / data
constexpr float full_range_mul = 1.f / 11000.f; // that's around the biggest value I got when testing
if (data == 0) {
rsp.depth_zfar = 1.f;
} else {
// sometimes this will overshoot 1 but GL can handle that
rsp.depth_zfar =((131072.f * full_range_mul) / (float)data);
}
break;
}
}
@@ -1999,6 +2000,11 @@ static void gfx_dp_set_fill_color(uint32_t packed_color) {
rdp.fill_color.a = a * 255;
}
static void gfx_dp_set_subpixel_offset(int16_t x, int16_t y) {
rdp.subpixel_ofs_x = x;
rdp.subpixel_ofs_y = y;
}
static void gfx_draw_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int32_t lry) {
uint32_t saved_other_mode_h = rdp.other_mode_h;
uint32_t cycle_type = (rdp.other_mode_h & (3U << G_MDSFT_CYCLETYPE));
@@ -2007,6 +2013,11 @@ static void gfx_draw_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int32_t lr
rdp.other_mode_h = (rdp.other_mode_h & ~(3U << G_MDSFT_TEXTFILT)) | G_TF_POINT;
}
ulx += rdp.subpixel_ofs_x;
lrx += rdp.subpixel_ofs_x;
uly += rdp.subpixel_ofs_y;
lry += rdp.subpixel_ofs_y;
// U10.2 coordinates
float ulxf = ulx;
float ulyf = uly;
@@ -2391,6 +2402,10 @@ static void gfx_run_dl(Gfx* cmd) {
break;
// G_SETPRIMCOLOR, G_CCMUX_PRIMITIVE, G_ACMUX_PRIMITIVE, is used by Goddard
// G_CCMUX_TEXEL1, LOD_FRACTION is used in Bowser room 1
case G_SETSUBPIXELOFFSET_EXT: {
gfx_dp_set_subpixel_offset(C0(0, 16), C1(0, 16));
break;
}
case G_TEXRECT:
case G_TEXRECTFLIP: {
int32_t lrx, lry, tile, ulx, uly;
@@ -2504,6 +2519,10 @@ static void gfx_run_dl(Gfx* cmd) {
case G_RDPFLUSH_EXT:
gfx_flush();
break;
case G_CLEAR_DEPTH_EXT:
gfx_flush();
gfx_rapi->clear_framebuffer(false, true);
break;
case G_RDPPIPESYNC:
case G_RDPFULLSYNC:
case G_RDPLOADSYNC:
@@ -2554,8 +2573,6 @@ extern "C" void gfx_init(const GfxInitSettings *settings) {
tex_upload_buffer = (uint8_t*)malloc(max_tex_size * max_tex_size * 4);
}
rsp.depth_zfar = 1.0f;
rsp.lookat[0].dir[0] = rsp.lookat[1].dir[1] = 0x7F;
rsp.current_lookat_coeffs[0][0] = rsp.current_lookat_coeffs[1][1] = 1.f;
rsp.lookat_enabled = true;
@@ -2661,7 +2678,7 @@ extern "C" void gfx_run(Gfx* commands) {
gfx_rapi->start_frame();
gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0,
(float)gfx_current_dimensions.height / SCREEN_HEIGHT);
gfx_rapi->clear_framebuffer();
gfx_rapi->clear_framebuffer(true, false);
rdp.viewport_or_scissor_changed = true;
rendering_state.viewport = {};
rendering_state.scissor = {};
@@ -2671,7 +2688,7 @@ extern "C" void gfx_run(Gfx* commands) {
if (game_renders_to_framebuffer) {
gfx_rapi->start_draw_to_framebuffer(0, 1);
gfx_rapi->clear_framebuffer();
gfx_rapi->clear_framebuffer(true, true);
if (gfx_msaa_level > 1) {
bool different_size = gfx_current_dimensions.width != gfx_current_game_window_viewport.width ||
@@ -2703,6 +2720,27 @@ extern "C" void gfx_set_target_fps(int fps) {
gfx_wapi->set_target_fps(fps);
}
extern "C" void reset_texture_state() {
gfx_texture_cache_clear();
if (rendering_state.shader_program) {
gfx_rapi->unload_shader(rendering_state.shader_program);
rendering_state.shader_program = nullptr;
}
gfx_rapi->clear_shaders();
color_combiner_pool.clear();
prev_combiner = color_combiner_pool.end();
}
extern "C" void gfx_set_texture_filter(enum FilteringMode mode) {
reset_texture_state();
gfx_rapi->set_texture_filter(mode);
}
extern "C" void gfx_set_mipmap_filter(enum MipmapFilteringMode mode) {
reset_texture_state();
gfx_rapi->set_mipmap_filter(mode);
}
extern "C" int gfx_create_framebuffer(uint32_t width, uint32_t height, int upscale, int autoresize) {
int fb = gfx_rapi->create_framebuffer();
gfx_resize_framebuffer(fb, width, height, upscale, autoresize);
@@ -2734,7 +2772,8 @@ extern "C" void gfx_resize_framebuffer(int fb, uint32_t width, uint32_t height,
extern "C" void gfx_set_framebuffer(int fb, float noise_scale) {
gfx_rapi->start_draw_to_framebuffer(fb, noise_scale);
gfx_rapi->clear_framebuffer();
gfx_rapi->clear_framebuffer(true, true);
active_fb = framebuffers.find(fb);
}
extern "C" void gfx_copy_framebuffer(int fb_dst, int fb_src, int left, int top, int use_back) {
@@ -2759,4 +2798,5 @@ extern "C" void gfx_copy_framebuffer(int fb_dst, int fb_src, int left, int top,
extern "C" void gfx_reset_framebuffer(void) {
gfx_rapi->start_draw_to_framebuffer(0, (float)gfx_current_dimensions.height / SCREEN_HEIGHT);
active_fb = framebuffers.end();
}
+10 -6
View File
@@ -13,6 +13,7 @@ struct GfxClipParameters {
};
enum FilteringMode { FILTER_NONE, FILTER_LINEAR, FILTER_THREE_POINT };
enum MipmapFilteringMode { MIPMAP_DISABLED, MIPMAP_NEAREST, MIPMAP_LINEAR };
struct GfxRenderingAPI {
const char* (*get_name)(void);
@@ -23,13 +24,13 @@ struct GfxRenderingAPI {
struct ShaderProgram* (*create_and_load_new_shader)(uint64_t shader_id0, uint32_t shader_id1);
struct ShaderProgram* (*lookup_shader)(uint64_t shader_id0, uint32_t shader_id1);
void (*shader_get_info)(struct ShaderProgram* prg, uint8_t* num_inputs, bool used_textures[2]);
void (*clear_shaders)(void);
uint32_t (*new_texture)(void);
void (*select_texture)(int tile, uint32_t texture_id);
void (*upload_texture)(const uint8_t* rgba32_buf, uint32_t width, uint32_t height);
void (*set_sampler_parameters)(int sampler, bool linear_filter, uint32_t cms, uint32_t cmt);
void (*set_depth_test_and_mask)(bool depth_test, bool z_upd);
void (*select_texture)(int tile, uint32_t texture_id, bool linear_filter);
void (*upload_texture)(const uint8_t* rgba32_buf, uint32_t width, uint32_t height, bool gen_mipmaps);
void (*set_sampler_parameters)(int sampler, bool linear_filter, uint32_t cms, uint32_t cmt, bool mipmaps);
void (*set_depth_mode)(bool depth_test, bool depth_update, bool depth_compare, bool depth_source_prim, uint16_t zmode);
void (*set_depth_range)(float znear, float zfar);
void (*set_zmode_decal)(bool zmode_decal);
void (*set_viewport)(int x, int y, int width, int height);
void (*set_scissor)(int x, int y, int width, int height);
void (*set_use_alpha)(bool use_alpha, bool modulate);
@@ -45,13 +46,16 @@ struct GfxRenderingAPI {
bool can_extract_depth);
bool (*start_draw_to_framebuffer)(int fb_id, float noise_scale);
void (*copy_framebuffer)(int fb_dst, int fb_src, int left, int top, bool flip_y, bool use_back);
void (*clear_framebuffer)(void);
void (*clear_framebuffer)(bool clear_color, bool clear_depth);
void (*resolve_msaa_color_buffer)(int fb_id_target, int fb_id_source);
void* (*get_framebuffer_texture_id)(int fb_id);
void (*select_texture_fb)(int fb_id);
void (*delete_texture)(uint32_t texID);
void (*set_texture_filter)(enum FilteringMode mode);
enum FilteringMode (*get_texture_filter)(void);
void (*set_mipmap_filter)(enum MipmapFilteringMode mode);
void (*set_anisotropy_level)(int);
int (*get_max_anisotropy_level)(void);
};
#endif
+152 -31
View File
@@ -30,10 +30,30 @@ static uint64_t qpc_freq;
#define FRAME_INTERVAL_US_NUMERATOR 1000000
#define FRAME_INTERVAL_US_DENOMINATOR (target_fps)
static void set_fullscreen(bool on, bool call_callback) {
if (fullscreen_state == on) {
return;
static int32_t gfx_sdl_get_maximized_state(void) {
return (int32_t)maximized_state;
}
static int32_t gfx_sdl_get_fullscreen_state(void) {
return (int32_t)fullscreen_state;
}
static int32_t gfx_sdl_get_fullscreen_flag_mode(void) {
return fullscreen_flag == SDL_WINDOW_FULLSCREEN_DESKTOP ? 0 : 1;
}
static void gfx_sdl_set_fullscreen_flag(int32_t mode) {
switch (mode) {
case 0: {
fullscreen_flag = SDL_WINDOW_FULLSCREEN_DESKTOP;
} break;
case 1: {
fullscreen_flag = SDL_WINDOW_FULLSCREEN;
} break;
}
}
static void set_fullscreen(bool on, bool call_callback) {
fullscreen_state = on;
SDL_SetWindowFullscreen(wnd, on ? fullscreen_flag : 0);
if (call_callback && on_fullscreen_changed_callback) {
@@ -42,9 +62,6 @@ static void set_fullscreen(bool on, bool call_callback) {
}
static void set_maximize_window(bool on) {
if (maximized_state == on) {
return;
}
maximized_state = on;
if (on) {
SDL_MaximizeWindow(wnd);
@@ -83,7 +100,6 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
if (sysArgCheck("--debug-gl")) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
}
@@ -92,15 +108,23 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
int posY = set->y;
int display_in_use = SDL_GetWindowDisplayIndex(wnd);
if (display_in_use < 0) { // Fallback to default if out of bounds
posX = 100;
posY = 100;
posX = SDL_WINDOWPOS_UNDEFINED;
posY = SDL_WINDOWPOS_UNDEFINED;
}
if (set->centered) {
SDL_DisplayMode mode = {};
SDL_GetCurrentDisplayMode(0, &mode);
posX = mode.w / 2 - window_width / 2;
posY = mode.h / 2 - window_height / 2;
}
if (set->fullscreen_is_exclusive) {
fullscreen_flag = SDL_WINDOW_FULLSCREEN;
}
Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL;
// we will unhide the window once the GL context is successfully created
Uint32 flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL;
// if fullscreen was requested, start the window in fullscreen right away
if (set->fullscreen) {
@@ -119,28 +143,25 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
}
#endif
wnd = SDL_CreateWindow(set->title, posX, posY, window_width, window_height, flags);
if (!wnd) {
sysFatalError("Could not open SDL window:\n%s", SDL_GetError());
}
// ideally we need 3.0 compat
// if that doesn't work, try 3.2 core in case we're on mac, 2.1 compat as a last resort
static u32 glver[][3] = {
{ 0, 0, 0 }, // for command line override
{ 3, 0, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY },
{ 3, 2, SDL_GL_CONTEXT_PROFILE_CORE },
{ 2, 1, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY },
{ 3, 0, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY }, // 3.0: default, has all the features required
{ 4, 1, SDL_GL_CONTEXT_PROFILE_CORE }, // 4.1core: macs only have core profile and this is the latest
{ 3, 2, SDL_GL_CONTEXT_PROFILE_CORE }, // 3.2core: older macs will only have this at best
{ 3, 0, SDL_GL_CONTEXT_PROFILE_ES }, // es3: don't really support ES properly, but we can try
{ 2, 1, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY }, // 2.1: absolute last resort, will still require GLSL130 as an extension
};
u32 glcore = false;
u32 verstart = 1;
const u32 verend = sizeof(glver) / sizeof(*glver);
const char *verstr = sysArgGetString("--gl-version");
if (verstr && *verstr) {
// user override
glver[0][2] = strstr(verstr, "core") ? SDL_GL_CONTEXT_PROFILE_CORE :
SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
(strstr(verstr, "es") ? SDL_GL_CONTEXT_PROFILE_ES :
SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
sscanf(verstr, "%d.%d", &glver[0][0], &glver[0][1]);
if (glver[0][0] >= 1 && glver[0][0] <= 4 && glver[0][1] < 9) {
verstart = 0;
@@ -148,31 +169,44 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
}
ctx = NULL;
u32 vmin = 0, vmaj = 0;
for (u32 i = verstart; i < verend; ++i) {
u32 vmin = 0, vmaj = 0, vprof = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
const char *vprofstr = "";
for (u32 i = verstart; i < verend && !ctx; ++i) {
vmaj = glver[i][0];
vmin = glver[i][1];
vprof = glver[i][2];
vprofstr = (vprof == SDL_GL_CONTEXT_PROFILE_CORE ? "core" :
(vprof == SDL_GL_CONTEXT_PROFILE_ES ? "es" : ""));
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, vmaj);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, vmin);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, glver[i][2]);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, vprof);
wnd = SDL_CreateWindow(set->title, posX, posY, window_width, window_height, flags);
if (!wnd) {
sysLogPrintf(LOG_WARNING, "SDL: could not open SDL window for GL%d.%d%s:\n%s", vmaj, vmin, vprofstr, SDL_GetError());
continue;
}
ctx = SDL_GL_CreateContext(wnd);
if (!ctx) {
sysLogPrintf(LOG_WARNING, "GL: could not create GL%d.%d context: %s", vmaj, vmin, SDL_GetError());
} else {
glcore = (glver[i][2] == SDL_GL_CONTEXT_PROFILE_CORE);
break;
sysLogPrintf(LOG_WARNING, "SDL: could not create GL%d.%d%s context: %s", vmaj, vmin, vprofstr, SDL_GetError());
SDL_DestroyWindow(wnd);
wnd = nullptr;
}
}
if (!ctx) {
sysFatalError("Could not create an OpenGL context of any supported version.\nSDL error: %s", SDL_GetError());
if (!wnd || !ctx) {
sysFatalError("Could not open SDL window with an OpenGL context of any supported version:\n%s", SDL_GetError());
} else {
sysLogPrintf(LOG_NOTE, "GL: created GL%d.%d%s context", vmaj, vmin, glcore ? "core" : "");
sysLogPrintf(LOG_NOTE, "SDL: created GL%d.%d%s context", vmaj, vmin, vprofstr);
}
SDL_GL_MakeCurrent(wnd, ctx);
SDL_GL_SetSwapInterval(1);
SDL_ShowWindow(wnd);
qpc_freq = SDL_GetPerformanceFrequency();
}
@@ -212,6 +246,43 @@ static void gfx_sdl_set_cursor_visibility(bool visible) {
}
}
static void get_centered_positions_native(int32_t width, int32_t height, int32_t *posX, int32_t *posY) {
const int disp_idx = SDL_GetWindowDisplayIndex(wnd);
SDL_DisplayMode mode = {};
SDL_GetDesktopDisplayMode(disp_idx, &mode);
*posX = mode.w / 2 - width / 2;
*posY = mode.h / 2 - height / 2;
}
static void gfx_sdl_get_centered_positions(int32_t width, int32_t height, int32_t *posX, int32_t *posY) {
const int disp_idx = SDL_GetWindowDisplayIndex(wnd);
SDL_DisplayMode mode = {};
SDL_GetCurrentDisplayMode(disp_idx, &mode);
*posX = mode.w / 2 - width / 2;
*posY = mode.h / 2 - height / 2;
}
static void gfx_sdl_set_closest_resolution(int32_t width, int32_t height, bool should_center) {
const SDL_DisplayMode mode = {.w = width, .h = height};
const int disp_idx = SDL_GetWindowDisplayIndex(wnd);
SDL_DisplayMode closest = {};
if (SDL_GetClosestDisplayMode(disp_idx, &mode, &closest)) {
SDL_SetWindowDisplayMode(wnd, &closest);
SDL_SetWindowSize(wnd, closest.w, closest.h);
if (should_center) {
int32_t posX = 0;
int32_t posY = 0;
get_centered_positions_native(closest.w, closest.h, &posX, &posY);
SDL_SetWindowPosition(wnd, posX, posY);
}
}
}
static void gfx_sdl_set_dimensions(uint32_t width, uint32_t height, int32_t posX, int32_t posY) {
SDL_SetWindowSize(wnd, width, height);
SDL_SetWindowPosition(wnd, posX, posY);
}
static void gfx_sdl_get_dimensions(uint32_t* width, uint32_t* height, int32_t* posX, int32_t* posY) {
SDL_GL_GetDrawableSize(wnd, static_cast<int*>((void*)width), static_cast<int*>((void*)height));
SDL_GetWindowPosition(wnd, static_cast<int*>(posX), static_cast<int*>(posY));
@@ -230,6 +301,9 @@ static void gfx_sdl_handle_events(void) {
case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
SDL_GL_GetDrawableSize(wnd, &window_width, &window_height);
if (!fullscreen_state) {
maximized_state = SDL_GetWindowFlags(wnd) & SDL_WINDOW_MAXIMIZED ? true : false;
}
} else if (event.window.event == SDL_WINDOWEVENT_CLOSE &&
event.window.windowID == SDL_GetWindowID(wnd)) {
// We listen specifically for main window close because closing main window
@@ -294,6 +368,10 @@ static double gfx_sdl_get_time(void) {
return SDL_GetPerformanceCounter() / (double)qpc_freq;
}
static int32_t gfx_sdl_get_target_fps(void) {
return target_fps;
}
static void gfx_sdl_set_target_fps(int fps) {
target_fps = fps;
}
@@ -310,6 +388,10 @@ static void gfx_sdl_set_window_title(const char *title) {
SDL_SetWindowTitle(wnd, title);
}
static int gfx_sdl_get_swap_interval(void) {
return SDL_GL_GetSwapInterval();
}
static bool gfx_sdl_set_swap_interval(int interval) {
const bool success = SDL_GL_SetSwapInterval(interval) >= 0;
vsync_enabled = success && (interval != 0);
@@ -319,24 +401,63 @@ static bool gfx_sdl_set_swap_interval(int interval) {
return success;
}
struct GfxWindowManagerAPI gfx_sdl = {
int gfx_sdl_get_display_mode(int modenum, int *out_w, int *out_h) {
const int display_in_use = SDL_GetWindowDisplayIndex(wnd);
SDL_DisplayMode sdlmode;
if (SDL_GetDisplayMode(display_in_use, modenum, &sdlmode) == 0) {
*out_w = sdlmode.w;
*out_h = sdlmode.h;
return 1;
}
return 0;
}
int gfx_sdl_get_current_display_mode(int *out_w, int *out_h) {
const int display_in_use = SDL_GetWindowDisplayIndex(wnd);
SDL_DisplayMode sdlmode;
if (SDL_GetCurrentDisplayMode(display_in_use, &sdlmode) == 0) {
*out_w = sdlmode.w;
*out_h = sdlmode.h;
return 1;
}
return 0;
}
int gfx_sdl_get_num_display_modes(void) {
const int display_in_use = SDL_GetWindowDisplayIndex(wnd);
return SDL_GetNumDisplayModes(display_in_use);
}
struct GfxWindowManagerAPI gfx_sdl = {
gfx_sdl_init,
gfx_sdl_close,
gfx_sdl_get_display_mode,
gfx_sdl_get_current_display_mode,
gfx_sdl_get_num_display_modes,
gfx_sdl_get_fullscreen_state,
gfx_sdl_set_fullscreen_changed_callback,
gfx_sdl_set_fullscreen,
gfx_sdl_set_fullscreen_exclusive,
gfx_sdl_set_fullscreen_flag,
gfx_sdl_get_fullscreen_flag_mode,
gfx_sdl_get_maximized_state,
gfx_sdl_set_maximize_window,
gfx_sdl_get_active_window_refresh_rate,
gfx_sdl_set_cursor_visibility,
gfx_sdl_set_closest_resolution,
gfx_sdl_set_dimensions,
gfx_sdl_get_dimensions,
gfx_sdl_get_centered_positions,
gfx_sdl_handle_events,
gfx_sdl_start_frame,
gfx_sdl_swap_buffers_begin,
gfx_sdl_swap_buffers_end,
gfx_sdl_get_time,
gfx_sdl_get_target_fps,
gfx_sdl_set_target_fps,
gfx_sdl_can_disable_vsync,
gfx_sdl_get_window_handle,
gfx_sdl_set_window_title,
gfx_sdl_get_swap_interval,
gfx_sdl_set_swap_interval,
};
+13
View File
@@ -13,28 +13,41 @@ struct GfxWindowInitSettings {
bool fullscreen;
bool fullscreen_is_exclusive;
bool maximized;
bool centered;
bool allow_hidpi;
};
struct GfxWindowManagerAPI {
void (*init)(const struct GfxWindowInitSettings *settings);
void (*close)(void);
int (*get_display_mode)(int modenum, int *out_w, int *out_h);
int (*get_current_display_mode)(int *out_w, int *out_h);
int (*get_num_display_modes)(void);
int32_t (*get_fullscreen_state)(void);
void (*set_fullscreen_changed_callback)(void (*on_fullscreen_changed)(bool is_now_fullscreen));
void (*set_fullscreen)(bool enable);
void (*set_fullscreen_exclusive)(bool exc);
void (*set_fullscreen_flag)(int32_t mode);
int32_t (*get_fullscreen_flag_mode)(void);
int32_t (*get_maximized_state)(void);
void (*set_maximize)(bool enable);
void (*get_active_window_refresh_rate)(uint32_t* refresh_rate);
void (*set_cursor_visibility)(bool visible);
void (*set_closest_resolution)(int32_t width, int32_t height, bool should_center);
void (*set_dimensions)(uint32_t width, uint32_t height, int32_t posX, int32_t posY);
void (*get_dimensions)(uint32_t* width, uint32_t* height, int32_t* posX, int32_t* posY);
void (*get_centered_positions)(int32_t width, int32_t height, int32_t *posX, int32_t *posY);
void (*handle_events)(void);
bool (*start_frame)(void);
void (*swap_buffers_begin)(void);
void (*swap_buffers_end)(void);
double (*get_time)(void); // For debug
int32_t (*get_target_fps)(void);
void (*set_target_fps)(int fps);
bool (*can_disable_vsync)(void);
void *(*get_window_handle)(void);
void (*set_window_title)(const char *);
int (*get_swap_interval)(void);
bool (*set_swap_interval)(int);
};
+773 -844
View File
File diff suppressed because it is too large. Load diff
+860 -1492
View File
File diff suppressed because it is too large. Load diff
+2 -1
View File
@@ -19,8 +19,9 @@ s32 fsFileSize(const char *name);
FILE *fsFileOpenWrite(const char *name);
FILE *fsFileOpenRead(const char *name);
void fsFileClose(FILE *f);
void fsFileFree(FILE *f);
const char *fsGetModDir(void);
s32 fsCreateDir(const char *path);
#endif
+128 -61
View File
@@ -17,68 +17,108 @@
#define CONT_NUM_BUTTONS 32 // not including the stick axes
enum virtkey {
/* same order as SDL scancodes */
VK_KEYBOARD_BEGIN = 0,
VK_RETURN = 40,
VK_ESCAPE = 41,
VK_DELETE = 76,
/* same order as SDL scancodes */
VK_KEYBOARD_BEGIN = 0,
VK_A = 4,
VK_Z = 29,
VK_1 = 30,
VK_9 = 38,
VK_0 = 39,
VK_RETURN = 40,
VK_ESCAPE = 41,
VK_BACKSPACE = 42,
VK_SPACE = 44,
VK_MINUS = 45,
VK_LEFTBRACKET = 47,
VK_RIGHTBRACKET = 48,
VK_SEMICOLON = 51,
VK_GRAVE = 53,
VK_COMMA = 54,
VK_PERIOD = 55,
VK_F1 = 58,
VK_F9 = 66,
VK_DELETE = 76,
VK_LCTRL = 224,
VK_LSHIFT = 225,
VK_LALT = 226,
VK_RCTRL = 228,
VK_RSHIFT = 229,
/* same order as SDL mouse buttons */
VK_MOUSE_BEGIN = 512,
VK_MOUSE_LEFT = VK_MOUSE_BEGIN,
VK_MOUSE_MIDDLE,
VK_MOUSE_RIGHT,
VK_MOUSE_X1,
VK_MOUSE_X2,
VK_MOUSE_WHEEL_UP,
VK_MOUSE_WHEEL_DN,
/* same order as SDL mouse buttons */
VK_MOUSE_BEGIN = 512,
VK_MOUSE_LEFT = VK_MOUSE_BEGIN,
VK_MOUSE_MIDDLE,
VK_MOUSE_RIGHT,
VK_MOUSE_X1,
VK_MOUSE_X2,
VK_MOUSE_WHEEL_UP,
VK_MOUSE_WHEEL_DN,
/* same order as SDL gamecontroller buttons plus two buttons for triggers */
VK_JOY_BEGIN,
VK_JOY1_BEGIN = VK_JOY_BEGIN,
VK_JOY1_LTRIG = VK_JOY1_BEGIN + 30,
VK_JOY1_RTRIG = VK_JOY1_BEGIN + 31,
VK_JOY2_BEGIN = VK_JOY1_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
VK_JOY3_BEGIN = VK_JOY2_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
VK_JOY4_BEGIN = VK_JOY3_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
/* same order as SDL gamecontroller buttons plus two buttons for triggers */
VK_JOY_BEGIN,
VK_JOY1_BEGIN = VK_JOY_BEGIN,
VK_JOY1_LSHOULDER = VK_JOY1_BEGIN + 9,
VK_JOY1_RSHOULDER = VK_JOY1_BEGIN + 10,
VK_JOY1_LTRIG = VK_JOY1_BEGIN + 30,
VK_JOY1_RTRIG = VK_JOY1_BEGIN + 31,
VK_JOY2_BEGIN = VK_JOY1_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
VK_JOY3_BEGIN = VK_JOY2_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
VK_JOY4_BEGIN = VK_JOY3_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
VK_TOTAL_COUNT = VK_JOY_BEGIN + INPUT_MAX_CONTROLLERS * INPUT_MAX_CONTROLLER_BUTTONS,
VK_TOTAL_COUNT = VK_JOY_BEGIN + INPUT_MAX_CONTROLLERS * INPUT_MAX_CONTROLLER_BUTTONS,
};
enum keymod {
/* same order as SDL keymods */
KM_LSHIFT = 0x0001,
KM_RSHIFT = 0x0002,
KM_LCTRL = 0x0040,
KM_RCTRL = 0x0080,
KM_CAPS = 0x2000,
KM_CTRL = KM_LCTRL | KM_RCTRL,
KM_SHIFT = KM_LSHIFT | KM_RSHIFT
};
enum contkey {
CK_C_R,
CK_C_L,
CK_C_D,
CK_C_U,
CK_RTRIG,
CK_LTRIG,
CK_X, // gap in CONT_
CK_Y, // gap in CONT_
CK_DPAD_R,
CK_DPAD_L,
CK_DPAD_D,
CK_DPAD_U,
CK_START,
CK_ZTRIG,
CK_B,
CK_A,
CK_STICK_XNEG,
CK_STICK_XPOS,
CK_STICK_YNEG,
CK_STICK_YPOS,
CK_0010,
CK_0020,
CK_0040,
CK_0080,
CK_0100,
CK_0200,
CK_0400,
CK_0800,
CK_1000,
CK_2000,
CK_4000,
CK_8000,
CK_TOTAL_COUNT
CK_C_R,
CK_C_L,
CK_C_D,
CK_C_U,
CK_RTRIG,
CK_LTRIG,
CK_X, // gap in CONT_
CK_Y, // gap in CONT_
CK_DPAD_R,
CK_DPAD_L,
CK_DPAD_D,
CK_DPAD_U,
CK_START,
CK_ZTRIG,
CK_B,
CK_A,
CK_STICK_XNEG,
CK_STICK_XPOS,
CK_STICK_YNEG,
CK_STICK_YPOS,
CK_ACCEPT,
CK_CANCEL,
CK_0040,
CK_0080,
CK_0100,
CK_0200,
CK_0400,
CK_0800,
CK_1000,
CK_2000,
CK_4000,
CK_8000,
CK_TOTAL_COUNT
};
enum mouselockmode {
MLOCK_OFF = 0,
MLOCK_ON = 1,
MLOCK_AUTO = 2
};
// returns bitmask of connected controllers or -1 if failed
@@ -105,6 +145,10 @@ void inputControllerSetSticksSwapped(s32 cidx, s32 swapped);
s32 inputControllerGetDualAnalog(s32 cidx);
void inputControllerSetDualAnalog(s32 cidx, s32 enable);
// get/set Input.Player%d.CancelCButtons
s32 inputControllerGetCancelCButtons(s32 cidx);
void inputControllerSetCancelCButtons(s32 cidx, s32 cancel);
// get/set sensitivity for a given player
f32 inputControllerGetAxisScale(s32 cidx, s32 stick, s32 axis);
void inputControllerSetAxisScale(s32 cidx, s32 stick, s32 axis, f32 value);
@@ -132,6 +176,7 @@ s32 inputAssignController(s32 cidx, s32 id);
// vk is a value from the virtkey enum above
s32 inputKeyPressed(u32 vk);
s32 inputKeyJustPressed(u32 vk);
// idx is controller index, contbtn is one of the CONT_ constants
s32 inputButtonPressed(s32 idx, u32 contbtn);
@@ -166,8 +211,9 @@ void inputLockMouse(s32 lock);
// returns the current state of the above
s32 inputMouseIsLocked(void);
// returns mouse position in native viewport coordinates (ie, 320x240 most of the time)
void inputMouseGetPosition(s32 *x, s32 *y);
// sets x, y to mouse position in native viewport coordinates (ie, 320x240 most of the time)
// returns true if mouse has moved this input frame
s32 inputMouseGetPosition(s32 *x, s32 *y);
// returns changes in mouse position since last frame, in window coordinates
void inputMouseGetRawDelta(s32 *dx, s32 *dy);
@@ -199,8 +245,29 @@ void inputSetDefaultKeyBinds(s32 cidx, s32 n64mode);
void inputClearLastKey(void);
s32 inputGetLastKey(void);
// get/set Input.MouseDefaultLocked
s32 inputGetMouseDefaultLocked(void);
void inputSetMouseDefaultLocked(s32 defaultLocked);
// get/set Input.MouseLockMode
s32 inputGetMouseLockMode(void);
void inputSetMouseLockMode(s32 lockmode);
// same as inputLockMouse but works only if mouse is enabled and lockmode == MLOCK_AUTO
s32 inputAutoLockMouse(s32 wantlock);
// show/hide mouse cursor; if mouse lock is on the cursor is always hidden
void inputMouseShowCursor(s32 show);
void inputStartTextInput(void);
void inputStopTextInput(void);
s32 inputIsTextInputActive(void);
void inputClearLastTextChar(void);
char inputGetLastTextChar(void);
s32 inputTextHandler(char *out, const u32 outSize, s32 *curCol, s32 oskCharsOnly);
void inputClearClipboard(void);
const char *inputGetClipboard(void);
// returns keymod values
u32 inputGetKeyModState(void);
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef _IN_MPSETUPS_H
#define _IN_MPSETUPS_H
#include "types.h"
s32 mpsetupLoadCurrentFile(void);
s32 mpsetupSaveCurrentFile(void);
void mpsetupLoadSetup(s32 slotindex);
s32 mpsetupSaveSetup(s32 slotindex, u8 savefile);
void mpsetupCopyAllFromPak(void);
#endif
+20 -22
View File
@@ -3,32 +3,30 @@
#include <PR/ultratypes.h>
typedef void (*preprocessfunc)(u8 *data, u32 size);
typedef u8 *(*preprocessfunc)(u8 *data, u32 size, u32 *outSize);
void preprocessAnimations(u8 *data, u32 size);
void preprocessMpConfigs(u8 *data, u32 size);
void preprocessFont(u8 *data, u32 size);
void preprocessJpnFont(u8 *data, u32 size);
void preprocessALBankFile(u8 *data, u32 size);
void preprocessALCMidiHdr(u8 *data, u32 size);
void preprocessSequences(u8 *data, u32 size);
void preprocessFiringRange(u8 *data, u32 size);
void preprocessTexturesList(u8 *data, u32 size);
u8* preprocessAnimations(u8 *data, u32 size, u32 *outSize);
u8* preprocessMpConfigs(u8 *data, u32 size, u32 *outSize);
u8* preprocessFont(u8 *data, u32 size, u32 *outSize);
u8* preprocessJpnFont(u8 *data, u32 size, u32 *outSize);
u8* preprocessALBankFile(u8 *data, u32 size, u32 *outSize);
u8 *preprocessALCMidiHdr(u8 *data, u32 size, u32 *outSize);
u8* preprocessSequences(u8 *data, u32 size, u32 *outSize);
u8* preprocessTexturesList(u8 *data, u32 size, u32 *outSize);
void preprocessBgSection1Header(u8 *data, u32 size);
void preprocessBgSection1(u8 *data, u32 size);
void preprocessBgSection2Header(u8 *data, u32 size);
void preprocessBgSection1(u8* data, u32 size, u32 ofs);
void preprocessBgSection2(u8 *data, u32 size);
void preprocessBgSection3(u8* data, u32 size);
void preprocessBgSection1Header(u8 *data, u32 size);
void preprocessBgSection2Header(u8 *data, u32 size);
void preprocessBgSection3Header(u8 *data, u32 size);
void preprocessBgSection3(u8 *data, u32 size);
void preprocessBgRoom(u8 *data, u32 ofs);
void preprocessBgLights(u8 *data, u32 ofs);
u32 preprocessBgRoom(u8* data, u32 size, u32 room_ofs);
void preprocessLangFile(u8 *data, u32 size);
void preprocessPadsFile(u8 *data, u32 size);
void preprocessTilesFile(u8 *data, u32 size);
void preprocessSetupFile(u8 *data, u32 size);
void preprocessModelFile(u8 *data, u32 size);
void preprocessGunFile(u8 *data, u32 size);
u8 *preprocessLangFile(u8 *data, u32 size, u32 *outSize);
u8 *preprocessPadsFile(u8 *data, u32 size, u32 *outSize);
u8 *preprocessTilesFile(u8 *data, u32 size, u32 *outSize);
u8 *preprocessSetupFile(u8 *data, u32 size, u32 *outSize);
u8 *preprocessModelFile(u8 *data, u32 size, u32 *outSize);
u8 *preprocessGunFile(u8 *data, u32 size, u32 *outSize);
#endif
+59
View File
@@ -0,0 +1,59 @@
#ifndef _IN_PREPROCESS_COMMON_H
#define _IN_PREPROCESS_COMMON_H
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <PR/ultratypes.h>
#include "types.h"
#include "constants.h"
#include "platform.h"
#include "system.h"
#include "romdata.h"
#include "preprocess.h"
#define MAX_PTR_MARKERS (1024 * 8)
#define PD_ALIGN(val, size) (((val) + ((size) - 1)) & ~((size) - 1))
#define PD_PTR_BASE(x, b) (void *)((u8 *)b + (uintptr_t)x)
#define PD_PTR_BASEOFS(x, b, d) (void *)((u8 *)b - d + (uintptr_t)x)
static inline f32 swapF32(f32 x) { *(u32*)&x = PD_BE32(*(u32*)&x); return x; }
static inline u32 swapU32(u32 x) { return PD_BE32(x); }
static inline s32 swapS32(s32 x) { return PD_BE32(x); }
static inline u16 swapU16(u16 x) { return PD_BE16(x); }
static inline s16 swapS16(s16 x) { return PD_BE16(x); }
static inline void* swapPtr(void** x) { return (void*)PD_BEPTR((uintptr_t)x); }
static inline struct coord swapCrd(struct coord crd) { crd.x = swapF32(crd.x); crd.y = swapF32(crd.y); crd.z = swapF32(crd.z); return crd; }
static inline u32 swapUnk(u32 x) { assert(0 && "unknown type"); return x; }
#define PD_SWAPPED_VAL(x) _Generic((x), \
f32: swapF32, \
u32: swapU32, \
s32: swapS32, \
u16: swapU16, \
s16: swapS16, \
struct coord: swapCrd, \
default: swapUnk \
)(x)
#define PD_SWAP_VAL(x) x = PD_SWAPPED_VAL(x)
#define PD_SWAP_PTR(x) x = swapPtr((void *)(x))
// ptr marker functions
struct ptrmarker {
u32 ptr_src;
uintptr_t ptr_host;
};
void ptrAdd(u32 ptr_src, uintptr_t ptr_host);
struct ptrmarker* ptrFind(uintptr_t ptr_src);
void ptrReset(void);
#endif
+15
View File
@@ -0,0 +1,15 @@
#ifndef _IN_PREPROCESS_GBI_H
#define _IN_PREPROCESS_GBI_H
#include "preprocess/common.h"
// gbi related functions
void gbiReset(void);
void gbiSetSegment(int segment, u32 offset);
void gbiSetVtx(u32 src_offset, u32 dst_offset);
u32 gbiConvertGdl(u8 *dst, u32 dstpos, u8 *src, u32 srcpos, int segment_cmds);
void gbiConvertVtx(u8* dst, u32 dstpos, int count);
void gbiGdlRewriteAddrs(u8* dst, u32 offset);
void gbiAddTexAddr(u32 src_offset, u32 dst_offset);
#endif
+640
View File
@@ -0,0 +1,640 @@
#ifndef _IN_SETUP_DECL
#define _IN_SETUP_DECL
#include "preprocess/common.h"
struct n64_stagesetup {
u32 ptr_waypoints;
u32 ptr_waygroups;
u32 ptr_cover;
u32 ptr_intro;
u32 ptr_props;
u32 ptr_paths;
u32 ptr_ailists;
u32 ptr_padfiledata;
};
struct n64_coord {
f32 x;
f32 y;
f32 z;
};
struct n64_defaultobj {
u16 extrascale;
u8 hidden2;
u8 type;
s16 modelnum;
s16 pad;
u32 flags;
u32 flags2;
u32 flags3;
u32 ptr_prop;
u32 ptr_model;
f32 realrot[3][3];
u32 hidden;
union {
u32 ptr_geotilef;
u32 ptr_geoblock;
u32 ptr_geocyl;
u32 ptr_unkgeo;
};
union {
u32 ptr_projectile;
u32 ptr_embedment;
};
s16 damage;
s16 maxdamage;
u8 shadecol[4];
u8 nextcol[4];
u16 floorcol;
s8 geocount;
s8 _pad_;
};
struct n64_doorobj {
struct n64_defaultobj base;
f32 maxfrac;
f32 perimfrac;
f32 accel;
f32 decel;
f32 maxspeed;
u16 doorflags;
u16 doortype;
u32 keyflags;
s32 autoclosetime;
f32 frac;
f32 fracspeed;
s8 mode;
s8 glasshits;
s16 fadealpha;
s16 xludist;
s16 opadist;
struct n64_coord startpos;
f32 mtx98[3][3];
u32 ptr_sibling;
s32 lastopen60;
s16 portalnum;
s8 soundtype;
s8 fadetime60;
s32 lastcalc60;
u8 laserfade;
u8 unusedmaybe[3];
u8 shadeinfo1[4];
u8 shadeinfo2[4];
u8 actual1;
u8 actual2;
u8 extra1;
u8 extra2;
};
struct n64_doorscaleobj {
u32 unk00;
s32 scale;
};
struct n64_keyobj {
struct n64_defaultobj base;
u32 keyflags;
};
struct n64_alarmobj {
struct n64_defaultobj base;
};
struct n64_cctvobj {
struct n64_defaultobj base;
s16 lookatpadnum;
s16 toleft;
//Mtxf camrotm;
f32 m[4][4];
f32 yzero;
f32 yrot;
f32 yleft;
f32 yright;
f32 yspeed;
f32 ymaxspeed;
s32 seebondtime60;
f32 maxdist;
f32 xzero;
};
struct n64_ammocrateobj {
struct n64_defaultobj base;
s32 ammotype;
};
struct n64_gset {
u8 weaponnum;
u8 unk0639;
u8 unk063a;
u8 weaponfunc;
};
struct n64_weaponobj {
struct n64_defaultobj base;
union {
struct n64_gset gset;
struct {
u8 weaponnum;
s8 unk5d;
s8 unk5e;
u8 gunfunc;
};
};
s8 fadeouttimer60;
s8 dualweaponnum;
union {
s16 timer240;
s16 team;
};
u32 ptr_dualweapon;
};
struct n64_packedchr {
s16 chrindex;
s8 unk02;
s8 typenum;
u32 spawnflags;
s16 chrnum;
u16 padnum;
u8 bodynum;
s8 headnum;
u16 ailistnum;
u16 padpreset;
u16 chrpreset;
u16 hearscale;
u16 viewdist;
u32 flags;
u32 flags2;
u8 team;
u8 squadron;
s16 chair;
u32 convtalk;
u8 tude;
u8 naturalanim;
u8 yvisang;
u8 teamscandist;
};
struct n64_tvscreen {
u32 ptr_cmdlist;
u16 offset;
s16 pause60;
u32 ptr_tconfig;
f32 rot;
f32 xscale;
f32 xscalefrac;
f32 xscaleinc;
f32 xscaleold;
f32 xscalenew;
f32 yscale;
f32 yscalefrac;
f32 yscaleinc;
f32 yscaleold;
f32 yscalenew;
f32 xmid;
f32 xmidfrac;
f32 xmidinc;
f32 xmidold;
f32 xmidnew;
f32 ymid;
f32 ymidfrac;
f32 ymidinc;
f32 ymidold;
f32 ymidnew;
u8 red;
u8 redold;
u8 rednew;
u8 green;
u8 greenold;
u8 greennew;
u8 blue;
u8 blueold;
u8 bluenew;
u8 alpha;
u8 alphaold;
u8 alphanew;
f32 colfrac;
f32 colinc;
};
struct n64_singlemonitorobj {
struct n64_defaultobj base;
struct n64_tvscreen screen;
s16 owneroffset;
s8 ownerpart;
u8 imagenum;
};
struct n64_multimonitorobj {
struct n64_defaultobj base;
struct n64_tvscreen screens[4];
u8 imagenums[4];
};
struct n64_hangingmonitorsobj {
struct n64_defaultobj base;
};
struct n64_autogunobj {
struct n64_defaultobj base;
s16 targetpad;
s8 firing;
u8 firecount;
f32 yzero;
f32 ymaxleft;
f32 ymaxright;
f32 yrot;
f32 yspeed;
f32 xzero;
f32 xrot;
f32 xspeed;
f32 maxspeed;
f32 aimdist;
f32 barrelspeed;
f32 barrelrot;
s32 lastseebond60;
s32 lastaimbond60;
s32 allowsoundframe;
u32 ptr_beam;
f32 shotbondsum;
u32 ptr_target;
u8 targetteam;
u8 ammoquantity;
s16 nextchrtest;
};
struct n64_linkgunsobj {
u32 unk00;
s16 offset1;
s16 offset2;
};
struct n64_debrisobj {
struct n64_defaultobj base;
};
struct n64_hatobj {
struct n64_defaultobj base;
};
struct n64_grenadeprobobj { // objtype 0x12
u32 unk00;
s16 chrnum;
u16 probability;
};
struct n64_linkliftdoorobj {
u32 unk00;
u32 ptr_door;
u32 ptr_lift;
u32 ptr_next;
s32 stopnum;
};
struct n64_multiammocrateslot {
u16 modelnum;
u16 quantity;
};
struct n64_multiammocrateobj {
struct n64_defaultobj base;
struct n64_multiammocrateslot slots[19];
};
struct n64_shieldobj {
struct n64_defaultobj base;
f32 initialamount;
f32 amount;
u32 unk64;
};
struct n64_tag {
u32 identifier;
u16 tagnum;
s16 cmdoffset;
u32 ptr_next;
u32 ptr_obj;
};
struct n64_objective {
u32 unk00;
s32 index;
u32 text;
u16 unk0c;
u8 flags;
s8 difficulties;
};
struct n64_stdobjective {
u32 cmd;
};
struct n64_objectivecmd {
u8 cmd0[4];
u32 cmd1;
};
struct n64_briefingobj {
u32 unk00;
u32 type;
u32 text;
u32 ptr_next;
};
struct n64_padlockeddoorobj {
u32 unk00;
u32 ptr_door;
u32 ptr_lock;
u32 ptr_next;
};
struct n64_truckobj {
struct n64_defaultobj base;
u32 ptr_ailist;
u16 aioffset;
s16 aireturnlist;
f32 speed;
f32 wheelxrot;
f32 wheelyrot;
f32 speedaim;
f32 speedtime60;
f32 turnrot60;
f32 roty;
u32 ptr_path;
s32 nextstep;
};
struct n64_tankobj {
u8 _pad_[128];
};
struct n64_heliobj {
struct n64_defaultobj base;
u32 ptr_ailist;
u16 aioffset;
s16 aireturnlist;
f32 rotoryrot;
f32 rotoryspeed;
f32 rotoryspeedaim;
f32 rotoryspeedtime;
f32 speed;
f32 speedaim;
f32 speedtime60;
f32 yrot;
u32 ptr_path;
s32 nextstep;
};
struct n64_glassobj {
struct n64_defaultobj base;
s16 portalnum;
s16 _pad_;
};
struct n64_safeobj {
struct n64_defaultobj base;
};
struct n64_safeitemobj {
u32 unk00;
u32 ptr_item;
u32 ptr_safe;
u32 ptr_door;
u32 ptr_next;
};
struct n64_cameraposobj {
s32 type;
f32 x;
f32 y;
f32 z;
f32 theta;
f32 verta;
s32 pad;
};
struct n64_tintedglassobj {
struct n64_defaultobj base;
s16 xludist;
s16 opadist;
s16 opacity;
s16 portalnum;
f32 unk64;
};
struct n64_liftobj {
struct n64_defaultobj base;
s16 pads[4];
u32 ptr_doors[4];
f32 dist;
f32 speed;
f32 accel;
f32 maxspeed;
s8 soundtype;
s8 levelcur;
s8 levelaim;
s8 _pad_;
struct n64_coord prevpos;
};
struct n64_linksceneryobj {
u32 unk00;
u32 ptr_trigger;
u32 ptr_unexp;
u32 ptr_exp;
u32 ptr_next;
};
struct n64_blockedpathobj {
u32 unk00;
u32 ptr_blocker;
s16 waypoint1;
s16 waypoint2;
u32 ptr_next;
};
struct n64_hov {
u8 type;
u8 flags;
s16 _pad_;
f32 bobycur;
f32 bobytarget;
f32 bobyspeed;
f32 yrot;
f32 bobpitchcur;
f32 bobpitchtarget;
f32 bobpitchspeed;
f32 bobrollcur;
f32 bobrolltarget;
f32 bobrollspeed;
f32 groundpitch;
f32 y;
f32 ground;
s32 prevframe60;
s32 prevgroundframe60;
};
struct n64_hoverbikeobj {
struct n64_defaultobj base;
struct n64_hov hov;
f32 speed[2];
f32 prevpos[2];
f32 w;
f32 rels[2];
f32 exreal;
f32 ezreal;
f32 ezreal2;
f32 leanspeed;
f32 leandiff;
s32 maxspeedtime240;
f32 speedabs[2];
f32 speedrel[2];
};
struct n64_hoverpropobj {
struct n64_defaultobj base;
struct n64_hov hov;
};
struct n64_fanobj {
struct n64_defaultobj base;
f32 yrot;
f32 yrotprev;
f32 ymaxspeed;
f32 yspeed;
f32 yaccel;
s8 on;
u8 _pad_[3];
};
struct n64_hovercarobj {
struct n64_defaultobj base;
u32 ptr_ailist;
u16 aioffset;
s16 aireturnlist;
f32 speed;
f32 speedaim;
f32 speedtime60;
f32 turnyspeed60;
f32 turnxspeed60;
f32 turnrot60;
f32 roty;
f32 rotx;
f32 rotz;
u32 ptr_path;
s32 nextstep;
s16 status;
s16 dead;
s16 deadtimer60;
s16 sparkstimer60;
};
struct n64_chopperobj {
struct n64_defaultobj base;
u32 ptr_ailist;
u16 aioffset;
s16 aireturnlist;
union {
struct {
f32 speed;
f32 speedaim;
f32 speedtime60;
};
struct n64_coord fall;
};
f32 turnyspeed60;
f32 turnxspeed60;
f32 turnrot60;
f32 roty;
f32 rotx;
f32 rotz;
u32 ptr_path;
s32 nextstep;//
s16 weaponsarmed;
s16 ontarget;
s16 target;
u8 attackmode;
u8 cw;
f32 vx;
f32 vy;
f32 vz;
f32 power;
f32 otx;
f32 oty;
f32 otz;
f32 bob;
f32 bobstrength;
s32 targetvisible;
s32 timer60;
s32 patroltimer60;
f32 gunturnyspeed60;
f32 gunturnxspeed60;
f32 gunroty;
f32 gunrotx;
f32 barrelrotspeed;
f32 barrelrot;
u32 ptr_fireslotthing;
s32 dead;
};
struct n64_escalatorobj {
struct n64_defaultobj base;
s32 frame;
struct n64_coord prevpos;
};
struct n64_textoverride {
u32 unk00;
s32 objoffset;
s32 weapon;
u32 obtaintext;
u32 ownertext;
u32 inventorytext;
u32 inventory2text;
u32 pickuptext;
u32 ptr_next;
u32 ptr_obj;
};
struct n64_criteria_roomentered {
u32 unk00;
u32 pad;
u32 status;
u32 ptr_next;
};
struct n64_criteria_throwinroom {
u32 unk00;
u32 unk04;
u32 pad;
u32 status;
u32 ptr_next;
};
struct n64_criteria_holograph {
u32 unk00;
u32 obj;
u32 status;
u32 ptr_next;
};
struct n64_ailist {
u32 ptr_list;
s32 id;
};
struct n64_path {
u32 ptr_pads;
u8 id;
u8 flags;
u16 len;
};
#endif
+4 -1
View File
@@ -9,7 +9,7 @@ extern u32 g_RomFileSize;
s32 romdataInit(void);
u8 *romdataFileLoad(s32 fileNum, u32 *outSize);
void romdataFilePreprocess(s32 fileNum, s32 loadType, u8 *data, u32 size);
void romdataFilePreprocess(s32 fileNum, s32 loadType, u8 *data, u32 size, u32 *outSize);
void romdataFileFree(s32 fileNum);
const char *romdataFileGetName(s32 fileNum);
@@ -21,5 +21,8 @@ s32 romdataFileGetNumForName(const char *name);
u8 *romdataSegGetData(const char *segName);
u8 *romdataSegGetDataEnd(const char *segName);
u32 romdataSegGetSize(const char *segName);
u32 romdataFileGetEstimatedSize(const u32 size, const u32 loadtype);
s32 romdataCheckGbcRom(void);
#endif
+1
View File
@@ -32,6 +32,7 @@ void sysGetHomePath(char *outPath, const u32 outLen);
void *sysMemAlloc(const u32 size);
void *sysMemZeroAlloc(const u32 size);
void *sysMemRealloc(void *ptr, const u32 newSize);
void sysMemFree(void *ptr);
// hns is specified in 100ns units
+11
View File
@@ -0,0 +1,11 @@
#ifndef _IN_VERSIONINFO_H
#define _IN_VERSIONINFO_H
#define VERSION_TARGET "@VERSION_TARGET@"
#define VERSION_ARCH "@VERSION_ARCH@"
#define VERSION_ROMID "@VERSION_ROMID@"
#define VERSION_BUILD "@VERSION_BUILD@"
#define VERSION_HASH "@VERSION_HASH@"
#define VERSION_BRANCH "@VERSION_BRANCH@"
#endif
+33
View File
@@ -11,6 +11,11 @@
#define VIDEO_MAX_FPS 240
#endif
typedef struct {
s32 width;
s32 height;
} displaymode;
s32 videoInit(void);
void videoStartFrame(void);
void videoSubmitCommands(Gfx *cmds);
@@ -27,17 +32,42 @@ s32 videoGetWidth(void);
s32 videoGetHeight(void);
f32 videoGetAspect(void);
s32 videoGetFullscreen(void);
s32 videoGetFullscreenMode(void);
s32 videoGetMaximizeWindow(void);
void videoSetMaximizeWindow(s32 fs);
s32 videoGetCenterWindow(void);
void videoSetCenterWindow(s32 center);
u32 videoGetTextureFilter(void);
s32 videoGetTextureFilter2D(void);
u32 videoGetAnisotropicFilter(void);
u32 videoGetMaxAnisotropyLevel(void);
s32 videoGetDetailTextures(void);
s32 videoGetDisplayModeIndex(void);
s32 videoGetDisplayMode(displaymode *out, const s32 index);
s32 videoGetNumDisplayModes(void);
s32 videoGetVsync(void);
s32 videoGetFramerateLimit(void);
s32 videoGetDisplayFPS(void);
s32 videoGetMSAA(void);
f32 videoGetGlareBrightness(void);
f32 videoGetOverexposureScale(void);
f32 videoGetAverageFPS(void);
void videoSetWindowOffset(s32 x, s32 y);
void videoSetFullscreen(s32 fs);
void videoSetFullscreenMode(s32 mode);
void videoSetTextureFilter(u32 filter);
void videoSetTextureFilter2D(s32 filter);
void videoSetAnisotropicFilter(u32 filter);
void videoSetDetailTextures(s32 detail);
void videoSetDisplayMode(const s32 index);
void videoSetVsync(const s32 vsync);
void videoSetFramerateLimit(const s32 limit);
void videoSetDisplayFPS(const s32 displayfps);
void videoSetMSAA(const s32 msaa);
void videoSetGlareBrightness(f32 bright);
void videoSetOverexposureScale(f32 scale);
s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize);
void videoSetFramebuffer(s32 target);
@@ -48,5 +78,8 @@ s32 videoFramebuffersSupported(void);
void videoResetTextureCache(void);
void videoFreeCachedTexture(const void *texptr);
void videoFreeCachedTextures(const void *start, const void *end);
void videoShutdown(void);
#endif
+9 -4
View File
@@ -10,7 +10,7 @@
#define CONFIG_MAX_SECNAME 128
#define CONFIG_MAX_KEYNAME 256
#define CONFIG_MAX_SETTINGS 256
#define CONFIG_MAX_SETTINGS 300
typedef enum {
CFG_NONE,
@@ -34,6 +34,7 @@ struct configentry {
} settings[CONFIG_MAX_SETTINGS];
static s32 numSettings = 0;
static u8 configMaxWarningLogged = 0;
static inline s32 configClampInt(s32 val, s32 min, s32 max)
{
@@ -64,11 +65,15 @@ static inline struct configentry *configAddEntry(const char *key)
{
if (numSettings < CONFIG_MAX_SETTINGS) {
struct configentry *cfg = &settings[numSettings++];
strncpy(cfg->key, key, CONFIG_MAX_KEYNAME);
snprintf(cfg->key, CONFIG_MAX_KEYNAME, "%s", key);
const char *delim = strrchr(cfg->key, '.');
cfg->seclen = delim ? (delim - cfg->key) : 0;
return cfg;
}
if (!configMaxWarningLogged) {
sysLogPrintf(LOG_WARNING, "Maximum number of configuration entries exceeded: %d", CONFIG_MAX_SETTINGS);
configMaxWarningLogged = 1;
}
return NULL;
}
@@ -228,7 +233,7 @@ s32 configSave(const char *fname)
configSaveEntry(cfg, f);
}
fsFileClose(f);
fsFileFree(f);
return 1;
}
@@ -282,7 +287,7 @@ s32 configLoad(const char *fname)
}
}
fsFileClose(f);
fsFileFree(f);
return 1;
}
+15 -3
View File
@@ -11,6 +11,9 @@
#include "platform.h"
#include "utils.h"
#include "fs.h"
#ifdef PLATFORM_WIN32
#include <direct.h>
#endif
#define DEFAULT_BASEDIR_NAME "data"
@@ -111,7 +114,7 @@ s32 fsInit(void)
if (!portable) {
if (fsFileSize("./" DEFAULT_BASEDIR_NAME) >= 0) {
path = "./" DEFAULT_BASEDIR_NAME;
} else if (fsFileSize("$H/" DEFAULT_BASEDIR_NAME)) {
} else if (fsFileSize("$H/" DEFAULT_BASEDIR_NAME) >= 0) {
path = "$H/" DEFAULT_BASEDIR_NAME;
}
}
@@ -149,7 +152,7 @@ s32 fsInit(void)
if (portable) {
path = "$E";
} else {
#ifdef PLATFORM_LINUX
#if defined(PLATFORM_LINUX) || defined(PLATFORM_OSX)
// check if there's a config in the working directory, otherwise default to homeDir
if (fsFileSize("./" CONFIG_FNAME) >= 0) {
path = ".";
@@ -276,7 +279,16 @@ FILE *fsFileOpenRead(const char *name)
return fopen(fsFullPath(name), "rb");
}
void fsFileClose(FILE *f)
void fsFileFree(FILE *f)
{
fclose(f);
}
s32 fsCreateDir(const char *path)
{
#ifdef PLATFORM_WIN32
return _mkdir(fsFullPath(path));
#else
return mkdir(fsFullPath(path), 0777);
#endif
}
+310 -45
View File
@@ -28,6 +28,9 @@
#define WHEEL_UP_MASK SDL_BUTTON(VK_MOUSE_WHEEL_UP - VK_MOUSE_BEGIN + 1)
#define WHEEL_DN_MASK SDL_BUTTON(VK_MOUSE_WHEEL_DN - VK_MOUSE_BEGIN + 1)
#define CURSOR_HIDE_THRESHOLD 1
#define CURSOR_HIDE_TIME 3000000 // us
static SDL_GameController *pads[INPUT_MAX_CONTROLLERS];
#define CONTROLLERCFG_DEFAULT { \
@@ -41,7 +44,8 @@ static SDL_GameController *pads[INPUT_MAX_CONTROLLERS];
.deadzone = { DEFAULT_DEADZONE, DEFAULT_DEADZONE, DEFAULT_DEADZONE, DEFAULT_DEADZONE_RY }, \
.stickCButtons = 0, \
.swapSticks = 1, \
.deviceIndex = -1 \
.deviceIndex = -1, \
.cancelCButtons = 0, \
}
static struct controllercfg {
@@ -53,6 +57,7 @@ static struct controllercfg {
s32 stickCButtons;
s32 swapSticks;
s32 deviceIndex;
s32 cancelCButtons;
} padsCfg[INPUT_MAX_CONTROLLERS] = {
CONTROLLERCFG_DEFAULT,
CONTROLLERCFG_DEFAULT,
@@ -69,18 +74,28 @@ static s32 connectedMask = 0;
static s32 numJoysticks = 0;
static s32 useHIDAPI = 1;
static s32 useRawInput = 0;
static s32 mouseEnabled = 1;
static s32 mouseLocked = 0;
static s32 mouseDefaultLocked = 0;
static s32 mouseX, mouseY;
static s32 mouseDX, mouseDY;
static u32 mouseButtons;
static s32 mouseWheel = 0;
static f32 mouseSensX = 1.5f;
static f32 mouseSensY = 1.5f;
static s32 mouseLocked = 0;
static s32 mouseLockMode = MLOCK_AUTO;
static u64 mouseCursorTime = 0;
static s32 mouseShowCursor = 1;
static f32 mouseSensX = 2.5f;
static f32 mouseSensY = 2.5f;
static s32 lastKey = 0;
static char lastChar = 0;
static s32 textInput = 0;
static char *clipboardText = NULL;
static const char *ckNames[CK_TOTAL_COUNT] = {
"R_CBUTTONS",
@@ -103,8 +118,8 @@ static const char *ckNames[CK_TOTAL_COUNT] = {
"STICK_XPOS",
"STICK_YNEG",
"STICK_YPOS",
"CK_0010",
"CK_0020",
"ACCEPT_BUTTON",
"CANCEL_BUTTON",
"CK_0040",
"CK_0080",
"CK_0100",
@@ -169,6 +184,8 @@ static const char *vkJoyNames[] = {
static char vkNames[VK_TOTAL_COUNT][64];
static s8 vkPrevState[VK_TOTAL_COUNT];
void inputSetDefaultKeyBinds(s32 cidx, s32 n64mode)
{
// TODO: make VK constants for all these
@@ -178,7 +195,7 @@ void inputSetDefaultKeyBinds(s32 cidx, s32 n64mode)
{ CK_RTRIG, VK_MOUSE_RIGHT, SDL_SCANCODE_Z },
{ CK_LTRIG, SDL_SCANCODE_F, SDL_SCANCODE_X },
{ CK_ZTRIG, VK_MOUSE_LEFT, SDL_SCANCODE_SPACE },
{ CK_START, SDL_SCANCODE_RETURN, SDL_SCANCODE_TAB },
{ CK_START, SDL_SCANCODE_TAB, 0 },
{ CK_DPAD_D, SDL_SCANCODE_Q, VK_MOUSE_MIDDLE },
{ CK_DPAD_U, 0, 0 },
{ CK_Y, VK_MOUSE_WHEEL_DN, 0 },
@@ -192,7 +209,9 @@ void inputSetDefaultKeyBinds(s32 cidx, s32 n64mode)
{ CK_STICK_YNEG, SDL_SCANCODE_DOWN, 0 },
{ CK_STICK_YPOS, SDL_SCANCODE_UP, 0 },
{ CK_4000, SDL_SCANCODE_LSHIFT, 0 },
{ CK_2000, SDL_SCANCODE_LCTRL, 0 }
{ CK_2000, SDL_SCANCODE_LCTRL, 0 },
{ CK_ACCEPT, SDL_SCANCODE_RETURN, SDL_SCANCODE_E },
{ CK_CANCEL, VK_MOUSE_RIGHT, 0 },
};
static const u32 pcjoybinds[][2] = {
@@ -209,6 +228,8 @@ void inputSetDefaultKeyBinds(s32 cidx, s32 n64mode)
{ CK_C_U, SDL_CONTROLLER_BUTTON_DPAD_UP },
{ CK_C_R, SDL_CONTROLLER_BUTTON_DPAD_RIGHT },
{ CK_C_L, SDL_CONTROLLER_BUTTON_DPAD_LEFT },
{ CK_ACCEPT, SDL_CONTROLLER_BUTTON_A },
{ CK_CANCEL, SDL_CONTROLLER_BUTTON_B },
{ CK_8000, SDL_CONTROLLER_BUTTON_LEFTSTICK },
};
@@ -319,6 +340,14 @@ static inline void inputInitController(const s32 cidx, const s32 jidx)
sysLogPrintf(LOG_NOTE, "input: assigned controller '%d: (%s)' (id %d) to player %d",
jidx, SDL_GameControllerName(pads[cidx]), inputControllerGetId(pads[cidx]), cidx);
SDL_Joystick* joy = SDL_GameControllerGetJoystick(pads[cidx]);
if (joy) {
char guidStr[1024] = "";
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy);
SDL_JoystickGetGUIDString(guid, guidStr, sizeof(guidStr));
sysLogPrintf(LOG_NOTE, "input: GUID for controller %d: %s", jidx, guidStr);
}
}
static inline void inputCloseController(const s32 cidx)
@@ -512,6 +541,12 @@ static int inputEventFilter(void *data, SDL_Event *event)
}
break;
case SDL_TEXTINPUT:
if (!lastChar && event->text.text[0] && (u8)event->text.text[0] < 0x80) {
lastChar = event->text.text[0];
}
break;
default:
break;
}
@@ -644,6 +679,47 @@ static inline void inputLoadBinds(void)
s32 inputInit(void)
{
// Set SDL hints before initializing the controller subsystem.
if (useHIDAPI) {
#if SDL_VERSION_ATLEAST(2, 0, 12)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 0, 14)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 0, 22)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1");
// the two hints below enable Rumble and Motion Sensor for PS4/5 pads connected via bluetooth
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAM, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 23, 2)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 25, 1)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS3, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 26, 0)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 30, 0)
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, "1");
#endif
}
if (useRawInput) {
SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "1");
#ifdef SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT
SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT, "1");
#elif defined(SDL_HINT_JOYSTICK_HIDAPI_CORRELATE_XINPUT)
// old name for SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT before SDL2.0.16
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_CORRELATE_XINPUT, "1");
#endif
}
if (!SDL_WasInit(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC)) {
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC);
}
@@ -668,7 +744,9 @@ s32 inputInit(void)
inputSetDefaultKeyBinds(i, 0);
}
inputLockMouse(mouseDefaultLocked);
if (mouseLockMode != MLOCK_AUTO) {
inputLockMouse(mouseLockMode);
}
// update the axis maps
// NOTE: by default sticks get swapped for 1.2: "right stick" here means left stick on your controller
@@ -678,6 +756,9 @@ s32 inputInit(void)
inputLoadBinds();
// Explicitly stop text input to prevent key events being swallowed on certain Wayland systems
inputStopTextInput();
return connectedMask;
}
@@ -719,6 +800,14 @@ s32 inputReadController(s32 idx, OSContPad *npad)
npad->button = 0;
if (textInput) {
npad->stick_x = 0;
npad->stick_y = 0;
npad->rstick_x = 0;
npad->rstick_y = 0;
return 0;
}
for (u32 i = 0; i < CONT_NUM_BUTTONS; ++i) {
if (inputBindPressed(idx, i)) {
npad->button |= 1U << i;
@@ -730,12 +819,22 @@ s32 inputReadController(s32 idx, OSContPad *npad)
npad->stick_x = xdiff < 0 ? -0x80 : (xdiff > 0 ? 0x7F : 0);
npad->stick_y = ydiff < 0 ? -0x80 : (ydiff > 0 ? 0x7F : 0);
const struct controllercfg *cfg = &padsCfg[idx];
if (cfg->cancelCButtons) {
// opposite C buttons cancel each other out
if ((npad->button & (L_CBUTTONS | R_CBUTTONS)) == (L_CBUTTONS | R_CBUTTONS)) {
npad->button &= ~(L_CBUTTONS | R_CBUTTONS);
}
if ((npad->button & (U_CBUTTONS | D_CBUTTONS)) == (U_CBUTTONS | D_CBUTTONS)) {
npad->button &= ~(U_CBUTTONS | D_CBUTTONS);
}
}
if (!pads[idx]) {
return 0;
}
const struct controllercfg *cfg = &padsCfg[idx];
s32 leftX = SDL_GameControllerGetAxis(pads[idx], cfg->axisMap[0][0]);
s32 leftY = SDL_GameControllerGetAxis(pads[idx], cfg->axisMap[0][1]);
s32 rightX = SDL_GameControllerGetAxis(pads[idx], cfg->axisMap[1][0]);
@@ -790,8 +889,12 @@ static inline void inputUpdateMouse(void)
mouseWheel = 0;
s32 mdx = 0;
s32 mdy = 0;
SDL_GetRelativeMouseState(&mdx, &mdy);
if (mouseLocked) {
SDL_GetRelativeMouseState(&mouseDX, &mouseDY);
mouseDX = mdx;
mouseDY = mdy;
} else {
mouseDX = mx - mouseX;
mouseDY = my - mouseY;
@@ -800,10 +903,18 @@ static inline void inputUpdateMouse(void)
mouseX = mx;
mouseY = my;
if (!mouseLocked && (mouseButtons & SDL_BUTTON_LMASK)) {
inputLockMouse(1);
} else if (mouseLocked && inputKeyPressed(VK_ESCAPE)) {
inputLockMouse(0);
// if MLOCK_AUTO is enabled, disable cursor if mouse is unlocked
// and we haven't moved it for a few seconds
if (mouseLockMode == MLOCK_AUTO && !mouseLocked) {
if (abs(mouseDX) > CURSOR_HIDE_THRESHOLD || abs(mouseDY) > CURSOR_HIDE_THRESHOLD) {
if (!mouseShowCursor) {
inputMouseShowCursor(1);
}
} else if (sysGetMicroseconds() > mouseCursorTime) {
if (mouseShowCursor) {
inputMouseShowCursor(0);
}
}
}
}
@@ -901,6 +1012,16 @@ void inputControllerSetDualAnalog(s32 cidx, s32 enable)
padsCfg[cidx].stickCButtons = !enable;
}
s32 inputControllerGetCancelCButtons(s32 cidx)
{
return padsCfg[cidx].cancelCButtons;
}
void inputControllerSetCancelCButtons(s32 cidx, s32 cancel)
{
padsCfg[cidx].cancelCButtons = cancel;
}
f32 inputControllerGetAxisScale(s32 cidx, s32 stick, s32 axis)
{
return padsCfg[cidx].sens[stick * 2 + axis];
@@ -970,6 +1091,13 @@ const char *inputGetConnectedControllerName(s32 id)
snprintf(fullName, sizeof(fullName), "%d: %s", jidx, name);
// replace non-ascii chars with spaces
for (char *p = fullName; *p; ++p) {
if ((u32)*p >= 0x7f) {
*p = ' ';
}
}
return fullName;
}
@@ -1051,9 +1179,13 @@ s32 inputKeyPressed(u32 vk)
if (vk >= VK_KEYBOARD_BEGIN && vk < VK_MOUSE_BEGIN) {
const u8 *state = SDL_GetKeyboardState(NULL);
return state[vk - VK_KEYBOARD_BEGIN];
} else if (vk >= VK_MOUSE_BEGIN && vk < VK_JOY_BEGIN) {
return mouseButtons & SDL_BUTTON(vk - VK_MOUSE_BEGIN + 1);
} else if (vk >= VK_JOY_BEGIN && vk < VK_TOTAL_COUNT) {
}
if (vk >= VK_MOUSE_BEGIN && vk < VK_JOY_BEGIN) {
return (mouseButtons & SDL_BUTTON(vk - VK_MOUSE_BEGIN + 1)) != 0;
}
if (vk >= VK_JOY_BEGIN && vk < VK_TOTAL_COUNT) {
vk -= VK_JOY_BEGIN;
const s32 idx = vk / INPUT_MAX_CONTROLLER_BUTTONS;
if (idx < 0 || idx >= INPUT_MAX_CONTROLLERS || !pads[idx]) {
@@ -1067,9 +1199,18 @@ s32 inputKeyPressed(u32 vk)
}
return SDL_GameControllerGetButton(pads[idx], vk);
}
return 0;
}
s32 inputKeyJustPressed(u32 vk)
{
const s8 pressed = inputKeyPressed(vk);
const s32 result = pressed && !vkPrevState[vk];
vkPrevState[vk] = pressed;
return result;
}
static inline u32 inputContToContKey(const u32 cont)
{
if (cont == 0) {
@@ -1099,10 +1240,11 @@ s32 inputMouseIsLocked(void)
return mouseLocked;
}
void inputMouseGetPosition(s32 *x, s32 *y)
s32 inputMouseGetPosition(s32 *x, s32 *y)
{
if (x) *x = mouseX * videoGetNativeWidth() / videoGetWidth();
if (y) *y = mouseY * videoGetNativeHeight() / videoGetHeight();
return (mouseDX != 0 || mouseDY != 0);
}
void inputMouseGetRawDelta(s32 *dx, s32 *dy)
@@ -1111,29 +1253,23 @@ void inputMouseGetRawDelta(s32 *dx, s32 *dy)
if (dy) *dy = mouseDY;
}
void inputMouseGetScaledDelta(f32 *dx, f32 *dy)
void inputMouseGetScaledDelta(f32* dx, f32* dy)
{
f32 mdx, mdy;
f32 mdx = 0.f, mdy = 0.f;
if (mouseLocked) {
mdx = mouseSensX * (f32)mouseDX / 100.0f;
mdy = mouseSensY * (f32)mouseDY / 100.0f;
} else {
mdx = 0.f;
mdy = 0.f;
mdx = mouseDX * (0.022f / 3.5f) * mouseSensX;
mdy = mouseDY * (0.022f / 3.5f) * mouseSensY;
}
if (dx) *dx = mdx;
if (dy) *dy = mdy;
}
void inputMouseGetAbsScaledDelta(f32 *dx, f32 *dy)
void inputMouseGetAbsScaledDelta(f32* dx, f32* dy)
{
f32 mdx, mdy;
f32 mdx = 0.f, mdy = 0.f;
if (mouseLocked) {
mdx = fabsf(mouseSensX) * (f32)mouseDX / 100.0f;
mdy = fabsf(mouseSensY) * (f32)mouseDY / 100.0f;
} else {
mdx = 0.f;
mdy = 0.f;
mdx = mouseDX * (0.022f / 3.5f) * fabsf(mouseSensX);
mdy = mouseDY * (0.022f / 3.5f) * fabsf(mouseSensY);
}
if (dx) *dx = mdx;
if (dy) *dy = mdy;
@@ -1159,21 +1295,41 @@ s32 inputMouseIsEnabled(void)
void inputMouseEnable(s32 enabled)
{
mouseEnabled = !!enabled;
if (!mouseEnabled && mouseLocked) {
if (!mouseEnabled && mouseLockMode != MLOCK_ON && mouseLocked) {
inputLockMouse(0);
}
}
s32 inputGetMouseDefaultLocked(void)
s32 inputAutoLockMouse(s32 wantlock)
{
return mouseDefaultLocked;
if (mouseEnabled && mouseLockMode == MLOCK_AUTO) {
inputLockMouse(wantlock);
return 1;
}
return 0;
}
void inputSetMouseDefaultLocked(s32 defaultLocked)
void inputMouseShowCursor(s32 show)
{
mouseDefaultLocked = !!defaultLocked;
if (mouseEnabled) {
inputLockMouse(mouseDefaultLocked);
mouseShowCursor = !!show;
SDL_ShowCursor(mouseShowCursor);
if (show) {
mouseCursorTime = sysGetMicroseconds() + CURSOR_HIDE_TIME;
}
}
s32 inputGetMouseLockMode(void)
{
return mouseLockMode;
}
void inputSetMouseLockMode(s32 lockmode)
{
mouseLockMode = lockmode;
if (lockmode == MLOCK_ON) {
inputLockMouse(1);
} else {
inputLockMouse(0);
}
}
@@ -1251,14 +1407,122 @@ s32 inputGetLastKey(void)
return lastKey;
}
void inputStartTextInput(void)
{
lastChar = 0;
lastKey = 0;
textInput = 1;
SDL_StartTextInput();
}
void inputClearLastTextChar(void)
{
lastChar = 0;
}
char inputGetLastTextChar(void)
{
return lastChar;
}
static inline s32 filterChar(const char ch)
{
return isalnum(ch) || ch == ' ' || ch == '?' || ch == '!' || ch == '.';
}
s32 inputTextHandler(char *out, const u32 outSize, s32 *curCol, s32 oskCharsOnly)
{
const s32 ctrlHeld = inputGetKeyModState() & KM_CTRL;
if (!ctrlHeld) {
const char chr = inputGetLastTextChar();
inputClearLastTextChar();
const s32 valid = chr && (oskCharsOnly ? filterChar(chr) : isprint(chr));
if (valid) {
if (*curCol < outSize - 1) {
out[(*curCol)++] = chr;
out[*curCol] = '\0';
}
}
}
const s32 key = inputGetLastKey();
inputClearLastKey();
if (ctrlHeld && (key == VK_A + ('v' - 'a'))) {
// CTRL+V; paste from clipboard
const char *clip = inputGetClipboard();
if (clip) {
const s32 remain = outSize - *curCol - 1;
inputClearClipboard();
*curCol += snprintf(out + *curCol, remain, "%s", clip);
if (*curCol > outSize) {
*curCol = outSize;
}
}
} else if (key == VK_BACKSPACE) {
if (*curCol) {
out[--*curCol] = '\0';
} else {
out[0] = '\0';
}
} else if (key == VK_ESCAPE) {
return -1;
}
return 0;
}
void inputClearClipboard(void)
{
if (clipboardText) {
SDL_free(clipboardText);
clipboardText = NULL;
}
}
const char *inputGetClipboard(void)
{
if (!clipboardText) {
char *text = SDL_GetClipboardText();
if (text) {
clipboardText = text;
// remove non-printable and multibyte chars
for (; *text; ++text) {
if ((u8)*text < 0x20 || (u8)*text >= 0x7F) {
*text = '?';
}
}
}
}
return clipboardText;
}
void inputStopTextInput(void)
{
SDL_StopTextInput();
textInput = 0;
}
s32 inputIsTextInputActive(void)
{
return textInput;
}
u32 inputGetKeyModState(void)
{
return SDL_GetModState();
}
PD_CONSTRUCTOR static void inputConfigInit(void)
{
configRegisterInt("Input.MouseEnabled", &mouseEnabled, 0, 1);
configRegisterInt("Input.MouseDefaultLocked", &mouseDefaultLocked, 0, 1);
configRegisterFloat("Input.MouseSpeedX", &mouseSensX, -10.f, 10.f);
configRegisterFloat("Input.MouseSpeedY", &mouseSensY, -10.f, 10.f);
configRegisterInt("Input.MouseLockMode", &mouseLockMode, MLOCK_OFF, MLOCK_AUTO);
configRegisterFloat("Input.MouseSpeedX", &mouseSensX, -30.f, 30.f);
configRegisterFloat("Input.MouseSpeedY", &mouseSensY, -30.f, 30.f);
configRegisterInt("Input.FakeGamepads", &fakeControllers, 0, 4);
configRegisterInt("Input.FirstGamepadNum", &firstController, 0, 3);
configRegisterInt("Input.UseHIDAPI", &useHIDAPI, 0, 1);
configRegisterInt("Input.UseRawInput", &useRawInput, 0, 1);
char secname[] = "Input.Player1.Binds";
char keyname[256] = { 0 };
@@ -1275,6 +1539,7 @@ PD_CONSTRUCTOR static void inputConfigInit(void)
configRegisterFloat(strFmt("%s.RStickScaleX", secname), &padsCfg[c].sens[2], -10.f, 10.f);
configRegisterFloat(strFmt("%s.RStickScaleY", secname), &padsCfg[c].sens[3], -10.f, 10.f);
configRegisterInt(strFmt("%s.StickCButtons", secname), &padsCfg[c].stickCButtons, 0, 1);
configRegisterInt(strFmt("%s.CancelCButtons", secname), &padsCfg[c].cancelCButtons, 0, 1);
configRegisterInt(strFmt("%s.SwapSticks", secname), &padsCfg[c].swapSticks, 0, 1);
configRegisterInt(strFmt("%s.ControllerIndex", secname), &padsCfg[c].deviceIndex, -1, 0x7FFFFFFF);
secname[13] = '.';
+7 -8
View File
@@ -6,6 +6,7 @@
#include <errno.h>
#include <PR/os_internal.h>
#include <PR/rcp.h>
#include "platform.h"
#include "system.h"
#include "input.h"
#include "video.h"
@@ -277,7 +278,7 @@ static inline void osEeepromLoad(const char *fname)
FILE *fp = fsFileOpenRead(fname);
if (fp) {
fread(eeprom, 1, EEPROM_SIZE, fp);
fsFileClose(fp);
fsFileFree(fp);
} else {
sysLogPrintf(LOG_NOTE, "could not read EEPROM from `%s`: %s", fsFullPath(fname), strerror(errno));
}
@@ -289,7 +290,7 @@ static inline void osEeepromSave(const char *fname)
FILE* fp = fsFileOpenWrite(fname);
if (fp) {
fwrite(eeprom, 1, EEPROM_SIZE, fp);
fsFileClose(fp);
fsFileFree(fp);
} else {
sysLogPrintf(LOG_ERROR, "could not save EEPROM to `%s`: %s", fsFullPath(fname), strerror(errno));
}
@@ -433,7 +434,7 @@ void osInvalDCache(void *a, s32 b)
}
s32 osPiStartDma(OSIoMesg *mb, s32 priority, s32 direction, uintptr_t devAddr, void *vAddr, size_t nbytes, OSMesgQueue *mq)
s32 osPiStartDma(OSIoMesg *mb, s32 priority, s32 direction, uintptr_t devAddr, void *vAddr, u32 nbytes, OSMesgQueue *mq)
{
memcpy(vAddr, (const void *)devAddr, nbytes);
return 0;
@@ -466,23 +467,21 @@ OSIntMask osSetIntMask(OSIntMask mask)
/* libc compatibility wrappers */
#ifndef HAVE_BZERO
#ifndef PLATFORM_OSX
void bzero(void *ptr, size_t size)
{
memset(ptr, 0, size);
}
#endif
#ifndef HAVE_BCOPY
void bcopy(const void *src, void *dst, size_t n)
{
memcpy(dst, src, n);
}
#endif
#ifndef HAVE_BCMP
s32 bcmp(const void *s1, const void *s2, size_t n)
{
return memcmp(s1, s2, n);
}
#endif
+7
View File
@@ -88,6 +88,7 @@ static void cleanup(void)
sysLogPrintf(LOG_NOTE, "shutdown");
inputSaveBinds();
configSave(CONFIG_PATH);
videoShutdown();
crashShutdown();
// TODO: actually shut down all subsystems
}
@@ -108,6 +109,8 @@ int main(int argc, const char **argv)
audioInit();
romdataInit();
g_ValidGbcRomFound = romdataCheckGbcRom();
gameInit();
if (fsGetModDir()) {
@@ -159,12 +162,14 @@ PD_CONSTRUCTOR static void gameConfigInit(void)
{
configRegisterInt("Game.MemorySize", &g_OsMemSizeMb, 4, 2048);
configRegisterInt("Game.CenterHUD", &g_HudCenter, 0, 2);
configRegisterInt("Game.MenuMouseControl", &g_MenuMouseControl, 0, 1);
configRegisterFloat("Game.ScreenShakeIntensity", &g_ViShakeIntensityMult, 0.f, 10.f);
configRegisterInt("Game.TickRateDivisor", &g_TickRateDiv, 0, 10);
configRegisterInt("Game.ExtraSleep", &g_TickExtraSleep, 0, 1);
configRegisterInt("Game.SkipIntro", &g_SkipIntro, 0, 1);
configRegisterInt("Game.DisableMpDeathMusic", &g_MusicDisableMpDeath, 0, 1);
configRegisterInt("Game.GEMuzzleFlashes", &g_BgunGeMuzzleFlashes, 0, 1);
configRegisterInt("Game.MaxExplosions", &g_MaxExplosions, 6, 96);
for (s32 j = 0; j < MAX_PLAYERS; ++j) {
const s32 i = j + 1;
configRegisterFloat(strFmt("Game.Player%d.FovY", i), &g_PlayerExtCfg[j].fovy, 5.f, 175.f);
@@ -174,10 +179,12 @@ PD_CONSTRUCTOR static void gameConfigInit(void)
configRegisterFloat(strFmt("Game.Player%d.MouseAimSpeedY", i), &g_PlayerExtCfg[j].mouseaimspeedy, 0.f, 10.f);
configRegisterFloat(strFmt("Game.Player%d.RadialMenuSpeed", i), &g_PlayerExtCfg[j].radialmenuspeed, 0.f, 10.f);
configRegisterFloat(strFmt("Game.Player%d.CrosshairSway", i), &g_PlayerExtCfg[j].crosshairsway, 0.f, 10.f);
configRegisterFloat(strFmt("Game.Player%d.CrosshairEdgeBoundary", i), &g_PlayerExtCfg[j].crosshairedgeboundary, 0.0f, 1.0f);
configRegisterInt(strFmt("Game.Player%d.CrouchMode", i), &g_PlayerExtCfg[j].crouchmode, 0, CROUCHMODE_TOGGLE_ANALOG);
configRegisterInt(strFmt("Game.Player%d.ExtendedControls", i), &g_PlayerExtCfg[j].extcontrols, 0, 1);
configRegisterUInt(strFmt("Game.Player%d.CrosshairColour", i), &g_PlayerExtCfg[j].crosshaircolour, 0, 0xFFFFFFFF);
configRegisterUInt(strFmt("Game.Player%d.CrosshairSize", i), &g_PlayerExtCfg[j].crosshairsize, 0, 4);
configRegisterInt(strFmt("Game.Player%d.CrosshairHealth", i), &g_PlayerExtCfg[j].crosshairhealth, 0, CROSSHAIR_HEALTH_ON_WHITE);
configRegisterInt(strFmt("Game.Player%d.UseKeyReloads", i), &g_PlayerExtCfg[j].usereloads, 0, false);
}
}
+3 -3
View File
@@ -420,7 +420,7 @@ s32 modTextureLoad(u16 num, void *dst, u32 dstSize)
{
static s32 dirExists = -1;
if (dirExists < 0) {
dirExists = (fsFileSize(MOD_TEXTURES_DIR "/") >= 0);
dirExists = (fsFileSize(MOD_TEXTURES_DIR) >= 0);
}
if (!dirExists) {
@@ -442,7 +442,7 @@ void *modSequenceLoad(u16 num, u32 *outSize)
{
static s32 dirExists = -1;
if (dirExists < 0) {
dirExists = (fsFileSize(MOD_SEQUENCES_DIR "/") >= 0);
dirExists = (fsFileSize(MOD_SEQUENCES_DIR) >= 0);
}
if (!dirExists) {
@@ -478,7 +478,7 @@ s32 modAnimationLoadDescriptor(u16 num, struct animtableentry *anim)
{
static s32 dirExists = -1;
if (dirExists < 0) {
dirExists = (fsFileSize(MOD_ANIMATIONS_DIR "/") >= 0);
dirExists = (fsFileSize(MOD_ANIMATIONS_DIR) >= 0);
}
if (!dirExists) {
+896
View File
@@ -0,0 +1,896 @@
#include "types.h"
#include "constants.h"
#include "bss.h"
#include "game/pak.h"
#include "game/filelist.h"
#include "game/menu.h"
#include "game/savebuffer.h"
#include "game/mplayer/mplayer.h"
#include <string.h>
#include "fs.h"
#include "system.h"
#include "mpsetups.h"
/*
MP Setup File Format
# header
[version{1}]
[defaultsetup{1}]
[numsetups{1}]
# setups
[setup_1{80}]
...
[setup_n{80}]
*/
#define MPSETUP_VERSION 1
#define MPSETUP_EXPORTDIR "$S/exported/"
#define MPSETUP_FILENAME "mpsetups"
#define MPSETUP_FILENAME_EXP "mpsetups-ext"
#define MPSETUP_OP_DEFAULT 0
#define MPSETUP_OP_IMPORT 1
#define MPSETUP_OP_EXPORT 2
#define MPSETUP_IMPORT_OVERWRITE 0
#define MPSETUP_IMPORT_ADD 1
#define MPSETUP_IMPORT_CONFLICT 0x1313
extern struct menudialogdef g_MpSaveSetupNameMenuDialog;
s16 g_MpCurrentSetup = -1;
struct mpsetupfile g_MpSetupFile;
static struct mpsetupfile g_ImportMpSetupFile;
static u64 g_MpImportExportFilter[2];
static char g_StatusText[128];
static char g_TitleImportExportDialog[20];
static char g_LabelSetDefault[20] = "Set Default\n";
/* extended mpsetup menu definitions */
static MenuItemHandlerResult menuhandlerRenameSetup(s32 operation, struct menuitem *item, union handlerdata *data);
static MenuItemHandlerResult menuhandlerDeleteSetup(s32 operation, struct menuitem *item, union handlerdata *data);
static MenuItemHandlerResult menuhandlerImportOrExportSettings(s32 operation, struct menuitem *item, union handlerdata *data);
static MenuItemHandlerResult menuhandlerImportAction(s32 operation, struct menuitem *item, union handlerdata *data);
static MenuItemHandlerResult menuhandlerOpenImportExportDialog(s32 operation, struct menuitem *item, union handlerdata *data);
static MenuItemHandlerResult menuhandlerSelectSetupHandler(s32 operation, struct menuitem *item, union handlerdata *data);
static MenuItemHandlerResult menuhandlerSetupRename(s32 operation, struct menuitem *item, union handlerdata *data);
static MenuItemHandlerResult menuhandlerSetupDelete(s32 operation, struct menuitem *item, union handlerdata *data);
static MenuItemHandlerResult menuhandlerSetupSetDefault(s32 operation, struct menuitem *item, union handlerdata *data);
static struct menuitem g_StatusOkMenuItems[] = {
{
MENUITEMTYPE_LABEL,
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
(uintptr_t)g_StatusText,
0,
NULL,
},
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG | MENUITEMFLAG_SELECTABLE_CENTRE,
L_OPTIONS_347, // "OK"
0,
NULL,
},
{ MENUITEMTYPE_END },
};
static struct menudialogdef g_StatusOkDialog = {
MENUDIALOGTYPE_SUCCESS,
L_OPTIONS_345, // "Cool!"
g_StatusOkMenuItems,
NULL,
MENUDIALOGFLAG_DISABLEBANNER,
NULL,
};
static struct menuitem g_StatusErrorMenuItems[] = {
{
MENUITEMTYPE_LABEL,
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
(uintptr_t)g_StatusText,
0,
NULL,
},
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG | MENUITEMFLAG_SELECTABLE_CENTRE,
L_OPTIONS_347, // "OK"
0,
NULL,
},
{ MENUITEMTYPE_END },
};
/* public */
struct menudialogdef g_StatusErrorDialog = {
MENUDIALOGTYPE_DANGER,
L_OPTIONS_277, // "Failed"
g_StatusErrorMenuItems,
NULL,
MENUDIALOGFLAG_DISABLEBANNER,
NULL,
};
static struct menuitem g_RenameSetupItems[] = {
#if VERSION != VERSION_JPN_FINAL
{
MENUITEMTYPE_LABEL,
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
(uintptr_t)"Enter the setup name:\n",
0,
NULL,
},
#endif
{
MENUITEMTYPE_KEYBOARD,
18,
0,
0,
1,
menuhandlerRenameSetup,
},
{ MENUITEMTYPE_END },
};
static struct menudialogdef g_RenameSetupDialog = {
MENUDIALOGTYPE_DEFAULT,
(uintptr_t)"Setup Name:\n",
g_RenameSetupItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT,
NULL,
};
static struct menuitem g_DeleteSetupItems[] = {
{
MENUITEMTYPE_LABEL,
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
(uintptr_t)"Delete Setup?\n",
0,
NULL,
},
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG | MENUITEMFLAG_SELECTABLE_CENTRE,
L_OPTIONS_385, // "No"
0,
NULL,
},
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_CENTRE,
L_OPTIONS_386, // "Yes"
0,
menuhandlerDeleteSetup,
},
{ MENUITEMTYPE_END },
};
static struct menudialogdef g_DeleteSetupDialog = {
MENUDIALOGTYPE_DANGER,
(uintptr_t)"Delete Setup\n",
g_DeleteSetupItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT,
NULL,
};
static struct menuitem g_ImportExportItems[] = {
{
MENUITEMTYPE_LIST,
0,
MENUITEMFLAG_LOCKABLEMINOR | MENUITEMFLAG_LABEL_CUSTOMCOLOUR,
140,
0x0000004d,
menuhandlerImportOrExportSettings,
},
{ MENUITEMTYPE_END },
};
static struct menudialogdef g_ImportExportDialog = {
MENUDIALOGTYPE_DEFAULT,
(uintptr_t) g_TitleImportExportDialog,
g_ImportExportItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT,
NULL,
};
static struct menuitem g_ManageImportExportItems[] = {
{
MENUITEMTYPE_SELECTABLE,
MPSETUP_OP_IMPORT,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Import Settings\n",
0,
menuhandlerOpenImportExportDialog,
},
{
MENUITEMTYPE_SELECTABLE,
MPSETUP_OP_EXPORT,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Export Settings\n",
0,
menuhandlerOpenImportExportDialog,
},
{ MENUITEMTYPE_END },
};
static struct menudialogdef g_ManageImportExportDialog = {
MENUDIALOGTYPE_DEFAULT,
(uintptr_t) "Import/Export\n",
g_ManageImportExportItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT,
NULL,
};
static struct menuitem g_MpManageSettingsListItems[] = {
{
MENUITEMTYPE_LIST,
0,
MENUITEMFLAG_LABEL_CUSTOMCOLOUR,
160,
0x00000042,
menuhandlerSelectSetupHandler,
},
{ MENUITEMTYPE_END },
};
/* public */
struct menudialogdef g_ManageSettingsDialog = {
MENUDIALOGTYPE_DEFAULT,
(uintptr_t) "Manage Settings\n",
g_MpManageSettingsListItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT,
&g_ManageImportExportDialog,
};
static struct menuitem g_ManageSetupItems[] = {
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Rename\n",
0,
menuhandlerSetupRename,
},
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Delete\n",
0,
menuhandlerSetupDelete,
},
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)g_LabelSetDefault,
0,
menuhandlerSetupSetDefault,
},
{
MENUITEMTYPE_SEPARATOR,
0,
0,
0,
0,
NULL,
},
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
L_OPTIONS_213, // "Back"
0,
NULL,
},
{ MENUITEMTYPE_END },
};
static struct menudialogdef g_ManageSetupDialog = {
MENUDIALOGTYPE_DEFAULT,
(uintptr_t)"Manage Setup",
g_ManageSetupItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT,
NULL,
};
static struct menuitem g_ImportOverrideItems[] = {
{
MENUITEMTYPE_LABEL,
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
(uintptr_t) "How to resolve setups\nwith the same name?\n",
0,
NULL,
},
{
MENUITEMTYPE_SELECTABLE,
MPSETUP_IMPORT_ADD,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
(uintptr_t) "Add\n",
0,
menuhandlerImportAction,
},
{
MENUITEMTYPE_SELECTABLE,
MPSETUP_IMPORT_OVERWRITE,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
(uintptr_t) "Overwrite\n",
0,
menuhandlerImportAction,
},
{ MENUITEMTYPE_END },
};
static struct menudialogdef g_ImportOverrideDialog = {
MENUDIALOGTYPE_DEFAULT,
(uintptr_t)"Name Conflicts\n",
g_ImportOverrideItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT,
NULL,
};
/* common utils */
static s32 mpsetupDeserialize(FILE *f, struct mpsetupfile *setupfile)
{
s32 rx = 0;
rx += fread(&setupfile->version, sizeof(setupfile->version), 1, f);
rx += fread(&setupfile->defaultsetup, sizeof(setupfile->defaultsetup), 1, f);
rx += fread(&setupfile->numsetups, sizeof(setupfile->numsetups), 1, f);
for (int i = 0; i < setupfile->numsetups; ++i) {
rx += fread(setupfile->setups[i].bytes, sizeof(setupfile->setups[i].bytes), 1, f);
}
return rx;
}
static s32 mpsetupSerialize(FILE *f, struct mpsetupfile *setupfile)
{
s32 wx = 0;
wx += fwrite(&setupfile->version, sizeof(setupfile->version), 1, f);
wx += fwrite(&setupfile->defaultsetup, sizeof(setupfile->defaultsetup), 1, f);
wx += fwrite(&setupfile->numsetups, sizeof(setupfile->numsetups), 1, f);
for (int i = 0; i < setupfile->numsetups; ++i) {
wx += fwrite(setupfile->setups[i].bytes, sizeof(setupfile->setups[i].bytes), 1, f);
}
return wx;
}
static FILE *mpsetupOpenFile(bool write, u8 op) {
const char *filename = fsFullPath("$S/" MPSETUP_FILENAME ".bin");
if (op == MPSETUP_OP_EXPORT) {
// create export directory if it doesn't exist
if (fsFileSize(MPSETUP_EXPORTDIR) < 0) {
if (fsCreateDir(MPSETUP_EXPORTDIR) != 0) {
return NULL;
}
}
filename = fsFullPath(MPSETUP_EXPORTDIR MPSETUP_FILENAME_EXP ".bin");
} else if (op == MPSETUP_OP_IMPORT) {
// same name as export but different folder
filename = fsFullPath("$S/" MPSETUP_FILENAME_EXP ".bin");
}
FILE *f;
if (fsFileSize(filename) < 0) {
// setup file doesn't exist: create one
f = fsFileOpenWrite(filename);
fsFileFree(f);
}
if (write) {
f = fsFileOpenWrite(filename);
} else {
f = fsFileOpenRead(filename);
}
if (f == NULL) {
sysLogPrintf(LOG_ERROR, "Unable to open mp setup file");
return NULL;
}
return f;
}
static s32 mpsetupSaveFile(u8 op, struct mpsetupfile *setupfile)
{
FILE *f = mpsetupOpenFile(true, op);
if (f == NULL) {
return -1;
}
s32 nwritten = mpsetupSerialize(f, setupfile);
if (nwritten < 1) {
fsFileFree(f);
sysLogPrintf(LOG_ERROR, "Unable to write the MP setup file");
snprintf(g_StatusText, sizeof(g_StatusText), "Unable to write the setup file\n");
return -1;
}
fsFileFree(f);
return 0;
}
static s32 mpsetupLoadFile(struct mpsetupfile *setupfile, u8 op)
{
FILE *f = mpsetupOpenFile(false, op);
if (f == NULL) {
return -1;
}
mpsetupDeserialize(f, setupfile);
if (op == MPSETUP_OP_DEFAULT && setupfile->defaultsetup > 0) {
mpsetupLoadSetup(setupfile->defaultsetup - 1);
}
fsFileFree(f);
return 0;
}
static s32 mpsetupImportFile(u8 op, u8 skipOverlap)
{
if (!skipOverlap) {
// check for names overlap
u8 overlap = false;
for (int i = 0; i < g_ImportMpSetupFile.numsetups; ++i) {
for (int j = 0; j < g_MpSetupFile.numsetups; ++j) {
if (strcmp(g_ImportMpSetupFile.setups[i].bytes, g_MpSetupFile.setups[j].bytes) == 0) {
overlap = true;
return MPSETUP_IMPORT_CONFLICT;
}
}
}
}
for (int i = 0; i < g_ImportMpSetupFile.numsetups; ++i) {
s16 overlapIdx = -1;
for (int j = g_MpSetupFile.numsetups-1; j >= 0; --j) {
if (strcmp(g_ImportMpSetupFile.setups[i].bytes, g_MpSetupFile.setups[j].bytes) == 0) {
overlapIdx = j;
break;
}
}
s16 importIdx = overlapIdx;
if (overlapIdx < 0 || op == MPSETUP_IMPORT_ADD) {
if (g_MpSetupFile.numsetups == MPSETUP_MAXSETUPS) {
snprintf(g_StatusText, sizeof(g_StatusText), "Number of setups exceeds %d\n", MPSETUP_MAXSETUPS);
return -1;
}
importIdx = g_MpSetupFile.numsetups++;
}
memcpy(g_MpSetupFile.setups[importIdx].bytes, g_ImportMpSetupFile.setups[i].bytes, MPSETUP_BLOCKSIZE);
}
return mpsetupSaveCurrentFile();
}
static s32 mpsetupExportFile(void)
{
struct mpsetupfile expMpSetupFile;
expMpSetupFile.numsetups = 0;
expMpSetupFile.defaultsetup = 0;
expMpSetupFile.version = MPSETUP_VERSION;
u8 maxsetups = MPSETUP_MAXSETUPS;
maxsetups = MIN(maxsetups, g_MpSetupFile.numsetups);
for (int i = 0; i < maxsetups; ++i) {
u8 bank = i < 64 ? 0 : 1;
u8 bit = i - bank * 64;
if (g_MpImportExportFilter[bank] & (1 << bit)) {
u8 n = expMpSetupFile.numsetups;
expMpSetupFile.numsetups++;
char *name = g_MpSetupFile.setups[i].bytes;
memcpy(expMpSetupFile.setups[n].bytes, g_MpSetupFile.setups[i].bytes, MPSETUP_BLOCKSIZE);
expMpSetupFile.numsetups = n + 1;
}
}
s32 err = mpsetupSaveFile(MPSETUP_OP_EXPORT, &expMpSetupFile);
if (err) {
snprintf(g_StatusText, sizeof(g_StatusText), "Unable to write\nsetup file\n");
}
return err;
}
static s32 mpsetupDelete(void)
{
s32 slotindex = g_Menus[g_MpPlayerNum].mpsetup.slotindex;
for (int i = slotindex; i < g_MpSetupFile.numsetups - 1; ++i) {
u8* dst = g_MpSetupFile.setups[i].bytes;
u8* src = g_MpSetupFile.setups[i+1].bytes;
memcpy(dst, src, MPSETUP_BLOCKSIZE);
}
if (g_MpCurrentSetup > slotindex) {
g_MpCurrentSetup--;
}
else if (g_MpCurrentSetup == slotindex) {
g_MpCurrentSetup = -1;
}
if (g_MpSetupFile.defaultsetup > slotindex + 1) {
g_MpSetupFile.defaultsetup--;
}
else if (g_MpSetupFile.defaultsetup == slotindex + 1) {
g_MpSetupFile.defaultsetup = 0;
}
g_MpSetupFile.numsetups--;
return mpsetupSaveCurrentFile();
}
/* menu handlers */
// Rename setup dialog
static MenuItemHandlerResult menuhandlerRenameSetup(s32 operation, struct menuitem *item, union handlerdata *data)
{
char *name = data->keyboard.string;
s32 slotindex = g_Menus[g_MpPlayerNum].mpsetup.slotindex;
struct setupblock *setup = &g_MpSetupFile.setups[slotindex];
s32 err;
switch (operation) {
case MENUOP_GETTEXT:
strcpy(name, setup->bytes);
break;
case MENUOP_SETTEXT:
strcpy(g_MpSetup.name, name);
break;
case MENUOP_SET:
strcpy(setup->bytes, name);
err = mpsetupSaveSetup(slotindex, true);
if (!err) {
menuPopDialog();
} else {
// TODO
// menuPushDialog(&g_FilemgrFileSavedMenuDialog);
}
break;
}
return 0;
}
// Delete setup dialog
static MenuItemHandlerResult menuhandlerDeleteSetup(s32 operation, struct menuitem *item, union handlerdata *data)
{
if (operation == MENUOP_SET) {
s32 err = mpsetupDelete();
if (!err) {
menuPopDialog();
menuPopDialog();
} else {
// TODO
}
}
return 0;
}
// Import (or Export) settings dialog
static MenuItemHandlerResult menuhandlerImportOrExportSettings(s32 operation, struct menuitem *item, union handlerdata *data)
{
static const char *labels[] = {
"Select All",
"Select None",
"Import",
"Export",
};
s32 op = g_Menus[g_MpPlayerNum].mpsetup.unke24;
struct mpsetupfile *setupfile = op == MPSETUP_OP_IMPORT ? &g_ImportMpSetupFile : &g_MpSetupFile;
u8 numsetups = setupfile->numsetups;
u8 numitems = numsetups + 3;
u8 bank = data->list.value < 64 ? 0 : 1;
u8 bit = data->list.value - bank * 64;
u8 hasselection = (g_MpImportExportFilter[0] | g_MpImportExportFilter[1]) != 0;
u8 ofs;
s32 err;
u32 colour;
s32 index;
switch (operation) {
case MENUOP_GETCOLOUR:
colour = data->list.unk04;
if (data->list.value == numitems - 1) {
data->list.unk04 = hasselection ? colour : (colour & 0xffffff00) | 0x66;
}
break;
case MENUOP_GETOPTIONCOUNT:
data->list.value = numitems;
break;
case MENUOP_GETOPTIONTEXT:
if (data->list.value < numsetups) {
return (uintptr_t) setupfile->setups[data->list.value].bytes;
} else {
// creates an offset to select the "Export" or "Import" label for the last item
ofs = (data->list.value == numitems - 1) ? op - 1 : 0;
return (intptr_t)labels[data->list.value - numsetups + ofs];
}
case MENUOP_SET:
if (data->list.value < setupfile->numsetups) {
g_MpImportExportFilter[bank] ^= (1 << bit);
} else {
index = data->list.value - setupfile->numsetups;
switch (index) {
// Select All
case 0:
g_MpImportExportFilter[0] = g_MpImportExportFilter[1] = -1;
break;
// Select None
case 1:
g_MpImportExportFilter[0] = g_MpImportExportFilter[1] = 0;
break;
// Export (or Import)
case 2:
if (hasselection) {
err = op == MPSETUP_OP_IMPORT ? mpsetupImportFile(0, false) : mpsetupExportFile();
if (!err) {
menuPopDialog();
if (op == MPSETUP_OP_IMPORT) {
// back to the 'Manage Settings' screen
menuPopDialog();
menuPushDialog(&g_ManageSettingsDialog);
} else {
snprintf(g_StatusText, sizeof(g_StatusText), "File %s.bin\nwritten to the folder 'exported'\n", MPSETUP_FILENAME_EXP);
menuPushDialog(&g_StatusOkDialog);
}
} else {
if (err == MPSETUP_IMPORT_CONFLICT) {
menuPopDialog();
menuPushDialog(&g_ImportOverrideDialog);
} else {
menuPushDialog(&g_StatusErrorDialog);
}
}
}
break;
}
}
break;
case MENUOP_GETSELECTEDINDEX:
data->list.value = 0x000fffff;
break;
case MENUOP_GETLISTITEMCHECKBOX:
if (data->list.value < numsetups) {
data->list.unk04 = (g_MpImportExportFilter[bank] & (1 << bit));
}
break;
}
return 0;
}
// Import: overwrite dialog
static MenuItemHandlerResult menuhandlerImportAction(s32 operation, struct menuitem *item, union handlerdata *data)
{
if (operation == MENUOP_SET) {
s32 err = mpsetupImportFile(item->param, true);
if (!err) {
menuPopDialog();
menuPushDialog(&g_ManageSettingsDialog);
} else {
menuPushDialog(&g_StatusErrorDialog);
}
}
return 0;
}
// Manage Import/Export settings dialog
static MenuItemHandlerResult menuhandlerOpenImportExportDialog(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
case MENUOP_SET:
if (item->param == MPSETUP_OP_IMPORT) {
strcpy(g_TitleImportExportDialog, "Import Settings\n");
if (fsFileSize("$S/" MPSETUP_FILENAME_EXP ".bin") < 0) {
snprintf(
g_StatusText, sizeof(g_StatusText),
"No import file found.\n"
"Place the file %s.bin\n"
"Next to your %s.bin file\n",
MPSETUP_FILENAME_EXP, MPSETUP_FILENAME
);
menuPushDialog(&g_StatusErrorDialog);
return 0;
}
mpsetupLoadFile(&g_ImportMpSetupFile, MPSETUP_OP_IMPORT);
} else {
strcpy(g_TitleImportExportDialog, "Export Settings\n");
}
g_Menus[g_MpPlayerNum].mpsetup.unke24 = item->param;
g_MpImportExportFilter[0] = g_MpImportExportFilter[1] = -1;
menuPushDialog(&g_ImportExportDialog);
break;
}
return 0;
}
// Manage settings dialog
static MenuItemHandlerResult menuhandlerSelectSetupHandler(s32 operation, struct menuitem *item, union handlerdata *data)
{
u32 colour;
switch (operation) {
case MENUOP_GETCOLOUR:
colour = data->list.unk04;
if (data->list.value + 1 == g_MpSetupFile.defaultsetup) {
data->list.unk04 = (colour & 0xffff0000) | 0xff;
}
break;
case MENUOP_GETOPTIONCOUNT:
data->list.value = g_MpSetupFile.numsetups;
break;
case MENUOP_GETOPTIONTEXT:
return (uintptr_t) g_MpSetupFile.setups[data->list.value].bytes;
case MENUOP_SET:
g_Menus[g_MpPlayerNum].mpsetup.slotindex = data->list.value;
if (data->list.value == g_MpSetupFile.defaultsetup - 1) {
strcpy(g_LabelSetDefault, "Clear Default\n");
} else {
strcpy(g_LabelSetDefault, "Set Default\n");
}
menuPushDialog(&g_ManageSetupDialog);
break;
case MENUOP_GETSELECTEDINDEX:
data->list.value = 0xfffff;
break;
}
return 0;
}
static MenuItemHandlerResult menuhandlerSetupRename(s32 operation, struct menuitem *item, union handlerdata *data)
{
if (operation == MENUOP_SET) {
menuPushDialog(&g_RenameSetupDialog);
}
return 0;
}
static MenuItemHandlerResult menuhandlerSetupDelete(s32 operation, struct menuitem *item, union handlerdata *data)
{
if (operation == MENUOP_SET) {
menuPushDialog(&g_DeleteSetupDialog);
}
return 0;
}
static MenuItemHandlerResult menuhandlerSetupSetDefault(s32 operation, struct menuitem *item, union handlerdata *data)
{
if (operation == MENUOP_SET) {
s32 selected = g_Menus[g_MpPlayerNum].mpsetup.slotindex;
// clicked on "clear default"
if (selected == g_MpSetupFile.defaultsetup - 1) {
g_MpSetupFile.defaultsetup = 0;
strcpy(g_LabelSetDefault, "Set Default\n");
} else {
g_MpSetupFile.defaultsetup = selected + 1;
strcpy(g_LabelSetDefault, "Clear Default\n");
}
mpsetupSaveCurrentFile();
}
return 0;
}
/* public functions */
s32 mpsetupLoadCurrentFile(void)
{
return mpsetupLoadFile(&g_MpSetupFile, MPSETUP_OP_DEFAULT);
}
s32 mpsetupSaveCurrentFile(void)
{
g_MpSetupFile.version = MPSETUP_VERSION;
return mpsetupSaveFile(MPSETUP_OP_DEFAULT, &g_MpSetupFile);
}
s32 mpsetupSaveSetup(s32 slotindex, u8 savefile)
{
struct savebuffer setup;
// request to add a new setup
if (slotindex == g_MpSetupFile.numsetups) {
g_MpCurrentSetup = g_MpSetupFile.numsetups++;
}
savebufferClear(&setup);
mpsetupfileSaveWad(&setup);
memcpy(g_MpSetupFile.setups[slotindex].bytes, setup.bytes, MPSETUP_BLOCKSIZE);
return savefile ? mpsetupSaveCurrentFile() : 0;
}
void mpsetupLoadSetup(s32 index)
{
struct savebuffer buffer;
savebufferClear(&buffer);
struct setupblock *block = &g_MpSetupFile.setups[index];
memcpy(&buffer.bytes, block->bytes, MPSETUP_BLOCKSIZE);
mpsetupfileLoadWad(&buffer, g_MpSetupFile.version);
g_MpCurrentSetup = index;
}
void mpsetupCopyAllFromPak(void)
{
if (fsFileSize("$S/" MPSETUP_FILENAME ".bin") > 0) {
return;
}
filelistCreate(1, FILETYPE_MPSETUP);
filelistsTick();
for (int i = 0; i < g_FileLists[1]->numfiles; ++i) {
struct savebuffer buffer;
savebufferClear(&buffer);
struct filelistfile *file = &g_FileLists[1]->files[i];
s32 device = pakFindBySerial(file->deviceserial);
s32 err = pakReadBodyAtGuid(device, file->fileid, buffer.bytes, 0);
if (err != 0) {
sysLogPrintf(LOG_ERROR, "Unable to read pak. device %d fileid %d deviceserial %d err %d",
device, file->fileid, file->deviceserial, err);
continue;
}
mpsetupfileLoadWad(&buffer, 0);
// save the file when writing the last setup
u8 savefile = i == g_FileLists[1]->numfiles - 1;
mpsetupSaveSetup(g_MpSetupFile.numsetups, savefile);
}
// to reset the mp setup
mpInit(false);
}
+495 -41
View File
@@ -9,6 +9,8 @@
#include "game/mainmenu.h"
#include "game/menu.h"
#include "game/gamefile.h"
#include "game/player.h"
#include "lib/joy.h"
#include "video.h"
#include "input.h"
#include "config.h"
@@ -119,13 +121,40 @@ static MenuItemHandlerResult menuhandlerMouseAimLock(s32 operation, struct menui
return 0;
}
static MenuItemHandlerResult menuhandlerMouseDefaultLocked(s32 operation, struct menuitem *item, union handlerdata *data)
static MenuItemHandlerResult menuhandlerMouseLockMode(s32 operation, struct menuitem *item, union handlerdata *data)
{
static const char *opts[] = {
"Always Off",
"Always On",
"Auto"
};
switch (operation) {
case MENUOP_GETOPTIONCOUNT:
data->dropdown.value = ARRAYCOUNT(opts);
break;
case MENUOP_GETOPTIONTEXT:
return (intptr_t)opts[data->dropdown.value];
case MENUOP_SET:
inputSetMouseLockMode(data->checkbox.value);
break;
case MENUOP_GETSELECTEDINDEX:
data->dropdown.value = inputGetMouseLockMode();
}
return 0;
}
static MenuItemHandlerResult menuhandlerMenuMouseControl(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
case MENUOP_GET:
return inputGetMouseDefaultLocked();
return g_MenuMouseControl;
case MENUOP_SET:
inputSetMouseDefaultLocked(data->checkbox.value);
g_MenuMouseControl = data->checkbox.value;
if (!g_MenuMouseControl) {
g_MenuUsingMouse = false;
}
break;
}
@@ -141,15 +170,16 @@ static MenuItemHandlerResult menuhandlerMouseSpeedX(s32 operation, struct menuit
inputMouseGetSpeed(&x, &y);
if (x < 0.f) {
data->slider.value = 0;
} else if (x > 10.f) {
data->slider.value = 100;
} else {
data->slider.value = x * 10.f + 0.5f;
data->slider.value = x * 100.f + 0.5f;
}
break;
case MENUOP_SET:
inputMouseGetSpeed(&x, &y);
inputMouseSetSpeed((f32)data->slider.value / 10.f, y);
inputMouseSetSpeed((f32)data->slider.value / 100.f, y);
break;
case MENUOP_GETSLIDERLABEL:
sprintf(data->slider.label, "%.2f", (f32)data->slider.value / 100.f);
break;
}
@@ -165,15 +195,16 @@ static MenuItemHandlerResult menuhandlerMouseSpeedY(s32 operation, struct menuit
inputMouseGetSpeed(&x, &y);
if (y < 0.f) {
data->slider.value = 0;
} else if (y > 10.f) {
data->slider.value = 100;
} else {
data->slider.value = y * 10.f + 0.5f;
data->slider.value = y * 100.f + 0.5f;
}
break;
case MENUOP_SET:
inputMouseGetSpeed(&x, &y);
inputMouseSetSpeed(x, (f32)data->slider.value / 10.f);
inputMouseSetSpeed(x, (f32)data->slider.value / 100.f);
break;
case MENUOP_GETSLIDERLABEL:
sprintf(data->slider.label, "%.2f", (f32)data->slider.value / 100.f);
break;
}
@@ -187,14 +218,16 @@ static MenuItemHandlerResult menuhandlerMouseAimSpeedX(s32 operation, struct men
if (g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedx < 0.f) {
data->slider.value = 0;
} else if (g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedx > 10.f) {
data->slider.value = 100;
data->slider.value = 1000;
} else {
data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedx * 10.f + 0.5f;
data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedx * 100.f + 0.5f;
}
break;
case MENUOP_SET:
g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedx = (f32)data->slider.value / 10.f;
g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedx = (f32)data->slider.value / 100.f;
break;
case MENUOP_GETSLIDERLABEL:
sprintf(data->slider.label, "%.2f", (f32)data->slider.value / 100.f);
}
return 0;
@@ -207,14 +240,16 @@ static MenuItemHandlerResult menuhandlerMouseAimSpeedY(s32 operation, struct men
if (g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedy < 0.f) {
data->slider.value = 0;
} else if (g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedy > 10.f) {
data->slider.value = 100;
data->slider.value = 1000;
} else {
data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedy * 10.f + 0.5f;
data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedy * 100.f + 0.5f;
}
break;
case MENUOP_SET:
g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedy = (f32)data->slider.value / 10.f;
g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedy = (f32)data->slider.value / 100.f;
break;
case MENUOP_GETSLIDERLABEL:
sprintf(data->slider.label, "%.2f", (f32)data->slider.value / 100.f);
}
return 0;
@@ -227,14 +262,16 @@ static MenuItemHandlerResult menuhandlerRadialMenuSpeed(s32 operation, struct me
if (g_PlayerExtCfg[0].radialmenuspeed < 0.f) {
data->slider.value = 0;
} else if (g_PlayerExtCfg[0].radialmenuspeed > 10.f) {
data->slider.value = 100;
data->slider.value = 1000;
} else {
data->slider.value = g_PlayerExtCfg[0].radialmenuspeed * 10.f + 0.5f;
data->slider.value = g_PlayerExtCfg[0].radialmenuspeed * 100.f + 0.5f;
}
break;
case MENUOP_SET:
g_PlayerExtCfg[0].radialmenuspeed = (f32)data->slider.value / 10.f;
g_PlayerExtCfg[0].radialmenuspeed = (f32)data->slider.value / 100.f;
break;
case MENUOP_GETSLIDERLABEL:
sprintf(data->slider.label, "%.2f", (f32)data->slider.value / 100.f);
}
return 0;
@@ -257,13 +294,21 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
0,
menuhandlerMouseAimLock,
},
{
MENUITEMTYPE_DROPDOWN,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Mouse Lock Mode",
0,
menuhandlerMouseLockMode,
},
{
MENUITEMTYPE_CHECKBOX,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Grab Mouse Input by Default",
(uintptr_t)"Mouse Menu Navigation",
0,
menuhandlerMouseDefaultLocked,
menuhandlerMenuMouseControl,
},
{
MENUITEMTYPE_SEPARATOR,
@@ -278,7 +323,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Mouse Speed X",
100,
3000,
menuhandlerMouseSpeedX,
},
{
@@ -286,7 +331,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Mouse Speed Y",
100,
3000,
menuhandlerMouseSpeedY,
},
{
@@ -294,7 +339,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Crosshair Speed X",
100,
1000,
menuhandlerMouseAimSpeedX,
},
{
@@ -302,7 +347,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Crosshair Speed Y",
100,
1000,
menuhandlerMouseAimSpeedY,
},
{
@@ -310,7 +355,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Radial Menu Speed",
100,
1000,
menuhandlerRadialMenuSpeed,
},
{
@@ -551,8 +596,10 @@ static MenuItemHandlerResult menuhandlerController(s32 operation, struct menuite
if (data->dropdown.value == 0) {
// unassign controller
inputAssignController(g_ExtMenuPlayer, -1);
joyReset();
} else if (data->dropdown.value <= numCtrls) {
inputAssignController(g_ExtMenuPlayer, ctrls[data->dropdown.value - 1]);
joyReset();
}
break;
case MENUOP_GETSELECTEDINDEX:
@@ -652,27 +699,183 @@ static MenuItemHandlerResult menuhandlerFullScreen(s32 operation, struct menuite
return 0;
}
static MenuItemHandlerResult menuhandlerMaximizeWindow(s32 operation, struct menuitem *item, union handlerdata *data)
static MenuItemHandlerResult menuhandlerFullScreenMode(s32 operation, struct menuitem *item, union handlerdata *data)
{
static const char *opts[] = {
"Borderless",
"Exclusive"
};
switch (operation) {
case MENUOP_GETOPTIONCOUNT:
data->dropdown.value = ARRAYCOUNT(opts);
break;
case MENUOP_GETOPTIONTEXT:
return (intptr_t)opts[data->dropdown.value];
case MENUOP_SET:
videoSetFullscreenMode(data->dropdown.value);
break;
case MENUOP_GETSELECTEDINDEX:
data->dropdown.value = videoGetFullscreenMode();
}
return 0;
}
static MenuItemHandlerResult menuhandlerCenterWindow(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
case MENUOP_GET:
return videoGetMaximizeWindow();
return videoGetCenterWindow();
case MENUOP_SET:
videoSetMaximizeWindow(data->checkbox.value);
videoSetCenterWindow(data->checkbox.value);
break;
}
return 0;
}
static MenuItemHandlerResult menuhandlerVsync(s32 operation, struct menuitem *item, union handlerdata *data)
{
static const s32 numOpts = 10;
static const char *constOpts[] = {
"Adaptive",
"Off",
"On"
};
static char dynOpt[20];
s32 vblanks;
switch (operation) {
case MENUOP_GETOPTIONCOUNT:
data->dropdown.value = numOpts;
break;
case MENUOP_GETOPTIONTEXT:
if (data->dropdown.value < ARRAYCOUNT(constOpts))
return (intptr_t)constOpts[data->dropdown.value];
vblanks = (s32)data->dropdown.value - 1;
snprintf(dynOpt, sizeof(dynOpt), "On (%d frames)", vblanks);
return (intptr_t)dynOpt;
case MENUOP_SET:
videoSetVsync(data->dropdown.value - 1);
case MENUOP_GETSELECTEDINDEX:
data->dropdown.value = videoGetVsync() + 1;
}
return 0;
}
static MenuItemHandlerResult menuhandlerFramerateLimit(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
case MENUOP_GETSLIDER:
data->slider.value = videoGetFramerateLimit();
break;
case MENUOP_SET:
videoSetFramerateLimit(data->slider.value);
break;
case MENUOP_GETSLIDERLABEL:
// NOTE: data->slider.label length must not exceed 15.
if (data->slider.value == 0) {
strcpy(data->slider.label, "Off");
} else {
sprintf(data->slider.label, "%d FPS", data->slider.value);
}
}
return 0;
}
static MenuItemHandlerResult menuhandlerMSAA(s32 operation, struct menuitem *item, union handlerdata *data)
{
s32 msaa;
static const char *opts[] = {
"Off",
"2x (MSAA)",
"4x (MSAA)",
"8x (MSAA)",
"16x (MSAA)"
};
switch (operation) {
case MENUOP_GETOPTIONCOUNT:
data->dropdown.value = ARRAYCOUNT(opts);
break;
case MENUOP_GETOPTIONTEXT:
return (intptr_t)opts[data->dropdown.value];
case MENUOP_SET:
videoSetMSAA(1 << data->dropdown.value);
break;
case MENUOP_GETSELECTEDINDEX:
msaa = videoGetMSAA();
if (msaa < 2) {
data->dropdown.value = 0;
} else if (msaa < 4) {
data->dropdown.value = 1;
} else if (msaa < 8) {
data->dropdown.value = 2;
} else if (msaa < 16) {
data->dropdown.value = 3;
} else {
data->dropdown.value = 4;
}
}
return 0;
}
static MenuItemHandlerResult menuhandlerResolution(s32 operation, struct menuitem *item, union handlerdata *data)
{
static char resstring[32];
static const char *rescustom = "Custom";
displaymode mode;
switch (operation) {
case MENUOP_CHECKDISABLED:
if (videoGetFullscreen() && videoGetFullscreenMode() == 0) {
return true;
}
break;
case MENUOP_GETOPTIONCOUNT:
data->dropdown.value = videoGetNumDisplayModes();
break;
case MENUOP_GETOPTIONTEXT:
videoGetDisplayMode(&mode, data->dropdown.value);
if (mode.width == 0 && mode.height == 0) {
return (intptr_t)rescustom;
} else {
snprintf(resstring, sizeof(resstring), "%dx%d", mode.width, mode.height);
}
return (intptr_t)resstring;
case MENUOP_SET:
videoSetDisplayMode(data->dropdown.value);
break;
case MENUOP_GETSELECTEDINDEX:
data->dropdown.value = videoGetDisplayModeIndex();
}
return 0;
}
static MenuItemHandlerResult menuhandlerTexFilter(s32 operation, struct menuitem *item, union handlerdata *data)
{
static const char *opts[] = {
"Nearest",
"Bilinear",
"Three Point"
};
switch (operation) {
case MENUOP_GET:
return (videoGetTextureFilter() != 0);
case MENUOP_SET:
videoSetTextureFilter(data->checkbox.value);
case MENUOP_GETOPTIONCOUNT:
data->dropdown.value = ARRAYCOUNT(opts);
break;
case MENUOP_GETOPTIONTEXT:
return (intptr_t)opts[data->dropdown.value];
case MENUOP_SET:
videoSetTextureFilter(data->dropdown.value);
break;
case MENUOP_GETSELECTEDINDEX:
data->dropdown.value = videoGetTextureFilter();
}
return 0;
@@ -698,12 +901,39 @@ static MenuItemHandlerResult menuhandlerTexFilter2D(s32 operation, struct menuit
return videoGetTextureFilter2D();
case MENUOP_SET:
videoSetTextureFilter2D(data->checkbox.value);
g_TexFilter2D = videoGetTextureFilter2D() ? G_TF_BILERP : G_TF_POINT;
break;
}
return 0;
}
static MenuItemHandlerResult menuhandlerAnisotropicFiltering(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
case MENUOP_GETSLIDER:
data->slider.value = videoGetAnisotropicFilter();
break;
case MENUOP_SET:
videoSetAnisotropicFilter(data->slider.value);
break;
}
return 0;
}
static MenuItemHandlerResult menuhandlerDisplayFPS(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
case MENUOP_GET:
return videoGetDisplayFPS();
case MENUOP_SET:
videoSetDisplayFPS(data->checkbox.value);
}
return 0;
}
static MenuItemHandlerResult menuhandlerGeMuzzleFlashes(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
@@ -717,6 +947,19 @@ static MenuItemHandlerResult menuhandlerGeMuzzleFlashes(s32 operation, struct me
return 0;
}
static MenuItemHandlerResult menuhandlerUncapTickrate(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
case MENUOP_GET:
return (g_TickRateDiv == 0);
case MENUOP_SET:
g_TickRateDiv = !data->checkbox.value;
break;
}
return 0;
}
static MenuItemHandlerResult menuhandlerCenterHUD(s32 operation, struct menuitem *item, union handlerdata *data)
{
static const char *opts[] = {
@@ -765,6 +1008,34 @@ static MenuItemHandlerResult menuhandlerScreenShake(s32 operation, struct menuit
return 0;
}
static MenuItemHandlerResult menuhandlerGlareBrightness(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
case MENUOP_GETSLIDER:
data->slider.value = videoGetGlareBrightness() * 10.f + 0.5f;
break;
case MENUOP_SET:
videoSetGlareBrightness((f32)data->slider.value / 10.f);
break;
}
return 0;
}
static MenuItemHandlerResult menuhandlerOverexposureScale(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
case MENUOP_GETSLIDER:
data->slider.value = videoGetOverexposureScale() * 10.f + 0.5f;
break;
case MENUOP_SET:
videoSetOverexposureScale((f32)data->slider.value / 10.f);
break;
}
return 0;
}
struct menuitem g_ExtendedVideoMenuItems[] = {
{
MENUITEMTYPE_CHECKBOX,
@@ -775,25 +1046,89 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
menuhandlerFullScreen,
},
{
MENUITEMTYPE_CHECKBOX,
MENUITEMTYPE_DROPDOWN,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Maximize Window",
(uintptr_t)"Full Screen Mode",
0,
menuhandlerMaximizeWindow,
menuhandlerFullScreenMode,
},
{
MENUITEMTYPE_DROPDOWN,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Resolution",
0,
menuhandlerResolution,
},
{
MENUITEMTYPE_CHECKBOX,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Detail Textures",
(uintptr_t)"Center Window",
0,
menuhandlerTexDetail,
menuhandlerCenterWindow,
},
{
MENUITEMTYPE_DROPDOWN,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Anti-aliasing",
0,
menuhandlerMSAA,
},
{
MENUITEMTYPE_SEPARATOR,
0,
0,
0,
0,
NULL,
},
{
MENUITEMTYPE_DROPDOWN,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Vsync",
0,
menuhandlerVsync,
},
{
MENUITEMTYPE_SLIDER,
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE | MENUITEMFLAG_SLIDER_DEFERRED,
(uintptr_t)"Framerate Limit",
VIDEO_MAX_FPS,
menuhandlerFramerateLimit,
},
{
MENUITEMTYPE_CHECKBOX,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Uncap Tickrate",
0,
menuhandlerUncapTickrate,
},
{
MENUITEMTYPE_CHECKBOX,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Display FPS",
0,
menuhandlerDisplayFPS,
},
{
MENUITEMTYPE_SEPARATOR,
0,
0,
0,
0,
NULL,
},
{
MENUITEMTYPE_DROPDOWN,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Texture Filtering",
0,
menuhandlerTexFilter,
@@ -806,13 +1141,29 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
0,
menuhandlerTexFilter2D,
},
{
MENUITEMTYPE_SLIDER,
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Anisotropic Filtering",
8,
menuhandlerAnisotropicFiltering,
},
{
MENUITEMTYPE_CHECKBOX,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"GE64-style Muzzle Flashes",
(uintptr_t)"Detail Textures",
0,
menuhandlerGeMuzzleFlashes,
menuhandlerTexDetail,
},
{
MENUITEMTYPE_SEPARATOR,
0,
0,
0,
0,
NULL,
},
{
MENUITEMTYPE_DROPDOWN,
@@ -822,6 +1173,14 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
0,
menuhandlerCenterHUD,
},
{
MENUITEMTYPE_CHECKBOX,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"GE64-style Muzzle Flashes",
0,
menuhandlerGeMuzzleFlashes,
},
{
MENUITEMTYPE_SLIDER,
0,
@@ -838,6 +1197,30 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
0,
NULL,
},
{
MENUITEMTYPE_SLIDER,
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Glare Brightness",
10,
menuhandlerGlareBrightness,
},
{
MENUITEMTYPE_SLIDER,
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Overexposure Scale",
10,
menuhandlerOverexposureScale,
},
{
MENUITEMTYPE_SEPARATOR,
0,
0,
0,
0,
NULL,
},
{
MENUITEMTYPE_SELECTABLE,
0,
@@ -908,6 +1291,21 @@ struct menudialogdef g_ExtendedAudioMenuDialog = {
NULL,
};
static MenuItemHandlerResult menuhandlerUseKeyReloads(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
case MENUOP_CHECKDISABLED:
return !g_PlayerExtCfg[g_ExtMenuPlayer].extcontrols;
case MENUOP_GET:
return g_PlayerExtCfg[g_ExtMenuPlayer].usereloads;
case MENUOP_SET:
g_PlayerExtCfg[g_ExtMenuPlayer].usereloads = data->checkbox.value;
break;
}
return 0;
}
static MenuItemHandlerResult menuhandlerCrouchMode(s32 operation, struct menuitem *item, union handlerdata *data)
{
static const char *opts[] = {
@@ -944,6 +1342,7 @@ static MenuItemHandlerResult menuhandlerFieldOfView(s32 operation, struct menuit
g_PlayerExtCfg[g_ExtMenuPlayer].fovy = data->slider.value;
if (g_PlayerExtCfg[g_ExtMenuPlayer].fovzoom) {
g_PlayerExtCfg[g_ExtMenuPlayer].fovzoommult = g_PlayerExtCfg[g_ExtMenuPlayer].fovy / 60.f;
playerClampGunZoomFovY(g_ExtMenuPlayer);
}
}
break;
@@ -966,6 +1365,22 @@ static MenuItemHandlerResult menuhandlerCrosshairSway(s32 operation, struct menu
return 0;
}
static MenuItemHandlerResult menuhandlerCrosshairEdgeBoundary(s32 operation, struct menuitem* item, union handlerdata *data)
{
switch (operation) {
case MENUOP_GETSLIDER:
data->slider.value = (s32)(g_PlayerExtCfg[g_ExtMenuPlayer].crosshairedgeboundary * 10.f + 0.5f);
break;
case MENUOP_SET:
g_PlayerExtCfg[g_ExtMenuPlayer].crosshairedgeboundary = (f32)data->slider.value / 10.f;
break;
case MENUOP_GETSLIDERLABEL:
sprintf(data->slider.label, "%d", (s32)data->slider.value);
break;
}
return 0;
}
static MenuItemHandlerResult menuhandlerCrosshairR(s32 operation, struct menuitem* item, union handlerdata* data)
{
u32 newColor;
@@ -1187,6 +1602,14 @@ struct menuitem g_ExtendedGameMenuItems[] = {
20,
menuhandlerCrosshairSway,
},
{
MENUITEMTYPE_SLIDER,
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Crosshair Edge Deadzone",
10,
menuhandlerCrosshairEdgeBoundary,
},
{
MENUITEMTYPE_SLIDER,
0,
@@ -1211,6 +1634,14 @@ struct menuitem g_ExtendedGameMenuItems[] = {
0,
menuhandlerCrosshairHealth,
},
{
MENUITEMTYPE_CHECKBOX,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Use Key Reloads",
0,
menuhandlerUseKeyReloads,
},
{
MENUITEMTYPE_SEPARATOR,
0,
@@ -1313,6 +1744,8 @@ static const struct menubind menuBinds[] = {
{ CK_8000, "Cycle Crouch [+]\n", "N64 Ext 8000\n" },
{ CK_4000, "Half Crouch [+]\n", "N64 Ext 4000\n" },
{ CK_2000, "Full Crouch [+]\n", "N64 Ext 2000\n" },
{ CK_ACCEPT, "UI Accept [+]\n", "EXT UI Accept\n" },
{ CK_CANCEL, "UI Cancel [+]\n", "EXT UI Cancel\n" },
};
static const char *menutextBind(struct menuitem *item);
@@ -1350,6 +1783,8 @@ struct menuitem g_ExtendedBindsMenuItems[] = {
DEFINE_MENU_BIND(),
DEFINE_MENU_BIND(),
DEFINE_MENU_BIND(),
DEFINE_MENU_BIND(),
DEFINE_MENU_BIND(),
{
MENUITEMTYPE_SEPARATOR,
0,
@@ -1586,3 +2021,22 @@ struct menudialogdef g_ExtendedMenuDialog = {
MENUDIALOGFLAG_LITERAL_TEXT,
NULL,
};
void updateMaxAnisotropyLevel()
{
for (int i = 0; i < ARRAYCOUNT(g_ExtendedVideoMenuItems); ++i) {
struct menuitem *item = &g_ExtendedVideoMenuItems[i];
const char *text = menuResolveParam2Text(item);
if (text && strstr(text, "Anisotropic Filtering") != NULL) {
item->param3 = videoGetMaxAnisotropyLevel();
break;
}
}
}
void optionsMenuInit()
{
updateMaxAnisotropyLevel();
}
+7 -2
View File
@@ -225,6 +225,8 @@ void mainInit(void)
joyInit();
joyReset();
var8005d9b0 = rmonIsDisabled();
g_Is4Mb = (osGetMemSize() <= 0x400000);
g_VmShowStats = 0;
@@ -257,7 +259,7 @@ void mainInit(void)
frametimeInit();
profileInit();
smokesInit();
mpInit();
mpInit(true);
pheadInit();
paksInit();
pheadInit2();
@@ -460,6 +462,9 @@ void mainLoop(void)
}
if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) {
if (g_MpSetup.chrslots & 0xfff0) {
g_MpSetup.storedbotbits = g_MpSetup.chrslots & 0xfff0;
}
g_MpSetup.chrslots = 0x03;
mpReset();
} else if (g_Vars.perfectbuddynum) {
@@ -570,7 +575,7 @@ void mainTick(void)
viUpdateMode();
}
rdpCreateTask(gdlstart, gdl, 0, (s32) &msg);
rdpCreateTask(gdlstart, gdl, 0, (uintptr_t) &msg);
memaPrint();
profileSetMarker(PROFILE_MAINTICK_END);
}
File diff suppressed because it is too large. Load diff
+31
View File
@@ -0,0 +1,31 @@
#include "preprocess/common.h"
static struct ptrmarker ptrMarkers[MAX_PTR_MARKERS];
static int numPtrMarkers;
void ptrAdd(u32 ptr_src, uintptr_t ptr_host)
{
if (numPtrMarkers >= ARRAYCOUNT(ptrMarkers)) {
sysFatalError("ptrAdd(%p, %p): ptrmarker limit exceeded", (void *)(uintptr_t)ptr_src, (void *)ptr_host);
}
ptrMarkers[numPtrMarkers].ptr_src = ptr_src;
ptrMarkers[numPtrMarkers].ptr_host = ptr_host;
numPtrMarkers++;
}
struct ptrmarker *ptrFind(uintptr_t ptr_src)
{
for (int i = 0; i < numPtrMarkers; i++) {
if (ptrMarkers[i].ptr_src == ptr_src) {
return &ptrMarkers[i];
}
}
return NULL;
}
void ptrReset(void)
{
numPtrMarkers = 0;
}
+524
View File
@@ -0,0 +1,524 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "data.h"
#include "bss.h"
#include "preprocess/common.h"
#include "preprocess/gbi.h"
/**
* 4 bytes decompressed size of primary data
* 4 bytes compressed size of section 1 in its entirety
* 4 bytes compressed size of primary data
* Section 1:
* Primary: (zipped)
* 4 bytes null
* 4 bytes pointer to room table
* 4 bytes pointer to portal table
* 4 bytes pointer to bgcmds
* 4 bytes pointer to lights table
* 4 bytes null
* (room table)
* (portal table)
* (bgcmds)
* (lights table)
* room 1 (zipped)
* room 2 (zipped)
* ...
* Section 2:
* 2 bytes decompressed size of section (mask with 0x7fff)
* 2 bytes compressed size of section
* Texture ID list (zipped)
* Section 3:
* 2 bytes decompressed size of section (mask with 0x7fff)
* 2 bytes compressed size of section
* Zipped:
* (room bbox table)
* (list of roomgfxdata sizes)
* (list of light counts per room)
*/
struct fileheader {
u32 primary_infsize;
u32 section1_cmpsize;
u32 primary_cmpsize;
};
struct sectionheader {
u16 infsize;
u16 cmpsize;
};
struct n64_primaryheader {
u32 unused1;
u32 ptr_rooms;
u32 ptr_portals;
u32 ptr_bgcmds;
u32 ptr_lights;
u32 unused2;
};
struct host_primaryheader {
uintptr_t unused1;
uintptr_t ptr_rooms;
uintptr_t ptr_portals;
uintptr_t ptr_bgcmds;
uintptr_t ptr_lights;
uintptr_t unused2;
};
struct n64_bgroom {
u32 ptr_gfxdata;
struct coord pos;
u8 br_light_min;
u8 br_light_max;
};
struct n64_roomblock {
u8 type;
u32 ptr_next;
u32 ptr_gdl;
u32 ptr_vertices;
u32 ptr_colours;
};
struct n64_roomgfxdata {
u32 ptr_vertices;
u32 ptr_colours;
u32 ptr_opablocks;
u32 ptr_xlublocks;
s16 lightsindex;
s16 numlights;
s16 numvertices;
s16 numcolours;
// roomblocks[]
};
struct vtx {
s16 coord[3];
u8 flag;
u8 color;
u16 s;
u16 t;
};
static void convertPrimaryRooms(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos)
{
struct n64_bgroom *n64_rooms = (struct n64_bgroom *) &src[*srcpos];
struct bgroom *host_rooms = (struct bgroom *) &dst[*dstpos];
s32 numRooms = 0;
for (int i = 1; n64_rooms[i].ptr_gfxdata != 0; i++) {
numRooms++;
}
for (int i = 0; i < numRooms + 1; i++) {
host_rooms[i].unk00 = PD_BE32(n64_rooms[i].ptr_gfxdata);
host_rooms[i].pos = PD_SWAPPED_VAL(n64_rooms[i].pos);
host_rooms[i].br_light_min = n64_rooms[i].br_light_min;
host_rooms[i].br_light_max = n64_rooms[i].br_light_max;
}
*srcpos += sizeof(*n64_rooms) * (numRooms + 2);
*dstpos += sizeof(*host_rooms) * (numRooms +2);
}
static void convertPrimaryPortals(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos, u32 *src_portalvtxs, u32 *dst_portalvtxs)
{
struct bgportal *n64_portals = (struct bgportal *) &src[*srcpos];
struct bgportal *host_portals = (struct bgportal *) &dst[*dstpos];
// Count portals
int numportals = 0;
for (int i = 0; n64_portals[i].verticesoffset != 0; i++) {
numportals++;
}
// Convert portals
for (int i = 0; i < numportals; i++) {
host_portals[i].verticesoffset = PD_BE16(n64_portals[i].verticesoffset);
host_portals[i].roomnum1 = PD_BE16(n64_portals[i].roomnum1);
host_portals[i].roomnum2 = PD_BE16(n64_portals[i].roomnum2);
host_portals[i].flags = n64_portals[i].flags;
}
*srcpos += sizeof(*n64_portals) * (numportals + 1);
*dstpos += sizeof(*host_portals) * (numportals + 1);
*src_portalvtxs = *srcpos;
*dst_portalvtxs = *dstpos;
while (1) {
struct portalvertices *n64_pvertices = (struct portalvertices *)&src[*srcpos];
struct portalvertices *host_pvertices = (struct portalvertices *)&dst[*dstpos];
host_pvertices->count = n64_pvertices->count;
for (int j = 0; j < host_pvertices->count; j++) {
host_pvertices->vertices[j] = PD_SWAPPED_VAL(n64_pvertices->vertices[j]);
}
*srcpos += 4 + host_pvertices->count * 12;
*dstpos += 4 + host_pvertices->count * 12;
if (host_pvertices->count == 0) break;
}
}
static void convertPrimaryBgCmds(u8 *dst, u32 *dstpos, u8 *src, u32 dst_portalvtxs, u32 src_portalvtxs)
{
struct bgcmd *n64_cmds = (struct bgcmd *) src;
struct bgcmd *host_cmds = (struct bgcmd *) &dst[*dstpos];
int num_cmds = 0;
for (int i = 0; n64_cmds[i].type != 0; i++) {
num_cmds++;
}
num_cmds++;
for (int i = 0; i < num_cmds; i++) {
host_cmds[i].type = n64_cmds[i].type;
host_cmds[i].len = n64_cmds[i].len;
host_cmds[i].param = PD_BE32(n64_cmds[i].param);
if (host_cmds[i].type == 0x64) {
u32 offset = host_cmds[i].param - src_portalvtxs;
host_cmds[i].param = dst_portalvtxs + offset;
}
}
*dstpos += sizeof(*host_cmds) * num_cmds;
}
static void convertPrimaryLights(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos, u32 end)
{
struct light *n64_lights = (struct light *) &src[*srcpos];
struct light *host_lights = (struct light *) &dst[*dstpos];
int num_lights = (end - *srcpos) / sizeof(struct light);
for (int i = 0; i < num_lights; i++) {
host_lights[i].roomnum = PD_BE16(n64_lights[i].roomnum);
host_lights[i].colour = PD_BE16(n64_lights[i].colour);
host_lights[i].brightness = n64_lights[i].brightness;
host_lights[i].sparkable = n64_lights[i].sparkable;
host_lights[i].healthy = n64_lights[i].healthy;
host_lights[i].on = n64_lights[i].on;
host_lights[i].sparking = n64_lights[i].sparking;
host_lights[i].vulnerable = n64_lights[i].vulnerable;
host_lights[i].brightnessmult = n64_lights[i].brightnessmult;
host_lights[i].dirx = n64_lights[i].dirx;
host_lights[i].diry = n64_lights[i].diry;
host_lights[i].dirz = n64_lights[i].dirz;
for (int j = 0; j < 4; j++) {
host_lights[i].bbox[j].x = PD_BE16(n64_lights[i].bbox[j].x);
host_lights[i].bbox[j].y = PD_BE16(n64_lights[i].bbox[j].y);
host_lights[i].bbox[j].z = PD_BE16(n64_lights[i].bbox[j].z);
}
}
*srcpos += sizeof(*n64_lights) * num_lights;
*dstpos += ALIGN(sizeof(*host_lights) * num_lights, 4);
}
#define BLOCK_LEAF 0
#define BLOCK_PARENT 1
void relinkPtr(uintptr_t* ptr)
{
if (!*ptr) return;
struct ptrmarker* marker = ptrFind(*ptr);
if (!marker) {
sysFatalError("[BG] WARNING: Unable to relink pointer: %p\n", ptr);
}
*ptr = marker->ptr_host;
}
static u32 convertRoomGfxData(u8 *dst, u8 *src, u32 infsize, u32 src_ofs)
{
ptrReset();
gbiReset();
u32 dst_roomoffset = src_ofs;
uintptr_t gdls_addr[64];
int numgdls = 0;
struct n64_roomgfxdata *src_header = (struct n64_roomgfxdata*)src;
struct roomgfxdata *dst_header = (struct roomgfxdata*)dst;
dst_header->vertices = (void *)(uintptr_t)PD_BE32(src_header->ptr_vertices);
dst_header->colours = (void *)(uintptr_t)PD_BE32(src_header->ptr_colours);
dst_header->opablocks = (void *)(uintptr_t)PD_BE32(src_header->ptr_opablocks);
dst_header->xlublocks = (void *)(uintptr_t)PD_BE32(src_header->ptr_xlublocks);
dst_header->lightsindex = PD_BE16(src_header->lightsindex);
dst_header->numlights = PD_BE16(src_header->numlights);
dst_header->numvertices = PD_BE16(src_header->numvertices);
dst_header->numcolours = PD_BE16(src_header->numcolours);
intptr_t endpos = (uintptr_t)dst_header->vertices - src_ofs;
uintptr_t curpos_src = sizeof(struct n64_roomgfxdata);
uintptr_t curpos_dst = sizeof(struct roomgfxdata) - sizeof(struct roomblock); // compensate for the [1]
// roomblocks
int ncoords = 0;
// save the ptr to roomblocks here to iterate later to fix the pointers
struct roomblock *ptr_dst_roomblocks = (struct roomblock*)&dst[curpos_dst];
int numblocks = 0;
while ((intptr_t)(curpos_src + sizeof(struct n64_roomblock)) <= endpos) {
struct n64_roomblock *src_roomblock = (struct n64_roomblock*)&src[curpos_src];
struct roomblock *dest_roomblock = (struct roomblock*)&dst[curpos_dst];
dest_roomblock->type = src_roomblock->type;
dest_roomblock->next = (void *)(uintptr_t)PD_BE32(src_roomblock->ptr_next);
dest_roomblock->gdl = (void *)(uintptr_t)PD_BE32(src_roomblock->ptr_gdl);
dest_roomblock->vertices = (void *)(uintptr_t)PD_BE32(src_roomblock->ptr_vertices);
dest_roomblock->colours = (void *)(uintptr_t)PD_BE32(src_roomblock->ptr_colours);
ptrAdd(curpos_src + src_ofs, curpos_dst + dst_roomoffset);
if (src_roomblock->type == BLOCK_PARENT) {
ncoords++;
uintptr_t vtx_ptr = (uintptr_t)dest_roomblock->vertices - src_ofs;
if (vtx_ptr < endpos) endpos = vtx_ptr;
}
else if (src_roomblock->ptr_gdl) {
gdls_addr[numgdls++] = PD_BE32(src_roomblock->ptr_gdl) - src_ofs;
}
curpos_src += sizeof(struct n64_roomblock);
curpos_dst += sizeof(struct roomblock);
numblocks++;
}
// block coords
for (size_t i = 0; i < ncoords; i++) {
u32 *src_coord = (u32*)(src + curpos_src);
u32 *dst_coord = (u32*)(dst + curpos_dst);
dst_coord[0] = PD_BE32(src_coord[0]);
dst_coord[1] = PD_BE32(src_coord[1]);
dst_coord[2] = PD_BE32(src_coord[2]);
dst_coord[3] = PD_BE32(src_coord[3]);
dst_coord[4] = PD_BE32(src_coord[4]);
dst_coord[5] = PD_BE32(src_coord[5]);
ptrAdd(curpos_src + src_ofs, curpos_dst + dst_roomoffset);
curpos_src += 6 * sizeof(u32);
curpos_dst += 6 * sizeof(u32);
}
curpos_dst = ALIGN8(curpos_dst);
// vertices
uintptr_t ptr_src_vertices = curpos_src = ALIGN8((uintptr_t)dst_header->vertices - src_ofs);
uintptr_t ptr_dst_vertices = curpos_dst + dst_roomoffset;
ptrAdd(curpos_src + src_ofs, curpos_dst + dst_roomoffset);
uintptr_t vtx_end = (uintptr_t)dst_header->colours - src_ofs;
while (dst_header->colours && curpos_src < vtx_end) {
struct vtx *src_vtx = (struct vtx*)(src + curpos_src);
struct vtx *dst_vtx = (struct vtx*)(dst + curpos_dst);
dst_vtx->coord[0] = PD_BE16(src_vtx->coord[0]);
dst_vtx->coord[1] = PD_BE16(src_vtx->coord[1]);
dst_vtx->coord[2] = PD_BE16(src_vtx->coord[2]);
dst_vtx->flag = src_vtx->flag;
dst_vtx->color = src_vtx->color;
dst_vtx->s = PD_BE16(src_vtx->s);
dst_vtx->t = PD_BE16(src_vtx->t);
curpos_src += sizeof(struct vtx);
curpos_dst += sizeof(struct vtx);
}
curpos_dst = ALIGN8(curpos_dst);
// colors
uintptr_t ptr_src_colors = 0;
uintptr_t ptr_dst_colors = 0;
if (dst_header->colours) {
ptr_src_colors = curpos_src = ALIGN8((uintptr_t)dst_header->colours - src_ofs);
ptr_dst_colors = curpos_dst + dst_roomoffset;
ptrAdd(curpos_src + src_ofs, curpos_dst + dst_roomoffset);
uintptr_t col_end = (numgdls > 0) ? gdls_addr[0] : infsize;
size_t col_len = col_end - curpos_src;
memcpy(dst + curpos_dst, src + curpos_src, col_len);
curpos_src += col_len;
curpos_dst += col_len;
}
// gdls
gbiSetVtx(src_header->ptr_vertices, ptr_src_vertices);
gbiSetSegment(0x0e, (uintptr_t)dst_header->vertices);
uintptr_t gdlstart = curpos_dst;
for (size_t i = 0; i < numgdls; i++) {
ptrAdd(gdls_addr[i] + src_ofs, curpos_dst + dst_roomoffset);
curpos_dst = gbiConvertGdl(dst, curpos_dst, src, gdls_addr[i], 1);
}
// relink ptrs: roomblocks
for (size_t i = 0; i < numblocks; i++) {
struct roomblock *block = (struct roomblock*)&ptr_dst_roomblocks[i];
relinkPtr((uintptr_t*)&block->next);
if (block->type == BLOCK_LEAF) {
relinkPtr((uintptr_t*)&block->gdl);
u32 offset_vtx = (uintptr_t)block->vertices - ptr_src_vertices - src_ofs;
u32 offset_col = (uintptr_t)block->colours - ptr_src_colors - src_ofs;
block->vertices = (void *)(ptr_dst_vertices + offset_vtx);
block->colours = (void *)(ptr_dst_colors + offset_col);
}
else {
relinkPtr((uintptr_t*)&block->gdl); // child
relinkPtr((uintptr_t*)&block->vertices); // coord
}
}
// relink ptrs: header
relinkPtr((uintptr_t*)&dst_header->vertices);
relinkPtr((uintptr_t*)&dst_header->colours);
relinkPtr((uintptr_t*)&dst_header->opablocks);
relinkPtr((uintptr_t*)&dst_header->xlublocks);
return curpos_dst;
}
static u32 convertSection1(u8 *dst, u8 *src, u32 ofs)
{
// Convert primary
u32 srcpos = 0;
u32 dstpos = 0;
struct host_primaryheader *host_primary_header = (struct host_primaryheader *) dst;
struct n64_primaryheader *n64_primary_header = (struct n64_primaryheader *) src;
srcpos += sizeof(struct n64_primaryheader);
dstpos += sizeof(*host_primary_header);
u32 src_bgcmds = PD_BE32(n64_primary_header->ptr_bgcmds) - ofs;
host_primary_header->unused1 = 0;
host_primary_header->unused2 = 0;
host_primary_header->ptr_rooms = dstpos + ofs;
convertPrimaryRooms(dst, &dstpos, src, &srcpos);
if (n64_primary_header->ptr_lights) {
host_primary_header->ptr_lights = dstpos + ofs;
srcpos = PD_BE32(n64_primary_header->ptr_lights) - ofs;
convertPrimaryLights(dst, &dstpos, src, &srcpos, src_bgcmds);
}
host_primary_header->ptr_portals = dstpos + ofs;
srcpos = PD_BE32(n64_primary_header->ptr_portals) - ofs;
u32 src_portalvtxs, dst_portalvtxs;
convertPrimaryPortals(dst, &dstpos, src, &srcpos, &src_portalvtxs, &dst_portalvtxs);
host_primary_header->ptr_bgcmds = dstpos + ofs;
convertPrimaryBgCmds(dst, &dstpos, &src[src_bgcmds], dst_portalvtxs, src_portalvtxs);
return dstpos;
}
void preprocessBgSection1(u8 *data, u32 size, u32 ofs)
{
u8 *dst = sysMemZeroAlloc(size);
u32 newSize = convertSection1(dst, data, ofs);
if (newSize > size) {
sysFatalError("overflow when trying to preprocess a bg file, size %d newsize %d", size, newSize);
}
memcpy(data, dst, newSize);
sysMemFree(dst);
}
u32 preprocessBgRoom(u8 *data, u32 size, u32 room_ofs)
{
size *= 2;
u8 *dst = sysMemZeroAlloc(size);
u32 newSize = convertRoomGfxData(dst, data, size, room_ofs);
if (newSize > size) {
sysFatalError("overflow when trying to preprocess a bg room, size %d newsize %d", size, newSize);
}
memcpy(data, dst, newSize);
sysMemFree(dst);
return newSize;
}
void preprocessBgSection1Header(u8* data, u32 size)
{
u32* header = (u32*)data;
PD_SWAP_VAL(header[0]); // inflatedsize
PD_SWAP_VAL(header[1]); // section1size
PD_SWAP_VAL(header[2]); // primcompsize
}
void preprocessBgSection2Header(u8* data, u32 size)
{
u16* header = (u16*)data;
PD_SWAP_VAL(header[0]); // inflatedsize
PD_SWAP_VAL(header[1]); // section2compsize
}
void preprocessBgSection2(u8* data, u32 size)
{
// section2 is a texture id list
u16* section2 = (u16*)data;
for (s32 i = 0; i < size; ++i) {
PD_SWAP_VAL(section2[i]);
}
}
void preprocessBgSection3Header(u8* data, u32 size)
{
u16* header = (u16*)data;
PD_SWAP_VAL(header[0]);
PD_SWAP_VAL(header[1]);
}
void preprocessBgSection3(u8* data, u32 size)
{
// room bounding boxes, 6x s16 per room
s16* bbox = (s16*)data;
for (s32 i = 1; i < g_Vars.roomcount; ++i) {
PD_SWAP_VAL(*bbox); ++bbox;
PD_SWAP_VAL(*bbox); ++bbox;
PD_SWAP_VAL(*bbox); ++bbox;
PD_SWAP_VAL(*bbox); ++bbox;
PD_SWAP_VAL(*bbox); ++bbox;
PD_SWAP_VAL(*bbox); ++bbox;
}
// gfxdatalen list
u16* gfxdatalen = (u16*)bbox;
for (s32 i = 1; i < g_Vars.roomcount; ++i) {
PD_SWAP_VAL(*gfxdatalen); ++gfxdatalen;
}
}
+92
View File
@@ -0,0 +1,92 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "preprocess/common.h"
static int getNextNonZero(u8 *src, u32 offset, size_t len)
{
u32 *ptr = (u32 *) &src[offset];
u32 *end = (u32 *) &src[len];
while (ptr < end) {
if (*ptr != 0) {
return PD_BE32(*ptr);
}
ptr++;
}
return 0;
}
static int getNumStrings(u8 *src, size_t len)
{
u32 ptr_table_len = getNextNonZero(src, 0, len);
if (ptr_table_len) {
return ptr_table_len / sizeof(u32);
}
return 1;
}
static u32 convertLangFile(u8 *dst, u8 *src, size_t srclen)
{
// Convert it
u32 *src_offsets = (u32 *) src;
size_t src_ptr_table_len = PD_BE32(src_offsets[0]);
size_t src_str_table_len = srclen - src_ptr_table_len;
int num_strings = getNumStrings(src, srclen);
size_t dst_ptr_table_len = num_strings * sizeof(uintptr_t);
size_t dst_str_table_len = src_str_table_len;
int cur_dst_offset = dst_ptr_table_len;
uintptr_t *dst_offsets = (uintptr_t *) dst;
for (int i = 0; i < num_strings; i++) {
u32 src_offset = PD_BE32(src_offsets[i]);
if (src_offset) {
// Write pointer
dst_offsets[i] = (cur_dst_offset);
// Write string
u32 end = getNextNonZero(src, (i + 1) * 4, num_strings * 4);
if (!end) {
end = srclen;
}
size_t len = end - src_offset;
len = ALIGN4(len);
memcpy(&dst[cur_dst_offset], &src[src_offset], len);
cur_dst_offset += len;
} else {
// Write pointer
dst_offsets[i] = 0;
}
}
return ALIGN16(cur_dst_offset);
}
u8 *preprocessLangFile(u8 *data, u32 size, u32 *outSize) {
u32 newSizeEstimated = romdataFileGetEstimatedSize(size, LOADTYPE_LANG);
u8 *dst = sysMemZeroAlloc(newSizeEstimated);
u32 newSize = convertLangFile(dst, data, size);
if (newSize > newSizeEstimated) {
sysFatalError("overflow when trying to preprocess a lang file, size %d newsize %d", size, newSize);
}
memcpy(data, dst, newSize);
sysMemFree(dst);
*outSize = newSize;
return 0;
}
File diff suppressed because it is too large. Load diff
+292
View File
@@ -0,0 +1,292 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "preprocess/common.h"
#include "constants.h"
struct n64_header {
s32 num_pads;
s32 num_covers;
u32 ptr_waypoints;
u32 ptr_waygroups;
u32 ptr_cover;
};
struct host_header {
s32 num_pads;
s32 num_covers;
uintptr_t ptr_waypoints;
uintptr_t ptr_waygroups;
uintptr_t ptr_cover;
};
struct padheader {
u32 flags : 18;
u32 room : 10;
u32 liftnum : 4;
};
struct n64_waypoint {
s32 padnum;
u32 ptr_neighbours;
s32 groupnum;
s32 step;
};
struct n64_waygroup {
u32 ptr_neighbours;
u32 ptr_waypoints;
s32 step;
};
static u32 convertPads(u8 *dst, u32 dstpos, u8 *src, u32 srcpos, int num_pads)
{
u16 *src_offsets = (u16 *) &src[srcpos];
u16 *dst_offsets = (u16 *) &dst[dstpos];
dstpos += num_pads * sizeof(u16);
for (int i = 0; i < num_pads; i++) {
srcpos = PD_BE16(src_offsets[i]);
dst_offsets[i] = (dstpos);
// Header
u32 n64_padheader = PD_BE32(*(u32 *) &src[srcpos]);
struct padheader *host_padheader = (struct padheader *) &dst[dstpos];
u32 flags = (n64_padheader >> 14) & 0x3ffff;
*(u32*)host_padheader = (n64_padheader);
srcpos += sizeof(struct padheader);
dstpos += sizeof(struct padheader);
// Position
if (flags & PADFLAG_INTPOS) {
s16 *srcptr = (s16 *) &src[srcpos];
s16 *dstptr = (s16 *) &dst[dstpos];
dstptr[0] = PD_BE16(srcptr[0]);
dstptr[1] = PD_BE16(srcptr[1]);
dstptr[2] = PD_BE16(srcptr[2]);
srcpos += 8;
dstpos += 8;
} else {
u32 *srcptr = (u32 *) &src[srcpos];
u32 *dstptr = (u32 *) &dst[dstpos];
dstptr[0] = PD_BE32(srcptr[0]);
dstptr[1] = PD_BE32(srcptr[1]);
dstptr[2] = PD_BE32(srcptr[2]);
srcpos += 12;
dstpos += 12;
}
// Up
if ((flags & (PADFLAG_UPALIGNTOX | PADFLAG_UPALIGNTOY | PADFLAG_UPALIGNTOZ)) == 0) {
u32 *srcptr = (u32 *) &src[srcpos];
u32 *dstptr = (u32 *) &dst[dstpos];
dstptr[0] = PD_BE32(srcptr[0]);
dstptr[1] = PD_BE32(srcptr[1]);
dstptr[2] = PD_BE32(srcptr[2]);
srcpos += 12;
dstpos += 12;
}
// Look
if ((flags & (PADFLAG_LOOKALIGNTOX | PADFLAG_LOOKALIGNTOY | PADFLAG_LOOKALIGNTOZ)) == 0) {
u32 *srcptr = (u32 *) &src[srcpos];
u32 *dstptr = (u32 *) &dst[dstpos];
dstptr[0] = PD_BE32(srcptr[0]);
dstptr[1] = PD_BE32(srcptr[1]);
dstptr[2] = PD_BE32(srcptr[2]);
srcpos += 12;
dstpos += 12;
}
// Bbox
if (flags & PADFLAG_HASBBOXDATA) {
u32 *srcptr = (u32 *) &src[srcpos];
u32 *dstptr = (u32 *) &dst[dstpos];
dstptr[0] = PD_BE32(srcptr[0]);
dstptr[1] = PD_BE32(srcptr[1]);
dstptr[2] = PD_BE32(srcptr[2]);
dstptr[3] = PD_BE32(srcptr[3]);
dstptr[4] = PD_BE32(srcptr[4]);
dstptr[5] = PD_BE32(srcptr[5]);
srcpos += 4 * 6;
dstpos += 4 * 6;
}
}
return dstpos;
}
static u32 convertWayPoints(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
{
struct n64_waypoint *n64_waypoints = (struct n64_waypoint *) &src[srcpos];
struct waypoint *host_waypoints = (struct waypoint *) &dst[dstpos];
int num_waypoints;
for (num_waypoints = 0; n64_waypoints[num_waypoints].padnum != -1; num_waypoints++);
dstpos += (num_waypoints + 1) * sizeof(struct waypoint);
u32 *host_neighbours = (u32 *) &dst[dstpos];
int n = 0;
for (int i = 0; i < num_waypoints; i++) {
host_waypoints[i].padnum = PD_BE32(n64_waypoints[i].padnum);
host_waypoints[i].neighbours = (void *)(uintptr_t)dstpos;
host_waypoints[i].groupnum = PD_BE32(n64_waypoints[i].groupnum);
host_waypoints[i].step = 0;
u32 *n64_neighbours = (u32 *) &src[PD_BE32(n64_waypoints[i].ptr_neighbours)];
for (int j = 0; n64_neighbours[j] != 0xffffffff; j++) {
host_neighbours[n++] = PD_BE32(n64_neighbours[j]);
dstpos += 4;
}
host_neighbours[n++] = 0xffffffff;
dstpos += 4;
}
// Terminator
host_waypoints[num_waypoints].padnum = 0xffffffff;
host_waypoints[num_waypoints].neighbours = NULL;
host_waypoints[num_waypoints].groupnum = 0;
host_waypoints[num_waypoints].step = 0;
return dstpos;
}
static u32 convertWayGroups(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
{
struct n64_waygroup *n64_waygroups = (struct n64_waygroup *) &src[srcpos];
struct waygroup *host_waygroups = (struct waygroup *) &dst[dstpos];
int num_waygroups;
for (num_waygroups = 0; n64_waygroups[num_waygroups].ptr_neighbours != 0; num_waygroups++);
dstpos += (num_waygroups + 1) * sizeof(struct waygroup);
// Waygroups and child waypoints
u32 *host_waypoints = (u32 *) &dst[dstpos];
int n = 0;
for (int i = 0; i < num_waygroups; i++) {
host_waygroups[i].waypoints = (void *)(uintptr_t)dstpos;
host_waygroups[i].step = 0;
u32 *n64_waypoints = (u32 *) &src[PD_BE32(n64_waygroups[i].ptr_waypoints)];
for (int j = 0; n64_waypoints[j] != 0xffffffff; j++) {
host_waypoints[n++] = PD_BE32(n64_waypoints[j]);
dstpos += 4;
}
host_waypoints[n++] = 0xffffffff;
dstpos += 4;
}
// Terminator
host_waygroups[num_waygroups].neighbours = NULL;
host_waygroups[num_waygroups].waypoints = NULL;
host_waygroups[num_waygroups].step = 0;
// Waygroup neighbours
u32 *host_neighbours = (u32 *) &dst[dstpos];
n = 0;
for (int i = 0; i < num_waygroups; i++) {
host_waygroups[i].neighbours = (void *)(uintptr_t)dstpos;
u32 *n64_neighbours = (u32 *) &src[PD_BE32(n64_waygroups[i].ptr_neighbours)];
for (int j = 0; n64_neighbours[j] != 0xffffffff; j++) {
host_neighbours[n++] = PD_BE32(n64_neighbours[j]);
dstpos += 4;
}
host_neighbours[n++] = 0xffffffff;
dstpos += 4;
}
return dstpos;
}
static u32 convertCover(u8 *dst, u32 dstpos, u8 *src, u32 srcpos, int num_covers)
{
struct coverdefinition *n64_covers = (struct coverdefinition *) &src[srcpos];
struct coverdefinition *host_covers = (struct coverdefinition *) &dst[dstpos];
for (int i = 0; i < num_covers; i++) {
host_covers[i].pos = PD_SWAPPED_VAL(n64_covers[i].pos);
host_covers[i].look = PD_SWAPPED_VAL(n64_covers[i].look);
host_covers[i].flags = PD_BE16(n64_covers[i].flags);
}
dstpos += num_covers * sizeof(struct coverdefinition);
return dstpos;
}
static u32 convertPadsFile(u8 *dst, u8 *src)
{
u32 dstpos = 0;
struct n64_header *n64_header = (struct n64_header *) src;
struct host_header *host_header = (struct host_header *) dst;
int num_pads = PD_BE32(n64_header->num_pads);
int num_covers = PD_BE32(n64_header->num_covers);
host_header->num_pads = (num_pads);
host_header->num_covers = (num_covers);
dstpos += sizeof(struct host_header);
// Pads
dstpos = convertPads(dst, dstpos, src, sizeof(struct n64_header), num_pads);
// Waypoints
host_header->ptr_waypoints = (dstpos);
dstpos = convertWayPoints(dst, dstpos, src, PD_BE32(n64_header->ptr_waypoints));
// Waygroups
host_header->ptr_waygroups = (dstpos);
dstpos = convertWayGroups(dst, dstpos, src, PD_BE32(n64_header->ptr_waygroups));
// Cover
host_header->ptr_cover = (dstpos);
dstpos = convertCover(dst, dstpos, src, PD_BE32(n64_header->ptr_cover), num_covers);
return dstpos;
}
u8* preprocessPadsFile(u8 *data, u32 size, u32 *outSize) {
u32 newSizeEstimated = romdataFileGetEstimatedSize(size, LOADTYPE_PADS);
u8* dst = sysMemZeroAlloc(newSizeEstimated);
u32 newSize = convertPadsFile(dst, data);
if (newSize > newSizeEstimated) {
sysFatalError("overflow when trying to preprocess a pads file, size %d newsize %d", size, newSize);
}
memcpy(data, dst, newSize);
sysMemFree(dst);
*outSize = newSize;
return 0;
}
File diff suppressed because it is too large. Load diff
+103
View File
@@ -0,0 +1,103 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "preprocess/common.h"
struct tile {
u8 type;
u8 numvertices;
u16 flags;
u16 floortype;
u8 xmin;
u8 ymin;
u8 zmin;
u8 xmax;
u8 ymax;
u8 zmax;
u16 floorcol;
};
static u32 convertTiles(u8 *dst, u8 *src, size_t srclen)
{
int num_rooms = PD_BE32(*(u32 *) src);
size_t src_ptr_table_len = (num_rooms + 1) * 4;
size_t dst_ptr_table_len = (num_rooms + 1) * sizeof(u32);
u32 *src_offsets = (u32 *) &src[4];
size_t data_len = srclen - src_ptr_table_len - 4;
*(u32 *) dst = (num_rooms);
u32 *dst_offsets = (u32 *) (dst + sizeof(u32));
u32 cur_dst_offset = dst_ptr_table_len + sizeof(u32);
u32 cur_src_offset = PD_BE32(src_offsets[0]);
u32 end_src_offset = PD_BE32(src_offsets[num_rooms]);
int room = 0;
while (1) {
// Check if this is a new room and write the pointer offset if so
while (room < (num_rooms + 1) && PD_BE32(src_offsets[room]) == cur_src_offset) {
dst_offsets[room] = (cur_dst_offset);
room++;
}
if (cur_src_offset >= end_src_offset) {
break;
}
// Write tile data
struct tile *n64tile = (struct tile *) &src[cur_src_offset];
struct tile hosttile;
hosttile.type = n64tile->type;
hosttile.numvertices = n64tile->numvertices;
hosttile.flags = PD_BE16(n64tile->flags);
hosttile.floortype = PD_BE16(n64tile->floortype);
hosttile.xmin = n64tile->xmin;
hosttile.ymin = n64tile->ymin;
hosttile.zmin = n64tile->zmin;
hosttile.xmax = n64tile->xmax;
hosttile.ymax = n64tile->ymax;
hosttile.zmax = n64tile->zmax;
hosttile.floorcol = PD_BE16(n64tile->floorcol);
memcpy(&dst[cur_dst_offset], &hosttile, sizeof(struct tile));
cur_dst_offset += sizeof(struct tile);
cur_src_offset += sizeof(struct tile);
// Write tile vertices
for (int i = 0; i < hosttile.numvertices; i++) {
*(s16 *) &dst[cur_dst_offset + 0] = PD_BE16(*(s16 *) &src[cur_src_offset + 0]);
*(s16 *) &dst[cur_dst_offset + 2] = PD_BE16(*(s16 *) &src[cur_src_offset + 2]);
*(s16 *) &dst[cur_dst_offset + 4] = PD_BE16(*(s16 *) &src[cur_src_offset + 4]);
cur_dst_offset += 6;
cur_src_offset += 6;
}
}
return ALIGN16(cur_dst_offset);
}
u8 *preprocessTilesFile(u8 *data, u32 size, u32 *outSize)
{
u32 newSizeEstimated = romdataFileGetEstimatedSize(size, LOADTYPE_TILES);
u8 *dst = sysMemZeroAlloc(newSizeEstimated);
u32 newSize = convertTiles(dst, data, size);
if (newSize > newSizeEstimated) {
sysFatalError("overflow when trying to preprocess a tiles file, size %d newsize %d", size, newSize);
}
memcpy(data, dst, newSize);
sysMemFree(dst);
*outSize = newSize;
return 0;
}
+208
View File
@@ -0,0 +1,208 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "preprocess/common.h"
#include "preprocess/gbi.h"
#if UINTPTR_MAX > 0xFFFFFFFFu
#define HOST_DWORDS_PER_CMD 2
#else
#define HOST_DWORDS_PER_CMD 1
#endif
struct vtx {
s16 x;
s16 y;
s16 z;
u8 flags;
u8 colour;
s16 s;
s16 t;
};
struct texaddr {
u32 src;
u32 dst;
};
static u32 gbiSegments[16];
static u32 srcVtxOffset;
static u32 dstVtxOffset;
static struct texaddr texAddrs[64];
static int numTexAddrs;
void gbiReset(void)
{
for (int i = 0; i < ARRAYCOUNT(gbiSegments); i++) {
gbiSegments[i] = 0;
}
srcVtxOffset = 0;
dstVtxOffset = 0;
numTexAddrs = 0;
}
void gbiSetSegment(int segment, u32 offset)
{
gbiSegments[segment] = offset & 0x00ffffff;
}
void gbiSetVtx(u32 src_offset, u32 dst_offset)
{
srcVtxOffset = src_offset & 0x00ffffff;
dstVtxOffset = dst_offset & 0x00ffffff;
}
void gbiAddTexAddr(u32 src_offset, u32 dst_offset)
{
texAddrs[numTexAddrs].src = src_offset & 0x00ffffff;
texAddrs[numTexAddrs++].dst = dst_offset & 0x00ffffff;
}
u32 gbiFindTexAddr(u32 src_offset)
{
for (int i = 0; i < numTexAddrs; i++) {
if (texAddrs[i].src == src_offset)
return texAddrs[i].dst;
}
return 0;
}
void gbiConvertVtx(u8 *dst, u32 offset, int count)
{
if (!offset) return;
struct vtx* vtxs = (struct vtx*)(dst + offset);
for (int i = 0; i < count; i++) {
struct vtx* vtx = &vtxs[i];
vtx->x = PD_BE16(vtx->x);
vtx->y = PD_BE16(vtx->y);
vtx->z = PD_BE16(vtx->z);
vtx->s = PD_BE16(vtx->s);
vtx->t = PD_BE16(vtx->t);
}
}
#define CMD_IS_VTX(cmd) ((cmd & 0xff00000000000000) == 0x0400000000000000)
#define CMD_IS_DL(cmd) ((cmd & 0xff00000000000000) == 0x0600000000000000)
#define CMD_IS_COL(cmd) ((cmd & 0xff00000000000000) == 0x0700000000000000)
#define CMD_IS_ENDDL(cmd) ((cmd & 0xff00000000000000) == 0xb800000000000000)
#define CMD_IS_MOVEWORD(cmd) ((cmd & 0xff00000000000000) == 0xbc00000000000000)
#define CMD_IS_MOVEMEM(cmd) ((cmd & 0xff00000000000000) == 0x0300000000000000)
#define CMD_IS_MTX(cmd) ((cmd & 0xff00000000000000) == 0x0100000000000000)
#define CMD_IS_SETTIMG(cmd) ((cmd & 0xff00000000000000) == 0xfd00000000000000)
#define CMD_IS_SETZIMG(cmd) ((cmd & 0xff00000000000000) == 0xfe00000000000000)
#define CMD_IS_SETCIMG(cmd) ((cmd & 0xff00000000000000) == 0xff00000000000000)
#define CMD_HAS_ADDR(cmd) CMD_IS_VTX(cmd) \
|| CMD_IS_COL(cmd) \
|| CMD_IS_MOVEWORD(cmd) \
|| CMD_IS_SETTIMG(cmd)
#define CMD_IS_SEGMENTED(cmd) ( CMD_IS_MOVEMEM(cmd) \
|| CMD_IS_MTX(cmd) \
|| CMD_IS_VTX(cmd) \
|| CMD_IS_COL(cmd) \
|| CMD_IS_DL(cmd) \
|| CMD_IS_SETTIMG(cmd) \
|| CMD_IS_SETCIMG(cmd) \
|| CMD_IS_SETZIMG(cmd))
/**
* Segment 5 is the start of the model file. The data in these files shifts
* depending on the pointer size, so this function adjusts the offset accordingly.
*/
static u64 gbiRewriteAddr(u64 cmd, u8 opcode)
{
u8 segment = (cmd & 0x0f000000) >> 24;
u32 offset = cmd & 0x00ffffff;
if (segment == 5) {
if (opcode == 0xfd) {
offset = gbiFindTexAddr(offset);
}
else {
if (offset < srcVtxOffset) {
sysFatalError("Tried to load data from offset 0x%x but segment starts at 0x%x\n", offset, srcVtxOffset);
}
offset = offset - srcVtxOffset + dstVtxOffset;
}
}
return (cmd & 0xffffffffff000000) | offset;
}
void gbiGdlRewriteAddrs(u8 *dst, u32 offset)
{
if (!offset) return;
u64 *cmds = (u64 *)(dst + (offset & 0x00ffffff));
if (!cmds) return;
u64 cmd;
do {
cmd = *cmds;
Gfx* gfxcmd = (Gfx *)cmds;
int idx = 0;
u8 opcode = (cmd >> 24) & 0xff;
#if HOST_DWORDS_PER_CMD == 2
idx = 1;
opcode = (cmd >> 24) & 0xff;
#endif
cmd = (u64)opcode << 56;
if (CMD_HAS_ADDR(cmd)) {
cmds[idx] = gbiRewriteAddr(cmds[idx], opcode);
}
if (CMD_IS_SEGMENTED(cmd)) {
gfxcmd->words.w1 |= 1;
}
cmds += HOST_DWORDS_PER_CMD;
} while (!CMD_IS_ENDDL(cmd));
}
u32 gbiConvertGdl(u8 *dst, u32 dstpos, u8 *src, u32 srcpos, int segment_cmds)
{
dstpos = ALIGN8(dstpos);
u64 *n64_cmd = (u64*)&src[srcpos];
u64 *host_cmd = (u64*)&dst[dstpos];
u64 cmd;
do {
cmd = PD_BE64(*n64_cmd);
#if HOST_DWORDS_PER_CMD == 2
host_cmd[0] = ((cmd & 0xffffffff00000000) >> 32);
host_cmd[1] = (cmd & 0xffffffff);
if (segment_cmds && CMD_IS_SEGMENTED(cmd)) {
host_cmd[1] |= 1;
}
#else
host_cmd[0] = (cmd >> 32) | ((cmd & 0xffffffff) << 32);
if (segment_cmds && CMD_IS_SEGMENTED(cmd)) {
Gfx* gfxcmd = (Gfx*)host_cmd;
gfxcmd->words.w1 |= 1;
}
#endif
dstpos += sizeof(*host_cmd) * HOST_DWORDS_PER_CMD;
host_cmd += HOST_DWORDS_PER_CMD;
n64_cmd++;
} while (!CMD_IS_ENDDL(cmd));
return dstpos;
}
+103
View File
@@ -0,0 +1,103 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <PR/ultratypes.h>
#include <PR/gbi.h>
#include "data.h"
#include "bss.h"
#include "game/setuputils.h"
#include "game/texdecompress.h"
#include "mod.h"
#include "preprocess/common.h"
u8 *preprocessAnimations(u8* data, u32 size, u32* outSize)
{
// set the anim table pointers as well
extern u8 *_animationsTableRomStart;
extern u8 *_animationsTableRomEnd;
// the animation table is at the end of the segment
u32 *animtbl = (void *)(data + size - 0x38a0);
_animationsTableRomStart = (u8 *)animtbl;
_animationsTableRomEnd = data + size;
PD_SWAP_VAL(*animtbl);
const u32 count = *animtbl++;
struct animtableentry *anim = (struct animtableentry *)animtbl;
for (u32 i = 0; i < count; ++i, ++anim) {
PD_SWAP_VAL(anim->numframes);
PD_SWAP_VAL(anim->bytesperframe);
PD_SWAP_VAL(anim->headerlen);
PD_SWAP_VAL(anim->data);
// if an external replacement exists, replace the table entry and mark the offset
if (modAnimationLoadDescriptor(i, anim) > 0) {
anim->data = 0xffffffff;
}
}
return NULL;
}
u8 *preprocessMpConfigs(u8* data, u32 size, u32* outSize)
{
const u32 count = size / sizeof(struct mpconfig);
struct mpconfig *cfg = (struct mpconfig *)data;
for (u32 i = 0; i < count; ++i, ++cfg) {
PD_SWAP_VAL(cfg->setup.options);
PD_SWAP_VAL(cfg->setup.teamscorelimit);
PD_SWAP_VAL(cfg->setup.chrslots);
// TODO: are these required or are they always 0?
PD_SWAP_VAL(cfg->setup.fileguid.deviceserial);
PD_SWAP_VAL(cfg->setup.fileguid.fileid);
// convert MPWEAPON_ to take classic weapons and JPN weapons into account
for (s32 j = 0; j < ARRAYCOUNT(cfg->setup.weapons); ++j) {
#if VERSION == VERSION_JPN_FINAL /* TODO: replace with runtime check */
if (cfg->setup.weapons[j] >= 0x24) {
// weapons after and including the shield need to be shifted (for classic weapons)
cfg->setup.weapons[j] += (MPWEAPON_SHIELD - MPWEAPON_PP9I);
}
if (cfg->setup.weapons[j] >= 0x22) {
// weapons after and including the cloaking device need to be shifted (for IR Scanner and Night Vision)
cfg->setup.weapons[j] += (MPWEAPON_CLOAKINGDEVICE - MPWEAPON_NIGHTVISION);
}
if (cfg->setup.weapons[j] >= 0x19) {
// weapons after the combat knife also need to be shifted up in JPN
cfg->setup.weapons[j]++;
}
#else
if (cfg->setup.weapons[j] >= 0x25) {
// weapons after and including the shield need to be shifted (for classic weapons)
cfg->setup.weapons[j] += (MPWEAPON_SHIELD - MPWEAPON_PP9I);
}
if (cfg->setup.weapons[j] >= 0x23) {
// weapons after and including the cloaking device need to be shifted (for IR Scanner and Night Vision)
cfg->setup.weapons[j] += (MPWEAPON_CLOAKINGDEVICE - MPWEAPON_NIGHTVISION);
}
#endif
}
}
return NULL;
}
u8 *preprocessTexturesList(u8* data, u32 size, u32* outSize)
{
struct texture *tex = (struct texture *)data;
const u32 count = size / sizeof(*tex);
for (u32 i = 0; i < count; ++i, ++tex) {
// TODO: it sure looks like none of the fields except soundsurfacetype, surfacetype and dataoffset are set
// just swap the last 3 bytes of the first word...
const u32 dofs = (u32)tex->dataoffset << 8;
tex->dataoffset = PD_BE32(dofs);
// ...and the surface types in the first byte
const u8 tmp = tex->soundsurfacetype;
tex->soundsurfacetype = tex->surfacetype;
tex->surfacetype = tmp;
}
return NULL;
}
+362
View File
@@ -0,0 +1,362 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libaudio.h"
#include "preprocess/common.h"
struct n64_adpcm_waveinfo {
u32 loop; // ptr to ALADPCMloop
u32 book; // ptr to ALADPCMBook
};
struct n64_raw_waveinfo {
u32 loop; // ptr to ALRawLoop
};
struct n64_wavetable {
u32 base;
s32 len;
u8 type;
u8 flags;
union {
struct n64_adpcm_waveinfo adpcmWave;
struct n64_raw_waveinfo rawWave;
} waveInfo;
};
struct n64_sound {
u32 envelope; // ptr to ALEnvelope
u32 keyMap; // ptr to ALKeyMap
u32 wavetable; // ptr to struct n64_wavetable
u8 samplePan;
u8 sampleVolume;
u8 flags;
};
struct n64_instrument {
u8 volume;
u8 pan;
u8 priority;
u8 flags;
u8 tremType;
u8 tremRate;
u8 tremDepth;
u8 tremDelay;
u8 vibType;
u8 vibRate;
u8 vibDepth;
u8 vibDelay;
s16 bendRange;
s16 soundCount;
u32 soundArray[1]; // ptr to struct n64_sound
};
struct n64_bank {
s16 instCount;
u8 flags;
u8 pad;
s32 sampleRate;
u32 percussion; // ptr to struct n64_instrument
u32 instArray[1]; // ptr to struct n64_instrument
};
struct n64_bankfile {
s16 revision;
s16 bankCount;
u32 bankArray[1]; // ptr to struct n64_bank
};
// only proceeds to convert the next item if it's not already converted
#define AL_NEXT_ITEM(field, func) { \
struct ptrmarker *marker = ptrFind(srcpos); \
if (marker == NULL) { \
field = (void *)(uintptr_t)(dstpos); \
ptrAdd(srcpos, (uintptr_t)(field)); \
dstpos = func(dst, dstpos, src, srcpos); \
} else { \
field = (void *)marker->ptr_host; } \
}
static u32 convertAudioEnvelope(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
{
ALEnvelope *n64_envelope = (ALEnvelope *) &src[srcpos];
ALEnvelope *host_envelope = (ALEnvelope *) &dst[dstpos];
dstpos += sizeof(ALEnvelope);
host_envelope->attackTime = PD_BE32(n64_envelope->attackTime);
host_envelope->decayTime = PD_BE32(n64_envelope->decayTime);
host_envelope->releaseTime = PD_BE32(n64_envelope->releaseTime);
host_envelope->attackVolume = n64_envelope->attackVolume;
host_envelope->decayVolume = n64_envelope->decayVolume;
return dstpos;
}
static u32 convertAudioKeyMap(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
{
ALKeyMap *n64_keymap = (ALKeyMap *) &src[srcpos];
ALKeyMap *host_keymap = (ALKeyMap *) &dst[dstpos];
dstpos += sizeof(ALKeyMap);
host_keymap->velocityMin = n64_keymap->velocityMin;
host_keymap->velocityMax = n64_keymap->velocityMax;
host_keymap->keyMin = n64_keymap->keyMin;
host_keymap->keyMax = n64_keymap->keyMax;
host_keymap->keyBase = n64_keymap->keyBase;
host_keymap->detune = n64_keymap->detune;
return dstpos;
}
static u32 convertAudioAdpcmLoop(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
{
ALADPCMloop *n64_loop = (ALADPCMloop *) &src[srcpos];
ALADPCMloop *host_loop = (ALADPCMloop *) &dst[dstpos];
dstpos += sizeof(ALADPCMloop);
host_loop->start = PD_BE32(n64_loop->start);
host_loop->end = PD_BE32(n64_loop->end);
host_loop->count = PD_BE32(n64_loop->count);
for (int i = 0; i < ARRAYCOUNT(host_loop->state); i++) {
host_loop->state[i] = PD_BE16(n64_loop->state[i]);
}
return dstpos;
}
static u32 convertAudioAdpcmBook(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
{
ALADPCMBook *n64_book = (ALADPCMBook *) &src[srcpos];
ALADPCMBook *host_book = (ALADPCMBook *) &dst[dstpos];
dstpos += sizeof(ALADPCMBook);
host_book->order = PD_BE32(n64_book->order);
host_book->npredictors = PD_BE32(n64_book->npredictors);
for (int i = 0; i < ARRAYCOUNT(host_book->book); i++) {
host_book->book[i] = PD_BE16(n64_book->book[i]);
}
return dstpos;
}
static u32 convertAudioRawLoop(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
{
ALRawLoop *n64_loop = (ALRawLoop *) &src[srcpos];
ALRawLoop *host_loop = (ALRawLoop *) &dst[dstpos];
dstpos += sizeof(ALRawLoop);
host_loop->start = PD_BE32(n64_loop->start);
host_loop->end = PD_BE32(n64_loop->end);
host_loop->count = PD_BE32(n64_loop->count);
return dstpos;
}
static u32 convertAudioWaveTable(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
{
struct n64_wavetable *n64_wavetable = (struct n64_wavetable *) &src[srcpos];
ALWaveTable *host_wavetable = (ALWaveTable *) &dst[dstpos];
dstpos += sizeof(ALWaveTable);
host_wavetable->base = (void *)(uintptr_t)PD_BE32(n64_wavetable->base);
host_wavetable->len = PD_BE32(n64_wavetable->len);
host_wavetable->type = n64_wavetable->type;
host_wavetable->flags = n64_wavetable->flags;
if (host_wavetable->type == AL_ADPCM_WAVE) {
if (n64_wavetable->waveInfo.adpcmWave.loop) {
srcpos = PD_BE32(n64_wavetable->waveInfo.adpcmWave.loop);
AL_NEXT_ITEM(host_wavetable->waveInfo.adpcmWave.loop, convertAudioAdpcmLoop);
} else {
host_wavetable->waveInfo.adpcmWave.loop = NULL;
}
if (n64_wavetable->waveInfo.adpcmWave.book) {
srcpos = PD_BE32(n64_wavetable->waveInfo.adpcmWave.book);
AL_NEXT_ITEM(host_wavetable->waveInfo.adpcmWave.book, convertAudioAdpcmBook);
} else {
host_wavetable->waveInfo.adpcmWave.book = NULL;
}
} else if (host_wavetable->type == AL_RAW16_WAVE) {
if (n64_wavetable->waveInfo.rawWave.loop) {
srcpos = PD_BE32(n64_wavetable->waveInfo.rawWave.loop);
AL_NEXT_ITEM(host_wavetable->waveInfo.rawWave.loop, convertAudioRawLoop);
} else {
host_wavetable->waveInfo.rawWave.loop = NULL;
}
}
return dstpos;
}
static u32 convertAudioSound(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
{
struct n64_sound *n64_sound = (struct n64_sound *) &src[srcpos];
ALSound *host_sound = (ALSound *) &dst[dstpos];
dstpos += sizeof(ALSound);
if (n64_sound->envelope) {
srcpos = PD_BE32(n64_sound->envelope);
AL_NEXT_ITEM(host_sound->envelope, convertAudioEnvelope);
} else {
host_sound->envelope = NULL;
}
if (n64_sound->keyMap) {
srcpos = PD_BE32(n64_sound->keyMap);
AL_NEXT_ITEM(host_sound->keyMap, convertAudioKeyMap);
} else {
host_sound->keyMap = NULL;
}
if (n64_sound->wavetable) {
srcpos = PD_BE32(n64_sound->wavetable);
AL_NEXT_ITEM(host_sound->wavetable, convertAudioWaveTable);
} else {
host_sound->wavetable = NULL;
}
host_sound->samplePan = n64_sound->samplePan;
host_sound->sampleVolume = n64_sound->sampleVolume;
host_sound->flags = n64_sound->flags;
return dstpos;
}
static u32 convertAudioInstrument(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
{
struct n64_instrument *n64_instrument = (struct n64_instrument *) &src[srcpos];
ALInstrument *host_instrument = (ALInstrument *) &dst[dstpos];
const s16 soundCount = PD_BE16(n64_instrument->soundCount);
host_instrument->volume = n64_instrument->volume;
host_instrument->pan = n64_instrument->pan;
host_instrument->priority = n64_instrument->priority;
host_instrument->flags = n64_instrument->flags;
host_instrument->tremType = n64_instrument->tremType;
host_instrument->tremRate = n64_instrument->tremRate;
host_instrument->tremDepth = n64_instrument->tremDepth;
host_instrument->tremDelay = n64_instrument->tremDelay;
host_instrument->vibType = n64_instrument->vibType;
host_instrument->vibRate = n64_instrument->vibRate;
host_instrument->vibDepth = n64_instrument->vibDepth;
host_instrument->vibDelay = n64_instrument->vibDelay;
host_instrument->bendRange = PD_BE16(n64_instrument->bendRange);
host_instrument->soundCount = (soundCount);
dstpos = dstpos + sizeof(ALInstrument) + sizeof(uintptr_t) * (soundCount - 1);
for (int i = 0; i < soundCount; i++) {
srcpos = PD_BE32(n64_instrument->soundArray[i]);
AL_NEXT_ITEM(host_instrument->soundArray[i], convertAudioSound);
}
return dstpos;
}
static u32 convertAudioBank(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
{
struct n64_bank *n64_bank = (struct n64_bank *) &src[srcpos];
ALBank *host_bank = (ALBank *) &dst[dstpos];
const s16 instCount = PD_BE16(n64_bank->instCount);
host_bank->instCount = (instCount);
host_bank->flags = n64_bank->flags;
host_bank->pad = n64_bank->pad;
host_bank->sampleRate = PD_BE32(n64_bank->sampleRate);
dstpos = dstpos + sizeof(ALBank) + sizeof(uintptr_t) * (instCount - 1);
if (n64_bank->percussion) {
srcpos = PD_BE32(n64_bank->percussion);
AL_NEXT_ITEM(host_bank->percussion, convertAudioInstrument);
} else {
host_bank->percussion = 0;
}
for (int i = 0; i < instCount; i++) {
srcpos = PD_BE32(n64_bank->instArray[i]);
AL_NEXT_ITEM(host_bank->instArray[i], convertAudioInstrument);
}
return dstpos;
}
static u32 convertAudioBankFile(u8 *dst, u8 *src)
{
struct n64_bankfile *n64_bankfile = (struct n64_bankfile *)src;
ALBankFile *host_bankfile = (ALBankFile *)dst;
const s16 bankCount = PD_BE16(n64_bankfile->bankCount);
host_bankfile->revision = PD_BE16(n64_bankfile->revision);
host_bankfile->bankCount = (bankCount);
u32 dstpos = sizeof(ALBankFile) + sizeof(uintptr_t) * (bankCount - 1);
for (int i = 0; i < bankCount; i++) {
host_bankfile->bankArray[i] = (void *)(uintptr_t)(dstpos);
u32 srcpos = PD_BE32(n64_bankfile->bankArray[i]);
dstpos = convertAudioBank(dst, dstpos, src, srcpos);
}
return dstpos;
}
u8 *preprocessALBankFile(u8 *src, u32 size, u32 *outSize)
{
ptrReset();
const u32 dstlen = size * 3; // this should overshoot any possible bank size, but * 2 also works for vanilla banks
u8 *dst = sysMemZeroAlloc(dstlen);
u32 reallen = convertAudioBankFile(dst, src);
if (reallen > dstlen || ALIGN16(reallen) > dstlen) {
sysFatalError("overflow when trying to preprocess an ALBankFile, size %u dstlen %u reallen %u", size, dstlen, reallen);
}
reallen = ALIGN16(reallen);
if (reallen < dstlen) {
dst = sysMemRealloc(dst, reallen);
}
*outSize = reallen;
return dst;
}
u8 *preprocessALCMidiHdr(u8 *data, u32 size, u32 *outSize)
{
ALCMidiHdr *hdr = (ALCMidiHdr *)data;
PD_SWAP_VAL(hdr->division);
for (s32 i = 0; i < ARRAYCOUNT(hdr->trackOffset); ++i) {
PD_SWAP_VAL(hdr->trackOffset[i]);
}
return NULL;
}
u8 *preprocessSequences(u8* data, u32 size, u32 *outSize)
{
struct seqtable *seq = (struct seqtable *)data;
PD_SWAP_VAL(seq->count);
for (s16 i = 0; i < seq->count; ++i) {
PD_SWAP_VAL(seq->entries[i].binlen);
PD_SWAP_VAL(seq->entries[i].ziplen);
PD_SWAP_VAL(seq->entries[i].romaddr);
}
return NULL;
}
+104
View File
@@ -0,0 +1,104 @@
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "preprocess/common.h"
struct n64_fontchar {
u8 index;
s8 baseline;
u8 height;
u8 width;
s32 kerningindex;
u32 pixeldata;
};
struct n64_fontcharjpn {
u16 index;
s8 baseline;
u8 height;
u8 width;
s16 kerningindex;
u32 pixeldata;
};
u8 *preprocessFont(u8 *src, u32 srclen, u32 *outSize)
{
int num_chars = 94;
#if VERSION == VERSION_PAL_FINAL
// PAL has more characters in these fonts
extern u8* _fonthandelgothicsmSegmentRomStart;
extern u8* _fonthandelgothicxsSegmentRomStart;
extern u8* _fonthandelgothicmdSegmentRomStart;
if (src == _fonthandelgothicsmSegmentRomStart
|| src == _fonthandelgothicxsSegmentRomStart
|| src == _fonthandelgothicmdSegmentRomStart) {
num_chars = 135;
}
#endif
size_t dstlen = srclen - (num_chars * sizeof(struct n64_fontchar)) + (num_chars * sizeof(struct fontchar)) + 0x20;
u8* dst = sysMemZeroAlloc(dstlen);
// Kerning table
s32 *src_kerning_table = (s32 *)src;
s32 *dst_kerning_table = (s32 *)dst;
for (int i = 0; i < 13 * 13; i++) {
dst_kerning_table[i] = PD_BE32(src_kerning_table[i]);
}
u32 src_offset = PD_ALIGN(13 * 13 * 4, sizeof(u32));
u32 dst_offset = PD_ALIGN(13 * 13 * 4, sizeof(uintptr_t));
// Character table
#if VERSION == VERSION_JPN_FINAL
struct n64_fontcharjpn *src_char_table = (struct n64_fontcharjpn *) &src[src_offset];
struct fontchar *dst_char_table = (struct fontchar *) &dst[dst_offset];
u32 diff = (dst_offset + num_chars * sizeof(struct fontchar)) - (src_offset + num_chars * sizeof(struct n64_fontcharjpn));
for (int i = 0; i < num_chars; i++) {
dst_char_table[i].index = PD_BE16(src_char_table[i].index);
dst_char_table[i].baseline = src_char_table[i].baseline;
dst_char_table[i].height = src_char_table[i].height;
dst_char_table[i].width = src_char_table[i].width;
dst_char_table[i].kerningindex = PD_BE16(src_char_table[i].kerningindex);
dst_char_table[i].pixeldata = (void *)(uintptr_t)(src_char_table[i].pixeldata ? PD_BE32(src_char_table[i].pixeldata) + diff : 0);
}
src_offset += num_chars * sizeof(struct n64_fontcharjpn);
dst_offset += num_chars * sizeof(struct fontchar);
#else
struct n64_fontchar *src_char_table = (struct n64_fontchar *) &src[src_offset];
struct fontchar *dst_char_table = (struct fontchar *) &dst[dst_offset];
u32 diff = (dst_offset + num_chars * sizeof(struct fontchar)) - (src_offset + num_chars * sizeof(struct n64_fontchar));
for (int i = 0; i < num_chars; i++) {
dst_char_table[i].index = src_char_table[i].index;
dst_char_table[i].baseline = src_char_table[i].baseline;
dst_char_table[i].height = src_char_table[i].height;
dst_char_table[i].width = src_char_table[i].width;
dst_char_table[i].kerningindex = PD_BE32(src_char_table[i].kerningindex);
dst_char_table[i].pixeldata = (void *)(uintptr_t)(src_char_table[i].pixeldata ? PD_BE32(src_char_table[i].pixeldata) + diff : 0);
}
src_offset += num_chars * sizeof(struct n64_fontchar);
dst_offset += num_chars * sizeof(struct fontchar);
#endif
// Pixel data
u32 len = srclen - src_offset;
memcpy(&dst[dst_offset], &src[src_offset], len);
if (outSize) *outSize = ALIGN16(dst_offset + len);
return dst;
}
u8 *preprocessJpnFont(u8* data, u32 size, u32* outSize)
{
// ???
return NULL;
}
+93 -13
View File
@@ -4,7 +4,6 @@
#include <string.h>
#include <ctype.h>
#include <PR/ultratypes.h>
#include <PR/ultratypes.h>
#include "lib/rzip.h"
#include "romdata.h"
#include "fs.h"
@@ -51,6 +50,9 @@
#define ROMDATA_MAX_FILES 2048
#define GBC_ROM_NAME "pd.gbc"
#define GBC_ROM_SIZE 4194304
u8 *g_RomFile;
u32 g_RomFileSize;
@@ -236,6 +238,17 @@ static inline void romdataLoadRom(void)
romDataSegSize = dataSegLen;
}
static inline void romdataUpdateSegStartEnd(struct romfile* seg)
{
if (seg->segstart) {
*seg->segstart = seg->data;
}
if (seg->segend) {
*seg->segend = seg->data + seg->size;
}
}
static inline void romdataInitSegment(struct romfile *seg)
{
if (!seg->data) {
@@ -251,7 +264,7 @@ static inline void romdataInitSegment(struct romfile *seg)
seg->size = seg[1].data - seg->data;
} else {
// this is the last segment, calculate based on rom size
seg->size = (u8 *)g_RomFileSize - seg->data;
seg->size = (uintptr_t)g_RomFileSize - (uintptr_t)seg->data;
}
}
@@ -269,7 +282,7 @@ static inline void romdataInitSegment(struct romfile *seg)
if (g_RomFile) {
newData = g_RomFile + (uintptr_t)seg->data;
seg->source = SRC_ROM;
sysLogPrintf(LOG_NOTE, "loading segment %s from ROM (offset %08x pointer %p)", seg->name, (u32)seg->data, newData);
sysLogPrintf(LOG_NOTE, "loading segment %s from ROM (offset %08x pointer %p)", seg->name, (uintptr_t)seg->data, newData);
} else {
sysFatalError("No ROM or external file for segment:\n%s", seg->name);
}
@@ -281,17 +294,19 @@ static inline void romdataInitSegment(struct romfile *seg)
seg->data = newData;
if (seg->segstart) {
*seg->segstart = seg->data;
}
if (seg->segend) {
*seg->segend = seg->data + seg->size;
}
romdataUpdateSegStartEnd(seg);
// call the post load function if any
if (seg->preprocess && !seg->preprocessed) {
seg->preprocess(seg->data, seg->size);
newData = seg->preprocess(seg->data, seg->size, &seg->size);
if (newData) {
if (seg->source == SRC_EXTERNAL)
sysMemFree(seg->data);
seg->data = newData;
romdataUpdateSegStartEnd(seg);
}
seg->preprocessed = 1;
}
}
@@ -386,6 +401,53 @@ s32 romdataInit(void)
return 0;
}
static inline bool romdataCheckGbcRomContents(const u8 *gbcRomFile, const u32 gbcRomSize)
{
if (gbcRomSize != GBC_ROM_SIZE) {
return false;
}
// ROM title
if (memcmp(gbcRomFile + 0x134, "PerfDark VPDE", 15) != 0) {
return false;
}
// Licensee code
if (memcmp(gbcRomFile + 0x144, "4Y", 2) != 0) {
return false;
}
// Header and global checksums
if (gbcRomFile[0x14D] != 0xA1 || gbcRomFile[0x14E] != 0xAD || gbcRomFile[0x14F] != 0x0F) {
return false;
}
return true;
}
s32 romdataCheckGbcRom(void)
{
if (fsFileSize(GBC_ROM_NAME) < 0) {
// bail early if it doesn't exist to avoid generating error messages
return false;
}
u32 gbcRomSize = 0;
u8 *gbcRomFile = fsFileLoad(GBC_ROM_NAME, &gbcRomSize);
if (!gbcRomFile) {
return false;
}
const bool ret = romdataCheckGbcRomContents(gbcRomFile, gbcRomSize);
sysMemFree(gbcRomFile);
if (ret) {
sysLogPrintf(LOG_NOTE, "romdataCheckGbcRom: valid GBC rom found");
}
return ret;
}
s32 romdataFileGetSize(s32 fileNum)
{
if (fileNum < 1 || fileNum >= ROMDATA_MAX_FILES) {
@@ -447,7 +509,7 @@ u8 *romdataFileLoad(s32 fileNum, u32 *outSize)
return out;
}
void romdataFilePreprocess(s32 fileNum, s32 loadType, u8 *data, u32 size)
void romdataFilePreprocess(s32 fileNum, s32 loadType, u8 *data, u32 size, u32 *outSize)
{
if (fileNum < 1 || fileNum >= ROMDATA_MAX_FILES) {
sysLogPrintf(LOG_ERROR, "romdataFilePreprocess: invalid file num %d", fileNum);
@@ -465,7 +527,7 @@ void romdataFilePreprocess(s32 fileNum, s32 loadType, u8 *data, u32 size)
}
}
// then preprocess
filePreprocFuncs[loadType](data, size);
filePreprocFuncs[loadType](data, size, outSize);
// fileSlots[fileNum].preprocessed = 1;
}
}
@@ -524,3 +586,21 @@ u32 romdataSegGetSize(const char *segName)
{
return romdataGetSeg(segName)->size;
}
u32 romdataFileGetEstimatedSize(const u32 size, const u32 loadtype)
{
#ifdef PLATFORM_64BIT
switch (loadtype) {
case LOADTYPE_BG: return (u32)(size * 1.1f);
case LOADTYPE_TILES: return (u32)(size * 1.1f);
case LOADTYPE_LANG: return (u32)(size * 1.3f);
case LOADTYPE_SETUP: return (u32)(size * 1.5f);
case LOADTYPE_PADS: return (u32)(size * 1.7f);
case LOADTYPE_MODEL: return (u32)(size * 1.7f);
case LOADTYPE_GUN: return (u32)(size * 1.7f);
default:
sysLogPrintf(LOG_WARNING, "romdataFileGetEstimatedSize: wrong loadtype %d", loadtype);
}
#endif
return size;
}
+6 -1
View File
@@ -40,7 +40,7 @@ __attribute__((dllexport)) u32 AmdPowerXpressRequestHighPerformance = 1;
// but if it doesn't we'll have to use __builtin_ia32_pause() or something
#include <immintrin.h>
#define DO_YIELD() _mm_pause()
#elif defined(PLATFORM_ARM)
#elif defined(PLATFORM_ARM) && (defined(PLATFORM_64BIT) || PLATFORM_ARM == 7 || PLATFORM_ARM == 8)
// same as YieldProcessor() on ARM Windows
#define DO_YIELD() __asm__ volatile("dmb ishst\n\tyield":::"memory")
#else
@@ -288,6 +288,11 @@ void *sysMemZeroAlloc(const u32 size)
return calloc(1, size);
}
void *sysMemRealloc(void *ptr, const u32 newSize)
{
return realloc(ptr, newSize);
}
void sysMemFree(void *ptr)
{
free(ptr);
+321 -25
View File
@@ -6,36 +6,68 @@
#include <PR/gbi.h>
#include "platform.h"
#include "config.h"
#include "system.h"
#include "video.h"
#include "../fast3d/gfx_api.h"
#include "../fast3d/gfx_sdl.h"
#include "../fast3d/gfx_opengl.h"
#ifdef PLATFORM_NSWITCH
#define DEFAULT_VID_WIDTH 1280
#define DEFAULT_VID_HEIGHT 720
#define DEFAULT_VID_FULLSCREEN true
#define DEFAULT_VID_FULLSCREEN_EXCLUSIVE true
#else
#define DEFAULT_VID_WIDTH 640
#define DEFAULT_VID_HEIGHT 480
#define DEFAULT_VID_FULLSCREEN false
#define DEFAULT_VID_FULLSCREEN_EXCLUSIVE false
#endif
static struct GfxWindowManagerAPI *wmAPI;
static struct GfxRenderingAPI *renderingAPI;
static bool initDone = false;
static s32 vidWidth = 640;
static s32 vidHeight = 480;
static s32 vidWidth = DEFAULT_VID_WIDTH;
static s32 vidHeight = DEFAULT_VID_HEIGHT;
static s32 vidFramebuffers = true;
static s32 vidFullscreen = false;
static s32 vidFullscreenExclusive = false;
static s32 vidFullscreen = DEFAULT_VID_FULLSCREEN;
static s32 vidFullscreenExclusive = DEFAULT_VID_FULLSCREEN_EXCLUSIVE;
static s32 vidMaximize = false;
static s32 vidCenter = false;
static s32 vidAllowHiDpi = false;
static s32 vidVsync = 1;
static s32 vidMSAA = 1;
static s32 vidFramerateLimit = 0;
static s32 vidDisplayFPS = 0;
static f32 vidDisplayFPSInterval = 1.f;
static f32 vidAvgFPS = 0;
static s32 vidNumModes = 1;
static displaymode vidModeDefault;
static displaymode *vidModes = &vidModeDefault;
static f32 vidGlareBrightness = 1.f;
static f32 vidOverexposureScale = 1.f;
static s32 texFilter = FILTER_LINEAR;
static s32 texFilter2D = true;
static s32 texDetail = true;
static s32 texDetail = false;
static s32 texMipmapFilter = MIPMAP_LINEAR;
static u32 texAnisotropicFilter = 4;
static u32 dlcount = 0;
static u32 frames = 0;
static u32 framesPerSec = 0;
static f64 startTime, endTime, fpsTime;
static f64 startTime, endTime;
static f64 accumDelta = 0.0;
static f64 fpsTime = 0.0;
static s32 fpsNumFrames = 0;
static s32 videoInitDisplayModes(void);
void optionsMenuInit();
s32 videoInit(void)
{
@@ -61,23 +93,21 @@ s32 videoInit(void)
.fullscreen = vidFullscreen,
.fullscreen_is_exclusive = vidFullscreenExclusive,
.maximized = vidMaximize,
.centered = vidCenter,
.allow_hidpi = vidAllowHiDpi
}
};
gfx_init(&set);
if (!wmAPI->set_swap_interval(vidVsync)) {
vidVsync = 0;
}
videoInitDisplayModes();
videoSetVsync(vidVsync);
videoSetFramerateLimit(vidFramerateLimit);
if (vidVsync == 0 && vidFramerateLimit == 0) {
// cap FPS if there's no vsync to prevent the game from exploding
vidFramerateLimit = VIDEO_MAX_FPS;
}
wmAPI->set_target_fps(vidFramerateLimit); // disabled because vsync is on
renderingAPI->set_texture_filter((enum FilteringMode)texFilter);
gfx_set_texture_filter((enum FilteringMode)texFilter);
gfx_set_mipmap_filter((enum MipmapFilteringMode)texMipmapFilter);
videoSetAnisotropicFilter(texAnisotropicFilter);
optionsMenuInit();
initDone = true;
return 0;
@@ -89,6 +119,10 @@ void videoStartFrame(void)
startTime = wmAPI->get_time();
gfx_start_frame();
}
// Synchronize with their backend counterparts.
vidFullscreen = videoGetFullscreen();
vidMaximize = videoGetMaximizeWindow();
}
void videoSubmitCommands(Gfx *cmds)
@@ -107,20 +141,29 @@ void videoEndFrame(void)
gfx_end_frame();
endTime = wmAPI->get_time();
++frames;
++framesPerSec;
++fpsNumFrames;
const f64 flipTime = wmAPI->get_time();
accumDelta += flipTime - endTime;
endTime = flipTime;
if (endTime >= fpsTime) {
char tmp[128];
snprintf(tmp, sizeof(tmp), "fps %3u frt %lf frm %u", framesPerSec, endTime - startTime, frames);
wmAPI->set_window_title(tmp);
framesPerSec = 0;
fpsTime = endTime + 1.0;
vidAvgFPS = fpsNumFrames ? ((f64)fpsNumFrames / accumDelta) : 0.f;
fpsNumFrames = 0;
accumDelta = 0.0;
fpsTime = endTime + vidDisplayFPSInterval;
}
}
f32 videoGetAverageFPS(void)
{
return vidAvgFPS;
}
void videoClearScreen(void)
{
videoStartFrame();
@@ -165,19 +208,159 @@ s32 videoGetHeight(void)
s32 videoGetFullscreen(void)
{
vidFullscreen = wmAPI->get_fullscreen_state();
return vidFullscreen;
}
s32 videoGetFullscreenMode(void)
{
vidFullscreenExclusive = wmAPI->get_fullscreen_flag_mode();
return vidFullscreenExclusive;
}
s32 videoGetMaximizeWindow(void)
{
vidMaximize = wmAPI->get_maximized_state();
return vidMaximize;
}
s32 videoGetCenterWindow(void)
{
return vidCenter;
}
f32 videoGetAspect(void)
{
return gfx_current_dimensions.aspect_ratio;
}
s32 videoGetDisplayModeIndex(void)
{
for (s32 i = 1; i < vidNumModes; ++i) {
if (vidModes[i].width == gfx_current_dimensions.width &&
vidModes[i].height == gfx_current_dimensions.height) {
return i;
}
}
// Current dimensions don't match any known mode, so return index 0, "Custom".
return 0;
}
s32 videoGetMSAA(void)
{
vidMSAA = (s32)gfx_msaa_level;
return vidMSAA;
}
s32 videoGetVsync(void)
{
vidVsync = wmAPI->get_swap_interval();
return vidVsync;
}
s32 videoGetFramerateLimit(void)
{
vidFramerateLimit = wmAPI->get_target_fps();
return vidFramerateLimit;
}
s32 videoGetDisplayFPS(void)
{
return vidDisplayFPS;
}
static s32 videoInitDisplayModes(void)
{
if (!wmAPI->get_current_display_mode(&vidModeDefault.width, &vidModeDefault.height)) {
vidModeDefault.width = 640;
vidModeDefault.height = 480;
return false;
}
const s32 numBaseModes = wmAPI->get_num_display_modes();
if (!numBaseModes) {
return false;
}
const s32 numCustomModes = 1;
displaymode *modeList = sysMemZeroAlloc((numBaseModes + numCustomModes) * sizeof(displaymode));
if (!modeList) {
return false;
}
modeList[0].width = 0;
modeList[0].height = 0;
s32 numModes = 1;
s32 w = -1, h = w, neww = w, newh = w;
// SDL modes are guaranteed to be sorted high to low
for (s32 i = 0; i < numBaseModes; ++i) {
wmAPI->get_display_mode(i, &neww, &newh);
if (neww != w || newh != h) {
w = neww;
h = newh;
modeList[numModes].width = w;
modeList[numModes].height = h;
++numModes;
}
}
modeList = sysMemRealloc(modeList, numModes * sizeof(displaymode));
if (!modeList) {
return false;
}
vidModes = modeList;
vidNumModes = numModes;
return true;
}
s32 videoGetDisplayMode(displaymode *out, const s32 index)
{
if (index >= 0 && index < vidNumModes) {
*out = vidModes[index];
return true;
}
return false;
}
s32 videoGetNumDisplayModes(void)
{
return vidNumModes;
}
void videoSetDisplayMode(const s32 index)
{
const displaymode dm = vidModes[index];
if (index == 0) {
// "Custom" video mode.
return;
}
vidWidth = dm.width;
vidHeight = dm.height;
s32 posX = 100;
s32 posY = 100;
if (vidCenter) {
wmAPI->get_centered_positions(vidWidth, vidHeight, &posX, &posY);
}
if (vidFullscreen) {
wmAPI->set_closest_resolution(vidWidth, vidHeight, vidCenter);
} else {
if (vidMaximize) {
videoSetMaximizeWindow(false);
} else {
wmAPI->set_dimensions(vidWidth, vidHeight, posX, posY);
}
}
}
s32 videoGetTextureFilter2D(void)
{
return texFilter2D;
@@ -188,11 +371,31 @@ u32 videoGetTextureFilter(void)
return texFilter;
}
u32 videoGetAnisotropicFilter()
{
return texAnisotropicFilter;
}
u32 videoGetMaxAnisotropyLevel()
{
return renderingAPI->get_max_anisotropy_level();
}
s32 videoGetDetailTextures(void)
{
return texDetail;
}
f32 videoGetGlareBrightness(void)
{
return vidGlareBrightness;
}
f32 videoGetOverexposureScale(void)
{
return vidOverexposureScale;
}
void videoSetWindowOffset(s32 x, s32 y)
{
gfx_current_game_window_viewport.x = x;
@@ -203,7 +406,22 @@ void videoSetFullscreen(s32 fs)
{
if (fs != vidFullscreen) {
vidFullscreen = !!fs;
wmAPI->set_closest_resolution(vidWidth, vidHeight, vidCenter);
wmAPI->set_fullscreen(vidFullscreen);
if (!vidFullscreen && vidMaximize) {
wmAPI->set_maximize(false);
wmAPI->set_maximize(true);
}
}
}
void videoSetFullscreenMode(s32 mode)
{
vidFullscreenExclusive = mode;
wmAPI->set_fullscreen_flag(mode);
if (vidFullscreen) {
wmAPI->set_fullscreen(false);
wmAPI->set_fullscreen(true);
}
}
@@ -212,14 +430,32 @@ void videoSetMaximizeWindow(s32 fs)
if (fs != vidMaximize) {
vidMaximize = !!fs;
wmAPI->set_maximize(vidMaximize);
if (vidCenter && !vidMaximize) {
s32 posX = 0;
s32 posY = 0;
wmAPI->get_centered_positions(vidWidth, vidHeight, &posX, &posY);
wmAPI->set_dimensions(vidWidth, vidHeight, posX, posY);
}
}
}
void videoSetCenterWindow(s32 center)
{
vidCenter = center;
if (vidCenter && !vidMaximize) {
s32 posX = 0;
s32 posY = 0;
wmAPI->get_centered_positions(vidWidth, vidHeight, &posX, &posY);
wmAPI->set_dimensions(vidWidth, vidHeight, posX, posY);
}
}
void videoSetTextureFilter(u32 filter)
{
if (filter > FILTER_THREE_POINT) filter = FILTER_THREE_POINT;
if (texFilter == filter) return;
texFilter = filter;
renderingAPI->set_texture_filter((enum FilteringMode)filter);
gfx_set_texture_filter((enum FilteringMode)filter);
}
void videoSetTextureFilter2D(s32 filter)
@@ -227,17 +463,60 @@ void videoSetTextureFilter2D(s32 filter)
texFilter2D = !!filter;
}
void videoSetAnisotropicFilter(u32 level)
{
texAnisotropicFilter = level;
renderingAPI->set_anisotropy_level(level);
}
void videoSetDetailTextures(s32 detail)
{
texDetail = !!detail;
gfx_detail_textures_enabled = (bool)texDetail;
}
void videoSetGlareBrightness(f32 bright)
{
vidGlareBrightness = (bright < 0.f ? 0.f : (bright > 1.f ? 1.f : bright));
}
void videoSetOverexposureScale(f32 scale)
{
vidOverexposureScale = (scale < 0.f ? 0.f : (scale > 1.f ? 1.f : scale));
}
s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize)
{
return gfx_create_framebuffer(w, h, upscale, autoresize);
}
void videoSetMSAA(const s32 msaa)
{
vidMSAA = msaa;
gfx_msaa_level = (u32)vidMSAA;
}
void videoSetVsync(const s32 vsync)
{
vidVsync = wmAPI->set_swap_interval(vsync) ? vsync : 0;
if (vidVsync == 0 && vidFramerateLimit == 0) {
// cap FPS if there's no vsync to prevent the game from exploding
videoSetFramerateLimit(VIDEO_MAX_FPS);
}
}
void videoSetFramerateLimit(const s32 limit)
{
vidFramerateLimit = (vidVsync == 0 && limit == 0) ? VIDEO_MAX_FPS : limit;
wmAPI->set_target_fps(vidFramerateLimit);
}
void videoSetDisplayFPS(const s32 displayfps)
{
vidDisplayFPS = displayfps;
}
void videoSetFramebuffer(s32 target)
{
return gfx_set_framebuffer(target, 1.f);
@@ -274,6 +553,16 @@ void videoFreeCachedTexture(const void *texptr)
gfx_texture_cache_delete(texptr);
}
void videoFreeCachedTextures(const void *start, const void *end)
{
gfx_texture_cache_delete_range(start, end);
}
void videoShutdown(void)
{
free(vidModes);
}
PD_CONSTRUCTOR static void videoConfigInit(void)
{
configRegisterInt("Video.DefaultFullscreen", &vidFullscreen, 0, 1);
@@ -281,12 +570,19 @@ PD_CONSTRUCTOR static void videoConfigInit(void)
configRegisterInt("Video.DefaultWidth", &vidWidth, 0, 32767);
configRegisterInt("Video.DefaultHeight", &vidHeight, 0, 32767);
configRegisterInt("Video.ExclusiveFullscreen", &vidFullscreenExclusive, 0, 1);
configRegisterInt("Video.CenterWindow", &vidCenter, 0, 1);
configRegisterInt("Video.AllowHiDpi", &vidAllowHiDpi, 0, 1);
configRegisterInt("Video.VSync", &vidVsync, -1, 10);
configRegisterInt("Video.FramebufferEffects", &vidFramebuffers, 0, 1);
configRegisterInt("Video.FramerateLimit", &vidFramerateLimit, 0, VIDEO_MAX_FPS);
configRegisterInt("Video.DisplayFPS", &vidDisplayFPS, 0, 1);
configRegisterFloat("Video.DisplayFPSInterval", &vidDisplayFPSInterval, 0.01f, 32.f);
configRegisterInt("Video.MSAA", &vidMSAA, 1, 16);
configRegisterInt("Video.TextureFilter", &texFilter, 0, 2);
configRegisterInt("Video.TextureFilter2D", &texFilter2D, 0, 1);
configRegisterInt("Video.DetailTextures", &texDetail, 0, 1);
configRegisterInt("Video.MipmapFilter", &texMipmapFilter, 0, 2);
configRegisterInt("Video.AnisotropicFilter", &texAnisotropicFilter, 0, 16);
configRegisterFloat("Video.GlareBrightness", &vidGlareBrightness, 0.f, 1.f);
configRegisterFloat("Video.OverexposureScale", &vidOverexposureScale, 0.f, 1.f);
}
+1 -1
View File
@@ -177,7 +177,7 @@ MenuItemHandlerResult amPickTargetMenuList(s32 operation, struct menuitem *item,
gdl = text0f153628(gdl);
gdl = textRenderProjected(gdl, &x, &y, g_MpAllChrConfigPtrs[chrindex]->name, g_CharsHandelGothicSm, g_FontHandelGothicSm, colour, viGetWidth(), viGetHeight(), 0, 0);
gdl = text0f153780(gdl);
return (s32)gdl;
return (uintptr_t)gdl;
}
case MENUOP_GETOPTIONHEIGHT:
data->list.value = LINEHEIGHT;
+167 -38
View File
@@ -7,7 +7,7 @@
#include "game/game_0b2150.h"
#include "game/tex.h"
#include "game/sky.h"
#include "game/game_13c510.h"
#include "game/artifact.h"
#include "game/bg.h"
#include "game/stagetable.h"
#include "game/room.h"
@@ -21,8 +21,73 @@
#include "lib/lib_17ce0.h"
#include "game/player.h"
#include "game/prop.h"
#include "video.h"
#endif
/**
* Artifacts are points of interest in the z-buffer.
*
* They correspond to:
* - Individual circles in the lens flare effect from the sun.
* - Individual corners of each light fixture's box.
*
* The game needs to do line of sight checks to these points. The collision
* system would normally be used for line of sight checks, but it only works
* with basic geometric volumes and also doesn't take into account the player's
* gun. Instead, the checks are done by reading from the previous frame's
* z-buffer.
*
* Typically, the z-buffer would be read by the scheduler after a graphics frame
* is rendered, but this only works if the z-buffer is a complete image.
* PD draws the scene, then clears the z-buffer before drawing the player's gun,
* so the z-buffer at the end only contains the player's gun. To work around
* this, the GPU is given commands to read the z-buffer as a texture and copy
* depth values to a safe place before clearing it. Then once the frame is
* rendered, the scheduler compares the saved depths with the current z-buffer
* and updates the artifact, applying the minimum of the two depths.
*
* The scheduler maintains 3 arrays of artifacts, each referenced by indexes
* which rotate between them.
* - Artifacts are written by the main thread using the write index.
* The write and front indexes are then incremented.
* - The same artifacts are updated by the scheduler using the pending index.
* The pending index is then updated.
* - The artifacts are then rendered on a later frame using the front index.
*
* In each artifacts array, the first several slots are reserved for the sun
* flare artifacts. The quantity depends on the number of suns in the stage
* (Skedar Ruins has 3) and there are 8 artifacts per sun. The remaining slots
* are used for light fixture corners. The array is big enough to handle at
* least 90 lights on screen at a time.
*
* The initial state of the indexes are write=0, front=1, pending=0.
* These are set in sched_reset_artifacts.
*
* The detailed workflow is:
* - CPU: Light artifacts are determined and added to write artifacts (0) array
* - CPU: Constructs the gdl in this order:
* - Render scene
* - Copy relevant parts of z-buffer to write depths (0) array
* - Clear z-buffer and render gun
* - Render artifacts by reading from front artifacts (1) array
* - CPU: increments write (0 -> 1) and front (1 -> 2) indexes
* - GPU: Executes above task. g_ArtifactDepths0 now contains depths, and is
* pointed to by pending.
* - Scheduler: Reads the z-buffer, which at this point only contains the gun
* depth information, and updates the artifact with the minimum of the two
* - Scheduler: Increments pending (0 -> 1)
*
* It appears that the front index should be initialised to 2 instead, so that
* it's one frame behind the others rather than two frames behind.
*
* There's no doubt this went through several iterations before landing on this
* implementation. It's likely that this was implemented using a single and full
* z-buffer and it worked well until they decided to clear the z-buffer before
* rendering the gun. There is evidence in zbuf.c that they allocated a second
* z-buffer and swapped it. But when memory got too tight they had to change it
* to this texture read method.
*/
u8 *var800a41a0;
u32 var800a41a4;
u32 var800a41a8;
@@ -44,11 +109,25 @@ void artifactsTick(void)
schedIncrementFrontArtifacts();
}
u16 func0f13c574(f32 arg0)
u16 floatToN64Depth(f32 arg0)
{
/**
* Method to convert a 32 bit floating point depth value to the
* unsigned 16 bit integer format used by the zbuffer on the N64.
* The argument arg0 represents z normalized to [0, 1] * 32704.0f.
*
* It works by converting the depth value to a large, unsigned 32 bit
* integer before scaling back down to an unsigned 16 bit integer.
* The scaling is done using bit shift operations on the most & least
* significant bytes of the resulting 16 bit integer, likely because
* bit shift operations are faster than division. The segmentation of
* this calculation at values 0x3f800, 0x3f000, etc. is probably
* intended to reduce z-fighting by adding more differentiation for
* distant z values.
*/
u32 value = arg0 * 8.0f;
u32 left;
u32 right = value;
u32 left; // forms the most significant byte of the final u16
u32 right = value; // forms the least significant byte of the final u16
if (value > 0x3f800) {
right = value & 0x7ff;
@@ -87,7 +166,7 @@ u16 func0f13c574(f32 arg0)
return left << 13 | (right << 2);
}
s32 func0f13c710(f32 arg0)
s32 artifactsFloatToInt(f32 arg0)
{
if (arg0 > 0.0f) {
if (arg0 > 2147483520.0f) {
@@ -168,6 +247,12 @@ void artifactsCalculateGlaresForRoom(s32 roomnum)
struct coord *campos = &g_Vars.currentplayer->cam_pos;
struct artifact *artifact;
#ifndef PLATFORM_N64
if (videoGetGlareBrightness() <= 0.f) {
return;
}
#endif
if (g_Rooms[roomnum].gfxdata != NULL && g_Rooms[roomnum].loaded240) {
numlights = g_Rooms[roomnum].gfxdata->numlights;
@@ -232,8 +317,8 @@ void artifactsCalculateGlaresForRoom(s32 roomnum)
if (spdc[3] > 0.0001f) {
f20 = 1.0f / spdc[3];
x = func0f13c710(viewleft + (1.0f + spdc[0] * f20) * (viewwidth * 0.5f));
y = func0f13c710(viewtop + (1.0f - spdc[1] * f20) * (viewheight * 0.5f));
x = artifactsFloatToInt(viewleft + (1.0f + spdc[0] * f20) * (viewwidth * 0.5f));
y = artifactsFloatToInt(viewtop + (1.0f - spdc[1] * f20) * (viewheight * 0.5f));
f0 = (spdc[2] * f20 * 511.0f + 511.0f) * 32.0f;
if (f0 < 32576.0f) {
@@ -335,8 +420,8 @@ void artifactsCalculateGlaresForRoom(s32 roomnum)
f20 = -9999.0f;
}
xi = func0f13c710(viewleft + (1.0f + spdc[0] * f20) * (viewwidth * 0.5f));
yi = func0f13c710(viewtop + (1.0f - spdc[1] * f20) * (viewheight * 0.5f));
xi = artifactsFloatToInt(viewleft + (1.0f + spdc[0] * f20) * (viewwidth * 0.5f));
yi = artifactsFloatToInt(viewtop + (1.0f - spdc[1] * f20) * (viewheight * 0.5f));
f0 = (spdc[2] * f20 * 511.0f + 511.0f) * 32.0f;
if (g_ZbufPtr1
@@ -357,14 +442,20 @@ void artifactsCalculateGlaresForRoom(s32 roomnum)
if (index < MAX_ARTIFACTS) {
#ifndef PLATFORM_N64
artifact->unk02 = artifactTestLos(&spec, &g_BgRooms[roomnum].pos, xi, yi);
artifact->visiblelos = artifactTestLos(&spec, &g_BgRooms[roomnum].pos, xi, yi);
#endif
artifact->unk04 = func0f13c574(f0) >> 2;
artifact->unk08 = &g_ZbufPtr1[viGetWidth() * yi + xi];
/**
* the original game performs artifact depth comparison
* using the N64 depth values divided by 4. This is
* accomplished by bit shifting the N64 depth value
* to the right using >> 2
*/
artifact->expecteddepth = floatToN64Depth(f0) >> 2;
artifact->zbufptr = &g_ZbufPtr1[viGetWidth() * yi + xi];
artifact->light = &roomlights[i];
artifact->type = ARTIFACTTYPE_GLARE;
artifact->unk0c.u16_2 = xi;
artifact->unk0c.u16_1 = yi;
artifact->screenx = xi;
artifact->screeny = yi;
}
}
}
@@ -375,7 +466,7 @@ void artifactsCalculateGlaresForRoom(s32 roomnum)
}
}
u8 func0f13d3c4(u8 arg0, u8 arg1)
u8 artifactsClamp(u8 arg0, u8 arg1)
{
if (arg1 >= arg0 + 7) {
return arg0 + 7;
@@ -423,18 +514,18 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum)
u16 min;
u16 max;
f32 lightop_cur_frac;
s32 t2;
s32 numgood;
struct light *light;
u8 *s3;
s32 k;
s32 count;
u16 t4;
u16 actualdepth;
f32 add;
s32 l;
f32 brightness;
s32 avg;
s32 tolerance;
f32 f0;
s32 v1;
s32 difference;
s32 r;
s32 g;
s32 b;
@@ -448,6 +539,13 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum)
f32 f24;
bool extra;
f32 f26;
#ifndef PLATFORM_N64
const f32 pfov = g_Vars.currentplayerstats ? PLAYER_DEFAULT_FOV : 60.f;
const f32 brightscale = videoGetGlareBrightness();
if (brightscale <= 0.f) {
return gdl;
}
#endif
artifacts = schedGetFrontArtifacts();
lightop_cur_frac = roomGetLightOpCurFrac(roomnum);
@@ -460,6 +558,12 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum)
struct light *light2 = artifacts[i].light;
count = 0;
/**
* light arifacts are created from several, closely spaced
* textures that give the appearance of a dynamic light glare
* as the character moves. Loop to count all the sub-artifacts
* in this light.
*/
for (j = i; j < MAX_ARTIFACTS && artifacts[j].type == ARTIFACTTYPE_GLARE && artifacts[j].light == light2; j++) {
count++;
}
@@ -470,52 +574,70 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum)
if (roomnum == light->roomnum) {
lightindex = ((uintptr_t)light - (uintptr_t)g_BgLightsFileData) / sizeof(struct light);
s3 = &var800a41a0[lightindex * 3];
t2 = 0;
numgood = 0;
min = 0xffff;
max = 0;
/**
* loop to determine the min & max depth of
* the sub-artifacts composing this room light.
*/
for (k = i; k < i + count; k++) {
if (artifacts[k].unk04 > max) {
max = artifacts[k].unk04;
if (artifacts[k].expecteddepth > max) {
max = artifacts[k].expecteddepth;
}
if (artifacts[k].unk04 < min) {
min = artifacts[k].unk04;
if (artifacts[k].expecteddepth < min) {
min = artifacts[k].expecteddepth;
}
}
avg = (max - min) >> 1;
/**
* Define a depth tolerance from the min & max
* depths of sub-artifacts for a given light.
* This will be used to determine which light
* artifacts are visible when comparing depth
* values of lights to other items rendered
* on screen. Without this, the lights would
* constantly flicker due to z-fighting caused
* by the low precision of the N64 depth.
*/
tolerance = (max - min) >> 1;
if (avg < 25) {
avg = 25;
if (tolerance < 25) {
tolerance = 25;
}
for (k = i; k < i + count; k++) {
#ifdef PLATFORM_N64
u16 tmp;
t4 = (artifacts[k].unk02 & 0xfffc) >> 2;
tmp = artifacts[k].unk04;
u16 expecteddepth;
actualdepth = (artifacts[k].actualdepth & 0xfffc) >> 2;
expecteddepth = artifacts[k].expecteddepth;
if (tmp < t4) {
v1 = t4 - tmp;
if (expecteddepth < actualdepth) {
difference = actualdepth - expecteddepth;
} else {
v1 = tmp - t4;
difference = expecteddepth - actualdepth;
}
if (avg >= v1) {
t2++;
if (difference <= tolerance) {
numgood++;
}
#else
t2 += artifacts[k].unk02;
numgood += artifacts[k].visiblelos;
#endif
artifacts[k].type = ARTIFACTTYPE_FREE;
}
s3[0] = func0f13d3c4(s3[0], t2 * 2);
s3[0] = artifactsClamp(s3[0], numgood * 2);
if (t2 > 0) {
if (numgood > 0) {
#ifndef PLATFORM_N64
brightness = viGetFovY() / pfov;
#else
brightness = viGetFovY() * 0.017453292f;
#endif
add = cosf(brightness) / sinf(brightness) * 14.6f;
if (lightIsHealthy(roomnum, lightindex - g_Rooms[roomnum].gfxdata->lightsindex)) {
@@ -545,6 +667,9 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum)
}
f0 = s3[2] * (1.0f / 255.0f);
#ifndef PLATFORM_N64
f0 *= (60.f / pfov);
#endif
skySetOverexposure((s32) ((f32)f0 * r), (s32) ((f32)f0 * g), (s32) ((f32)f0 * b));
@@ -594,6 +719,10 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum)
alpha *= (s3[1] / 255.0f);
alpha *= (s3[0] / 8.0f);
#ifndef PLATFORM_N64
alpha *= brightscale;
#endif
if (USINGDEVICE(DEVICE_NIGHTVISION)) {
alpha *= lightop_cur_frac * 7.0f;
}
+37 -16
View File
@@ -15,7 +15,7 @@
#include "game/sky.h"
#include "game/stars.h"
#include "game/dyntex.h"
#include "game/game_13c510.h"
#include "game/artifact.h"
#include "game/game_1531a0.h"
#include "game/gfxmemory.h"
#include "game/gfxreplace.h"
@@ -47,6 +47,7 @@
#include "preprocess.h"
#include "system.h"
#include "video.h"
#include "platform.h"
#endif
#define BGCMD_END 0x00
@@ -97,7 +98,7 @@ u16 g_BgUnloadDelay240;
u16 g_BgUnloadDelay240_2;
u32 var800a4bf4;
RoomNum g_GlareRooms[100];
u32 *g_BgPrimaryData2;
uintptr_t *g_BgPrimaryData2;
struct bgroom *g_BgRooms;
struct bgportal *g_BgPortals;
struct portalmetric *g_PortalMetrics;
@@ -113,7 +114,7 @@ struct portalcamcacheitem *g_PortalCameraCache;
struct bgsnake g_BgSnake;
s32 g_StageIndex = 1;
u32 var8007fc04 = 0;
uintptr_t var8007fc04 = 0;
u8 *var8007fc08 = NULL;
#if VERSION < VERSION_NTSC_1_0
@@ -134,6 +135,9 @@ s32 g_BgMostAttemptedDrawSlots = 0;
s32 g_BgNumRoomLoadCandidates = 0;
u16 g_BgFrameCount = 0xfffe;
s32 g_BgNumPortalCameraCacheItems = 0;
#ifndef PLATFORM_N64
bool g_BgHitXluDisabled = false;
#endif
void bgUnpausePropsInRoom(u32 roomnum, bool tintedglassonly)
{
@@ -763,7 +767,7 @@ Gfx *bgRenderGdlInXray(Gfx *gdl, s8 *readgdl, Vtx *vertices, s16 arg3[3])
gdl = bgProcessXrayTri(gdl, &xraydata, dmemvertices[x], dmemvertices[y], dmemvertices[z], dmemcolours[x], dmemcolours[y], dmemcolours[z], inrange[x], inrange[y], inrange[z]);
}
readgdl += 8;
readgdl += sizeof(Gfx);
}
gdl = bgRenderXrayData(gdl, &xraydata);
@@ -1468,7 +1472,7 @@ void bgReset(s32 stagenum)
u32 section2compsize;
u32 section2start;
u32 section1compsize;
u32 scratch;
uintptr_t scratch;
var8007fc0c = 8;
@@ -1509,6 +1513,11 @@ void bgReset(s32 stagenum)
primcompsize = *(u32 *)&header[8];
var8007fc54 = inflatedsize - primcompsize;
var8007fc54 -= 0xc;
#ifdef PLATFORM_64BIT
inflatedsize = romdataFileGetEstimatedSize(inflatedsize, LOADTYPE_BG);
#endif
inflatedsize = ALIGN16(inflatedsize);
// Allocate space for the primary bg data
@@ -1529,7 +1538,7 @@ void bgReset(s32 stagenum)
bgInflate((u8 *) scratch, g_BgPrimaryData, primcompsize);
#ifndef PLATFORM_N64
preprocessBgSection1(g_BgPrimaryData, 0x0f000000);
preprocessBgSection1(g_BgPrimaryData, inflatedsize, 0x0f000000);
#endif
// Shrink the allocation (ie. free the scratch space)
@@ -1598,7 +1607,7 @@ void bgReset(s32 stagenum)
// Copy 0x40 bytes from a random location in ROM to a random
// location in RAM. The write address can be anywhere in the
// boot segment or in the lib segment up to modelRenderNodeDl.
dmaExec((void *)(PHYS_TO_K0(0x1000) + (random() & 0x1fff8)), random() & 0x1fffe, 0x40);
dmaExec((void *)(PHYS_TO_K0(0x1000) + (rngRandom() & 0x1fff8)), rngRandom() & 0x1fffe, 0x40);
}
}
#endif
@@ -1606,7 +1615,7 @@ void bgReset(s32 stagenum)
var800a4920 = *(u32 *)g_BgPrimaryData;
if (var800a4920 == 0) {
g_BgPrimaryData2 = (u32 *)g_BgPrimaryData;
g_BgPrimaryData2 = (uintptr_t*)g_BgPrimaryData;
g_BgRooms = (struct bgroom *)(g_BgPrimaryData2[1] + g_BgPrimaryData - 0x0f000000);
goto foo; foo:;
g_Vars.roomcount = 0;
@@ -1998,10 +2007,6 @@ void bgBuildTables(s32 stagenum)
numlightsptr++;
}
#ifndef PLATFORM_N64
preprocessBgLights(g_BgLightsFileData, 0);
#endif
// Free the section 3 allocation
mempRealloc(section3, 0, MEMPOOL_STAGE);
@@ -2820,6 +2825,11 @@ void bgLoadRoom(s32 roomnum)
#endif
}
#ifdef PLATFORM_64BIT
alloclen = alloclen * 4; // just to be safe for now, adjust properly later #TODO
#endif
#ifdef PLATFORM_N64
bgGarbageCollectRooms(alloclen, false);
@@ -2856,7 +2866,7 @@ void bgLoadRoom(s32 roomnum)
// Inflate the data to the left side of the allocation
inflatedlen = bgInflate(memaddr, allocation, g_BgRooms[roomnum + 1].unk00 - g_BgRooms[roomnum].unk00);
#ifndef PLATFORM_N64
preprocessBgRoom(allocation, g_BgRooms[roomnum].unk00);
inflatedlen = preprocessBgRoom(allocation, inflatedlen, g_BgRooms[roomnum].unk00);
#endif
g_Rooms[roomnum].gfxdata = (struct roomgfxdata *)allocation;
@@ -2937,7 +2947,7 @@ void bgLoadRoom(s32 roomnum)
// Copy gdls to the right-side of the allocation
// and build a pointer array to them
texCopyGdls((void *) gfxblocks[0], (void *) (allocation + alloclen - (gfxblocks[numgdls] - gfxblocks[0])), (u32) (gfxblocks[numgdls] - gfxblocks[0]));
texCopyGdls((void *) gfxblocks[0], (void *) (allocation + alloclen - (gfxblocks[numgdls] - gfxblocks[0])), (uintptr_t) (gfxblocks[numgdls] - gfxblocks[0]));
for (i = 0; i < numgdls + 1; i++) {
gdlpointers[i] = gfxblocks[i] + (allocation + alloclen - gfxblocks[numgdls]);
@@ -3640,7 +3650,7 @@ bool bgTestHitOnObj(struct coord *arg0, struct coord *arg1, struct coord *arg2,
Gfx *imggdl = NULL;
s32 texturenum;
f32 lowestsqdist = MAXFLOAT;
s32 offset;
uintptr_t offset;
s32 numvertices;
Gfx *tri4gdl;
s32 count;
@@ -4243,7 +4253,7 @@ bool bgTestHitInVtxBatch(struct coord *arg0, struct coord *arg1, struct coord *a
vtx = bgFindVerticesForGdl(roomnum, gdl);
iter = &gdl[batch->gbicmdindex];
vtx = (Vtx *)((UNSEGADDR(iter->words.w1) & 0xffffff) + (s32)vtx);
vtx = (Vtx *)((UNSEGADDR(iter->words.w1) & 0xffffff) + (uintptr_t)vtx);
numvertices = (((u32) iter->bytes[GFX_W0_BYTE(1)] >> 4) & 0xf) + 1;
ptr = var800a6470;
@@ -4583,6 +4593,10 @@ bool bgTestHitInRoom(struct coord *frompos, struct coord *topos, s32 roomnum, st
numbatches = g_Rooms[roomnum].numvtxbatches;
for (i = 0; i < numbatches; batch++, i++) {
#ifndef PLATFORM_N64
if (g_BgHitXluDisabled && batch->type == VTXBATCHTYPE_XLU)
continue;
#endif
j = bg0f1612e4(&batch->bbmin, &batch->bbmax, &from, &dist, &sp94, &hitthing->pos);
if (j == 0) {
@@ -6410,6 +6424,10 @@ void bgCalculateGlaresForVisibleRooms(void)
g_NumRoomsWithGlares = 0;
// disable line-of-sight hits for transparent background
// surfaces before testing for light obstructions
g_BgHitXluDisabled = true;
if (!g_Vars.mplayerisrunning) {
for (i = 1; i < g_Vars.roomcount; i++) {
if (g_Rooms[i].flags & ROOMFLAG_ONSCREEN) {
@@ -6420,6 +6438,9 @@ void bgCalculateGlaresForVisibleRooms(void)
}
}
}
// re-enable background hits for transparent surfaces
g_BgHitXluDisabled = false;
}
#endif
+7 -7
View File
@@ -299,7 +299,7 @@ struct model *bodyAllocateModel(s32 bodynum, s32 headnum, u32 spawnflags)
if (spawnflags & SPAWNFLAG_FORCESUNGLASSES) {
sunglasses = true;
} else if (spawnflags & SPAWNFLAG_MAYBESUNGLASSES) {
sunglasses = random() % 2 == 0;
sunglasses = rngRandom() % 2 == 0;
}
if (spawnflags & SPAWNFLAG_FIXEDHEIGHT) {
@@ -325,7 +325,7 @@ s32 bodyChooseHead(s32 bodynum)
g_ActiveMaleHeadsIndex = 0;
}
} else if (bodynum == BODY_FEM_GUARD) {
head = g_FemGuardHeads[random() % 3];
head = g_FemGuardHeads[rngRandom() % 3];
} else {
head = g_ActiveFemaleHeads[g_ActiveFemaleHeadsIndex++];
@@ -493,10 +493,10 @@ void bodyAllocateChr(s32 stagenum, struct packedchr *packed, s32 cmdindex)
if (packed->tude != 4) {
chr->tude = packed->tude;
} else {
chr->tude = random() % 4;
chr->tude = rngRandom() % 4;
}
chr->voicebox = random() % 3;
chr->voicebox = rngRandom() % 3;
if (!g_HeadsAndBodies[chr->bodynum].ismale) {
chr->voicebox = VOICEBOX_FEMALE;
@@ -519,7 +519,7 @@ void bodyAllocateChr(s32 stagenum, struct packedchr *packed, s32 cmdindex)
chr->flags |= CHRFLAG0_AIVSAI;
}
if (random() % 5 == 0) {
if (rngRandom() % 5 == 0) {
// Make chr punch slower
chr->flags2 |= CHRFLAG1_ADJUSTPUNCHSPEED;
}
@@ -596,8 +596,8 @@ struct prop *bodyAllocateEyespy(struct pad *pad, RoomNum room)
chr->team = 0;
chr->squadron = 0;
chr->maxdamage = 2;
chr->tude = random() & 3;
chr->voicebox = random() % 3;
chr->tude = rngRandom() & 3;
chr->voicebox = rngRandom() % 3;
chr->naturalanim = 0;
chr->myspecial = 0;
chr->yvisang = 0;
+3 -3
View File
@@ -26,7 +26,7 @@ void bodiesReset(s32 stagenum)
g_HeadsAndBodies[i].modeldef = NULL;
}
var80062c80 = random() % g_NumBondBodies;
var80062c80 = rngRandom() % g_NumBondBodies;
var80062b14 = 0;
var80062b18 = 0;
@@ -67,7 +67,7 @@ void bodiesReset(s32 stagenum)
for (i = 0; i < g_NumActiveHeadsPerGender; i++) {
do {
done = true;
g_ActiveMaleHeads[i] = headsavailablelist[random() % headsavailablelen];
g_ActiveMaleHeads[i] = headsavailablelist[rngRandom() % headsavailablelen];
if (headsavailablelen > g_NumActiveHeadsPerGender) {
for (j = 0; j < i; j++) {
@@ -97,7 +97,7 @@ void bodiesReset(s32 stagenum)
for (i = 0; i < g_NumActiveHeadsPerGender; i++) {
do {
done = true;
g_ActiveFemaleHeads[i] = headsavailablelist[random() % headsavailablelen];
g_ActiveFemaleHeads[i] = headsavailablelist[rngRandom() % headsavailablelen];
if (headsavailablelen > g_NumActiveHeadsPerGender) {
for (j = 0; j < i; j++) {
+70 -72
View File
@@ -56,6 +56,7 @@
#ifndef PLATFORM_N64
#include "game/stagetable.h"
#include "video.h"
#include "platform.h"
#endif
#define GUNLOADSTATE_FLUX 0
@@ -165,8 +166,13 @@ u32 fill2[1];
Lights1 var80070090 = gdSPDefLights1(0x96, 0x96, 0x96, 0xff, 0xff, 0xff, 0xb2, 0x4d, 0x2e);
#ifdef PLATFORM_64BIT
u32 g_BgunGunMemBaseSizeDefault = 150 * 1024 * 2; // #TODO adjust these values properly
u32 g_BgunGunMemBaseSize4Mb2P = 120 * 1024 * 2;
#else
u32 g_BgunGunMemBaseSizeDefault = 150 * 1024;
u32 g_BgunGunMemBaseSize4Mb2P = 120 * 1024;
#endif
u16 g_CartFileNums[] = {
FILE_GCARTRIDGE,
@@ -890,7 +896,7 @@ void bgunStartAnimation(struct guncmd *cmd, s32 handnum, struct hand *hand)
if (cmd->type != GUNCMD_PLAYANIMATION) {
struct guncmd *loopcmd = cmd;
s32 done = false;
u32 rand = random() % 100;
u32 rand = rngRandom() % 100;
while (loopcmd->type != GUNCMD_END) {
if (bgun0f098884(loopcmd, &hand->gset) && !done) {
@@ -3794,17 +3800,17 @@ void bgunTickGunLoad(void)
{
s32 i;
s32 numthistick;
u32 remaining;
u64 remaining;
s32 padding;
u32 allocsize;
u32 loadsize;
u32 ptr;
u64 allocsize;
u64 loadsize;
uintptr_t ptr;
struct player *player = g_Vars.currentplayer;
struct modeldef *modeldef;
struct fileinfo *fileinfo;
struct fileinfo *gunfileinfo;
s32 newvalue;
u32 end;
uintptr_t newvalue;
uintptr_t end;
u32 stack;
#if VERSION >= VERSION_NTSC_1_0
u32 stack2;
@@ -3826,7 +3832,7 @@ void bgunTickGunLoad(void)
*player->gunctrl.loadmemptr = ptr;
*player->gunctrl.loadmemremaining = remaining;
loadsize = ALIGN64(fileGetInflatedSize(player->gunctrl.loadfilenum)) + 0x8000;
loadsize = ALIGN64(fileGetInflatedSize(player->gunctrl.loadfilenum, LOADTYPE_MODEL)) + 0x8000;
osSyncPrintf("BriGun: Loading - %s, pMem 0x%08x Size %d\n");
@@ -3844,6 +3850,9 @@ void bgunTickGunLoad(void)
// Reserve some space for textures
allocsize = fileGetLoadedSize(player->gunctrl.loadfilenum) + 0xe00;
#ifdef PLATFORM_64BIT
allocsize += 0xe00;
#endif
osSyncPrintf("BriGun: Used size %d (Ob Size %d)\n");
osSyncPrintf("BriGun: block len %d usedsize %d\n");
@@ -3854,7 +3863,7 @@ void bgunTickGunLoad(void)
fileinfo = &g_FileInfo[player->gunctrl.loadfilenum];
fileinfo->allocsize = allocsize;
end = ALIGN16((s32)ptr + allocsize);
end = ALIGN16((uintptr_t)ptr + allocsize);
allocsize = end - ptr;
if (1);
remaining -= allocsize;
@@ -3925,7 +3934,7 @@ void bgunTickGunLoad(void)
modeldef0f1a7560(modeldef, player->gunctrl.loadfilenum, 0x05000000, modeldef, &player->gunctrl.texpool, false);
fileGetInflatedSize(player->gunctrl.loadfilenum);
fileGetInflatedSize(player->gunctrl.loadfilenum, LOADTYPE_MODEL);
fileGetLoadedSize(player->gunctrl.loadfilenum);
fileGetLoadedSize(player->gunctrl.loadfilenum);
fileGetLoadedSize(player->gunctrl.loadfilenum);
@@ -3938,7 +3947,7 @@ void bgunTickGunLoad(void)
newvalue = ALIGN64(texGetPoolLeftPos(&player->gunctrl.texpool));
remaining = *player->gunctrl.loadmemremaining;
remaining -= (s32)(newvalue - *player->gunctrl.loadmemptr);
remaining -= (intptr_t)(newvalue - *player->gunctrl.loadmemptr);
*player->gunctrl.loadmemptr = newvalue;
*player->gunctrl.loadmemremaining = remaining;
@@ -4087,8 +4096,8 @@ void bgunTickMasterLoad(void)
player->gunctrl.gunloadstate = GUNLOADSTATE_MODEL;
player->gunctrl.loadfilenum = handfilenum;
player->gunctrl.loadtomodeldef = &player->gunctrl.handmodeldef;
player->gunctrl.loadmemptr = (u32 *) &player->gunctrl.handmemloadptr;
player->gunctrl.loadmemremaining = (u32 *) &player->gunctrl.handmemloadremaining;
player->gunctrl.loadmemptr = (uintptr_t *) &player->gunctrl.handmemloadptr;
player->gunctrl.loadmemremaining = (uintptr_t*) &player->gunctrl.handmemloadremaining;
}
bgunTickGunLoad();
@@ -4115,8 +4124,8 @@ void bgunTickMasterLoad(void)
player->gunctrl.gunloadstate = GUNLOADSTATE_MODEL;
player->gunctrl.loadfilenum = filenum;
player->gunctrl.loadtomodeldef = &player->gunctrl.gunmodeldef;
player->gunctrl.loadmemptr = (u32 *) &player->gunctrl.memloadptr;
player->gunctrl.loadmemremaining = (u32 *) &player->gunctrl.memloadremaining;
player->gunctrl.loadmemptr = (uintptr_t*) &player->gunctrl.memloadptr;
player->gunctrl.loadmemremaining = (uintptr_t*) &player->gunctrl.memloadremaining;
}
bgunTickGunLoad();
@@ -4157,8 +4166,8 @@ void bgunTickMasterLoad(void)
player->gunctrl.loadfilenum = filenum;
player->gunctrl.gunloadstate = GUNLOADSTATE_MODEL;
player->gunctrl.loadtomodeldef = &player->gunctrl.cartmodeldef;
player->gunctrl.loadmemptr = (u32 *) &player->gunctrl.memloadptr;
player->gunctrl.loadmemremaining = (u32 *) &player->gunctrl.memloadremaining;
player->gunctrl.loadmemptr = (uintptr_t *) &player->gunctrl.memloadptr;
player->gunctrl.loadmemremaining = (uintptr_t*) &player->gunctrl.memloadremaining;
break;
}
@@ -4184,18 +4193,18 @@ void bgunTickMasterLoad(void)
modelInit(&hand->handmodel, player->gunctrl.handmodeldef, hand->handsavedata, false);
}
hand->unk0dcc = (s32 *) player->gunctrl.memloadptr;
hand->unk0dcc = (uintptr_t *) player->gunctrl.memloadptr;
value = bgunCreateModelCmdList(&hand->gunmodel, player->gunctrl.gunmodeldef->rootnode, (s32 *) player->gunctrl.memloadptr);
value = bgunCreateModelCmdList(&hand->gunmodel, player->gunctrl.gunmodeldef->rootnode, (uintptr_t *) player->gunctrl.memloadptr);
sum += value;
player->gunctrl.memloadptr += value;
player->gunctrl.memloadremaining -= value;
if (player->gunctrl.handmodeldef != 0) {
hand->unk0dd0 = (s32 *) player->gunctrl.memloadptr;
hand->unk0dd0 = (uintptr_t*) player->gunctrl.memloadptr;
value = bgunCreateModelCmdList(&hand->handmodel, player->gunctrl.handmodeldef->rootnode, (s32 *) player->gunctrl.memloadptr);
value = bgunCreateModelCmdList(&hand->handmodel, player->gunctrl.handmodeldef->rootnode, (uintptr_t*) player->gunctrl.memloadptr);
sum += value;
player->gunctrl.memloadptr += value;
@@ -6415,7 +6424,7 @@ void bgunDisarm(struct prop *attackerprop)
*
* With this function stubbed, part of the CMP150 model does not render.
*/
void bgunExecuteModelCmdList(s32 *ptr)
void bgunExecuteModelCmdList(uintptr_t *ptr)
{
union modelrwdata *rwdata;
struct modelnode *node;
@@ -6472,7 +6481,7 @@ void bgunExecuteModelCmdList(s32 *ptr)
* iterate the command list to update part visibility rather than iterate the
* full model tree.
*/
s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, s32 *ptr)
s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, uintptr_t *ptr)
{
s32 len = 0;
struct modelnode *node = nodearg;
@@ -6489,11 +6498,11 @@ s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, s32 *
rwdata->distance.visible = false;
node->child = rodata->distance.target;
ptr[0] = 0;
ptr[1] = (s32)rwdata;
ptr[2] = (s32)node;
ptr[3] = (s32)rodata->distance.target;
ptr[1] = (uintptr_t)rwdata;
ptr[2] = (uintptr_t)node;
ptr[3] = (uintptr_t)rodata->distance.target;
ptr += 4;
len += 16;
len += 4 * sizeof(uintptr_t);
break;
case MODELNODETYPE_TOGGLE:
rodata = node->rodata;
@@ -6501,36 +6510,36 @@ s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, s32 *
rwdata->toggle.visible = true;
node->child = rodata->toggle.target;
ptr[0] = 1;
ptr[1] = (s32)rwdata;
ptr[2] = (s32)node;
ptr[3] = (s32)rodata->toggle.target;
ptr[1] = (uintptr_t)rwdata;
ptr[2] = (uintptr_t)node;
ptr[3] = (uintptr_t)rodata->toggle.target;
ptr += 4;
len += 16;
len += 4 * sizeof(uintptr_t);
break;
case MODELNODETYPE_HEADSPOT:
rwdata = modelGetNodeRwData(model, node);
rwdata->headspot.headmodeldef = NULL;
rwdata->headspot.rwdatas = NULL;
ptr[0] = 2;
ptr[1] = (s32)rwdata;
ptr[1] = (uintptr_t)rwdata;
ptr += 2;
len += 8;
len += 2 * sizeof(uintptr_t);
break;
case MODELNODETYPE_0B:
rwdata = modelGetNodeRwData(model, node);
rwdata->type0b.unk00 = 0;
ptr[0] = 3;
ptr[1] = (s32)rwdata;
ptr[1] = (uintptr_t)rwdata;
ptr += 2;
len += 8;
len += 2 * sizeof(uintptr_t);
break;
case MODELNODETYPE_CHRGUNFIRE:
rwdata = modelGetNodeRwData(model, node);
rwdata->chrgunfire.visible = false;
ptr[0] = 4;
ptr[1] = (s32)rwdata;
ptr[1] = (uintptr_t)rwdata;
ptr += 2;
len += 8;
len += 2 * sizeof(uintptr_t);
break;
case MODELNODETYPE_DL:
rodata = node->rodata;
@@ -6539,12 +6548,12 @@ s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, s32 *
rwdata->dl.gdl = rodata->dl.opagdl;
rwdata->dl.colours = (void *)ALIGN8((uintptr_t)&rodata->dl.vertices[rodata->dl.numvertices]);
ptr[0] = 5;
ptr[1] = (s32)rwdata;
ptr[2] = (s32)rwdata->dl.vertices;
ptr[3] = (s32)rwdata->dl.gdl;
ptr[4] = (s32)rwdata->dl.colours;
ptr[1] = (uintptr_t)rwdata;
ptr[2] = (uintptr_t)rwdata->dl.vertices;
ptr[3] = (uintptr_t)rwdata->dl.gdl;
ptr[4] = (uintptr_t)rwdata->dl.colours;
ptr += 5;
len += 20;
len += 5 * sizeof(uintptr_t);
break;
}
@@ -6568,7 +6577,7 @@ s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, s32 *
}
*ptr = 6;
len += 4;
len += sizeof(uintptr_t);
return len;
}
@@ -7161,7 +7170,7 @@ void bgunUpdateMagnum(struct hand *hand, s32 handnum, struct modeldef *modeldef,
if (modeldef != NULL) {
for (i = 0; i < hand->unk0cc8_04; i++) {
struct modelnode *node = modelGetPart(modeldef, 0x0a + random() % 6);
struct modelnode *node = modelGetPart(modeldef, 0x0a + rngRandom() % 6);
if (node) {
s32 index = modelFindNodeMtxIndex(node, 0);
@@ -8468,7 +8477,7 @@ glabel var7f1aca90
/* f0a71e4: 100002d5 */ b .L0f0a7d3c
/* f0a71e8: 8fbf0034 */ lw $ra,0x34($sp)
.L0f0a71ec:
/* f0a71ec: 0fc5d9ad */ jal zbufDrawArtifactsOffscreen
/* f0a71ec: 0fc5d9ad */ jal zbufSaveArtifactDepths
/* f0a71f0: 8fa4014c */ lw $a0,0x14c($sp)
/* f0a71f4: afa2014c */ sw $v0,0x14c($sp)
/* f0a71f8: 0c002ca0 */ jal viPrepareZbuf
@@ -9309,7 +9318,7 @@ glabel var7f1aca90
/* f0a71e4: 100002d5 */ b .L0f0a7d3c
/* f0a71e8: 8fbf0034 */ lw $ra,0x34($sp)
.L0f0a71ec:
/* f0a71ec: 0fc5d9ad */ jal zbufDrawArtifactsOffscreen
/* f0a71ec: 0fc5d9ad */ jal zbufSaveArtifactDepths
/* f0a71f0: 8fa4014c */ lw $a0,0x14c($sp)
/* f0a71f4: afa2014c */ sw $v0,0x14c($sp)
/* f0a71f8: 0c002ca0 */ jal viPrepareZbuf
@@ -10150,7 +10159,7 @@ glabel var7f1aca90
/* f0a4f30: 100002cd */ beqz $zero,.NB0f0a5a68
/* f0a4f34: 8fbf0034 */ lw $ra,0x34($sp)
.NB0f0a4f38:
/* f0a4f38: 0fc5c4d5 */ jal zbufDrawArtifactsOffscreen
/* f0a4f38: 0fc5c4d5 */ jal zbufSaveArtifactDepths
/* f0a4f3c: 8fa40144 */ lw $a0,0x144($sp)
/* f0a4f40: afa20144 */ sw $v0,0x144($sp)
/* f0a4f44: 0c002d00 */ jal viPrepareZbuf
@@ -10933,7 +10942,6 @@ void bgunRender(Gfx **gdlptr)
struct modelrenderdata renderdata = {NULL, true, 3}; // 10c
struct player *player;
s32 i;
const u32 wnorm = mtx00016dcc(0, 300);
static bool renderhand = true; // var800702dc
@@ -10949,7 +10957,7 @@ void bgunRender(Gfx **gdlptr)
}
#ifdef PLATFORM_N64 // TODO
gdl = zbufDrawArtifactsOffscreen(gdl);
gdl = zbufSaveArtifactDepths(gdl);
#endif
gdl = viPrepareZbuf(gdl);
gdl = vi0000b1d0(gdl);
@@ -10999,7 +11007,7 @@ void bgunRender(Gfx **gdlptr)
gSPLookAt(gdl++, camGetLookAt());
}
gSPPerspNormalize(gdl++, wnorm);
gSPPerspNormalize(gdl++, mtx00016dcc(0, 300));
// There is support for guns having a TV screen on them
// but no guns have this model part so it's not used.
@@ -11174,17 +11182,7 @@ void bgunRender(Gfx **gdlptr)
}
}
#ifndef PLATFORM_N64
// put the casings into the same Z range as the gun
gSPPerspNormalize(gdl++, wnorm);
#endif
casingsRender(&gdl);
#ifndef PLATFORM_N64
gSPPerspNormalize(gdl++, viGetPerspScale());
#endif
zbufSwap();
gdl = zbufConfigureRdp(gdl);
@@ -11216,8 +11214,8 @@ struct sndstate **bgunAllocateAudioHandle(void)
void bgunPlayPropHitSound(struct gset *gset, struct prop *prop, s32 texturenum)
{
#if VERSION >= VERSION_NTSC_1_0
u32 rand1 = random();
u32 rand2 = random();
u32 rand1 = rngRandom();
u32 rand2 = rngRandom();
struct sndstate **handle;
if (g_Vars.lvupdate240 <= 0) {
@@ -11296,8 +11294,8 @@ void bgunPlayPropHitSound(struct gset *gset, struct prop *prop, s32 texturenum)
if (texturenum == 10000) {
soundnum = SFX_SHIELD_DAMAGE;
} else if (gset->weaponnum == WEAPON_LASER) {
if (gset->weaponfunc == FUNC_PRIMARY || ((gset->unk063a % 4) == 0 && (random() % 2))) {
if ((random() % 2) == 0) {
if (gset->weaponfunc == FUNC_PRIMARY || ((gset->unk063a % 4) == 0 && (rngRandom() % 2))) {
if ((rngRandom() % 2) == 0) {
soundnum = SFX_CLOAK_ON;
} else {
soundnum = SFX_CLOAK_OFF;
@@ -11361,8 +11359,8 @@ void bgunPlayPropHitSound(struct gset *gset, struct prop *prop, s32 texturenum)
}
}
#else
u32 rand1 = random();
u32 rand2 = random();
u32 rand1 = rngRandom();
u32 rand2 = rngRandom();
struct sndstate **handle;
if (g_Vars.lvupdate240 <= 0) {
@@ -11435,7 +11433,7 @@ void bgunPlayPropHitSound(struct gset *gset, struct prop *prop, s32 texturenum)
soundnum = SFX_SHIELD_DAMAGE;
} else if (gset->weaponnum == WEAPON_LASER) {
if (gset->weaponfunc == FUNC_PRIMARY || (gset->unk063a % 8) == 0) {
if ((random() % 2) == 0) {
if ((rngRandom() % 2) == 0) {
soundnum = SFX_CLOAK_ON;
} else {
soundnum = SFX_CLOAK_OFF;
@@ -11513,8 +11511,8 @@ void bgunPlayBgHitSound(struct gset *gset, struct coord *hitpos, s32 texturenum,
{
#if VERSION >= VERSION_NTSC_1_0
struct sndstate **handle;
u32 rand1 = random();
u32 rand2 = random();
u32 rand1 = rngRandom();
u32 rand2 = rngRandom();
bool playdefault;
s16 soundnum;
bool overridden;
@@ -11537,7 +11535,7 @@ void bgunPlayBgHitSound(struct gset *gset, struct coord *hitpos, s32 texturenum,
if (gset->weaponnum == WEAPON_LASER) {
playdefault = false;
if (gset->weaponfunc == FUNC_PRIMARY || ((gset->unk063a % 4) == 0 && (random() % 2))) {
if (gset->weaponfunc == FUNC_PRIMARY || ((gset->unk063a % 4) == 0 && (rngRandom() % 2))) {
// Laser sounds
s16 sounds[] = {SFX_CLOAK_ON, SFX_CLOAK_OFF};
soundnum = sounds[rand1 % ARRAYCOUNT(sounds)];
@@ -11612,8 +11610,8 @@ void bgunPlayBgHitSound(struct gset *gset, struct coord *hitpos, s32 texturenum,
}
#else
struct sndstate **handle;
u32 rand1 = random();
u32 rand2 = random();
u32 rand1 = rngRandom();
u32 rand2 = rngRandom();
s16 soundnum;
bool overridden;
+84 -48
View File
@@ -329,11 +329,11 @@ void bmoveUpdateSpeedTheta(void)
f32 bmoveGetSpeedVertaLimit(f32 value)
{
if (value > 0) {
return (viGetFovY() * value * -0.7f) / 60.0f;
return (viGetFovY() * value * -0.7f) / PLAYER_DEFAULT_FOV;
}
if (value < 0) {
return (viGetFovY() * -value * 0.7f) / 60.0f;
return (viGetFovY() * -value * 0.7f) / PLAYER_DEFAULT_FOV;
}
return 0;
@@ -341,7 +341,7 @@ f32 bmoveGetSpeedVertaLimit(f32 value)
void bmoveUpdateSpeedVerta(f32 value)
{
f32 mult = viGetFovY() / 60.0f;
f32 mult = viGetFovY() / PLAYER_DEFAULT_FOV;
f32 limit = bmoveGetSpeedVertaLimit(value);
if (value > 0) {
@@ -384,11 +384,11 @@ void bmoveUpdateSpeedVerta(f32 value)
f32 bmoveGetSpeedThetaControlLimit(f32 value)
{
if (value > 0) {
return (viGetFovY() * value * -0.7f) / 60.0f;
return (viGetFovY() * value * -0.7f) / PLAYER_DEFAULT_FOV;
}
if (value < 0) {
return (viGetFovY() * -value * 0.7f) / 60.0f;
return (viGetFovY() * -value * 0.7f) / PLAYER_DEFAULT_FOV;
}
return 0;
@@ -396,7 +396,7 @@ f32 bmoveGetSpeedThetaControlLimit(f32 value)
void bmoveUpdateSpeedThetaControl(f32 value)
{
f32 mult = viGetFovY() / 60.0f;
f32 mult = viGetFovY() / PLAYER_DEFAULT_FOV;
f32 limit = bmoveGetSpeedThetaControlLimit(value);
if (value > 0) {
@@ -436,6 +436,38 @@ void bmoveUpdateSpeedThetaControl(f32 value)
}
}
/**
* Apply crosshair swivel based on camera movement with input detection
*/
static void bmoveApplyCrosshairSwivel(struct movedata *movedata, f32 mlookscale, f32 *x, f32 *y)
{
#ifdef PLATFORM_N64
*x = g_Vars.currentplayer->speedtheta * 0.3f + g_Vars.currentplayer->gunextraaimx;
*y = -g_Vars.currentplayer->speedverta * 0.1f + g_Vars.currentplayer->gunextraaimy;
#else
f32 xscale, yscale;
bool mouse_active = (movedata->freelookdx || movedata->freelookdy);
bool joystick_active = (movedata->c1stickxraw != 0 || movedata->c1stickyraw != 0);
if ((mouse_active) && joystick_active) {
// Mouse + joystick sway
xscale = PLAYER_EXTCFG().crosshairsway * 0.80f; // 80% for precision+joystick sway
yscale = PLAYER_EXTCFG().crosshairsway * 0.80f; // 80% for precision+joystick sway
} else if (mouse_active) {
// Mouse sway
xscale = PLAYER_EXTCFG().crosshairsway * 0.20f; // 20% for mouse sway
yscale = PLAYER_EXTCFG().crosshairsway * 0.30f; // 30% for mouse sway
} else {
// Joystick only or no input - full sway
xscale = yscale = PLAYER_EXTCFG().crosshairsway;
}
// Joystick x/y scaling
// 0.3f for x, 0.1f for y
*x = g_Vars.currentplayer->speedtheta * 0.3f * xscale + g_Vars.currentplayer->gunextraaimx;
*y = -g_Vars.currentplayer->speedverta * 0.1f * yscale + g_Vars.currentplayer->gunextraaimy;
#endif
}
/**
* Calculate the lookahead angle.
*
@@ -780,6 +812,12 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
movedata.freelookdy = -movedata.freelookdy;
}
}
// always pause with ESC
if (allowc1buttons && g_Vars.currentplayer->isdead == false && g_Vars.currentplayer->pausemode == PAUSEMODE_UNPAUSED) {
if (inputKeyJustPressed(VK_ESCAPE)) {
c1buttonsthisframe |= START_BUTTON;
}
}
#endif
// Pausing
@@ -901,7 +939,9 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
aimoffhist[i] = !aimonhist[i];
}
g_Vars.currentplayer->insightaimmode = aimonhist[numsamples - 1];
if (numsamples > 0) {
g_Vars.currentplayer->insightaimmode = aimonhist[numsamples - 1];
}
}
if (!lvIsPaused()) {
@@ -1232,7 +1272,9 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
aimoffhist[i] = !aimonhist[i];
}
g_Vars.currentplayer->insightaimmode = aimonhist[numsamples - 1];
if (numsamples > 0) {
g_Vars.currentplayer->insightaimmode = aimonhist[numsamples - 1];
}
}
if (!lvIsPaused()) {
@@ -1402,31 +1444,31 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
}
#ifndef PLATFORM_N64
// Handle turning and looking up/down via mouselook when aiming
if (g_Vars.currentplayer->insightaimmode && allowmcross && bgunGetWeaponNum(HAND_RIGHT) != WEAPON_HORIZONSCANNER) {
if (g_Vars.currentplayer->swivelpos[0] > 0.9f) {
movedata.aimturnrightspeed = (g_Vars.currentplayer->swivelpos[0] - 0.9f) / 0.1f;
movedata.aimturnleftspeed = 0.f;
} else if (g_Vars.currentplayer->swivelpos[0] < -0.9f) {
movedata.aimturnleftspeed = (g_Vars.currentplayer->swivelpos[0] - -0.9f) / -0.1f;
movedata.aimturnrightspeed = 0.f;
// Handle turning and looking (x/y) via mouselook when aiming
bool allowcross = allowmcross;
if (g_Vars.currentplayer->insightaimmode && allowcross && bgunGetWeaponNum(HAND_RIGHT) != WEAPON_HORIZONSCANNER) {
float edge_boundary = PLAYER_EXTCFG().crosshairedgeboundary;
if (g_Vars.currentplayer->swivelpos[0] > edge_boundary) {
movedata.aimturnrightspeed += (g_Vars.currentplayer->swivelpos[0] - edge_boundary) / (1.0f - edge_boundary);
} else if (g_Vars.currentplayer->swivelpos[0] < -edge_boundary) {
movedata.aimturnleftspeed += (g_Vars.currentplayer->swivelpos[0] + edge_boundary) / -(1.0f - edge_boundary);
}
f32 vertaup = 0.f, vertadown = 0.f;
if (g_Vars.currentplayer->swivelpos[1] > 0.9f) {
vertaup = (g_Vars.currentplayer->swivelpos[1] - 0.9f) / 0.1f;
} else if (g_Vars.currentplayer->swivelpos[1] < -0.9f) {
vertadown = (g_Vars.currentplayer->swivelpos[1] - -0.9f) / -0.1f;
if (g_Vars.currentplayer->swivelpos[1] > edge_boundary) {
vertaup = (g_Vars.currentplayer->swivelpos[1] - edge_boundary) / (1.0f - edge_boundary);
} else if (g_Vars.currentplayer->swivelpos[1] < -edge_boundary) {
vertadown = (g_Vars.currentplayer->swivelpos[1] + edge_boundary) / -(1.0f - edge_boundary);
}
// Uninvert pitch if needed
if (movedata.invertpitch) {
movedata.speedvertaup = vertadown;
movedata.speedvertadown = vertaup;
movedata.speedvertaup += vertadown;
movedata.speedvertadown += vertaup;
} else {
movedata.speedvertaup = vertaup;
movedata.speedvertadown = vertadown;
movedata.speedvertaup += vertaup;
movedata.speedvertadown += vertadown;
}
} else {
// Reset mouse aim position when not mouse aiming
// Reset mouse aim position when not aiming
g_Vars.currentplayer->swivelpos[0] = 0.f;
g_Vars.currentplayer->swivelpos[1] = 0.f;
}
@@ -1573,6 +1615,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
}
// Handle xbla-style crouch cycling
const s32 oldcrouchpos = g_Vars.currentplayer->crouchpos;
for (i = 0; i < numsamples; i++) {
// handle 1964GEPD style crouch setting
s32 crouchsample;
@@ -1614,6 +1657,10 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
}
}
}
// prevent uncrouching if we don't fit
while (g_Vars.currentplayer->crouchpos > oldcrouchpos && !bwalkCanUncrouch()) {
g_Vars.currentplayer->crouchpos--;
}
}
#endif
@@ -1795,7 +1842,9 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
g_Vars.currentplayer->bondactivateorreload = 0;
s32 usereloads = (controlmode != CONTROLMODE_PC);
#ifndef PLATFORM_N64
usereloads = usereloads || PLAYER_EXTCFG().usereloads;
if (controlmode == CONTROLMODE_PC && movedata.alt1tapcount) {
g_Vars.currentplayer->bondactivateorreload = g_Vars.currentplayer->bondactivateorreload | JO_ACTION_RELOAD;
}
@@ -1803,7 +1852,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
if (movedata.btapcount) {
g_Vars.currentplayer->activatetimelast = g_Vars.currentplayer->activatetimethis;
g_Vars.currentplayer->activatetimethis = g_Vars.lvframe60;
if (controlmode == CONTROLMODE_PC) {
if (!usereloads) {
g_Vars.currentplayer->bondactivateorreload = g_Vars.currentplayer->bondactivateorreload | JO_ACTION_ACTIVATE;
} else {
g_Vars.currentplayer->bondactivateorreload = movedata.btapcount ?
@@ -2015,7 +2064,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
}
} else {
if (movedata.cannaturalpitch) {
tmp = viGetFovY() / 60.0f;
tmp = viGetFovY() / PLAYER_DEFAULT_FOV;
fVar25 = movedata.analogpitch / 70.0f;
if (fVar25 > 1) {
@@ -2056,7 +2105,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
}
if (movedata.cannaturalturn) {
tmp = viGetFovY() / 60.0f;
tmp = viGetFovY() / PLAYER_DEFAULT_FOV;
fVar25 = movedata.analogturn / 70.0f;
if (fVar25 > 1) {
@@ -2169,15 +2218,8 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
x = g_Vars.currentplayer->speedtheta * 0.3f + g_Vars.currentplayer->gunextraaimx;
y = -g_Vars.currentplayer->speedverta * 0.1f + g_Vars.currentplayer->gunextraaimy;
#else
f32 xscale, yscale;
if (movedata.freelookdx || movedata.freelookdy) {
xscale = PLAYER_EXTCFG().crosshairsway * 0.20f;
yscale = PLAYER_EXTCFG().crosshairsway * 0.30f;
} else {
xscale = yscale = PLAYER_EXTCFG().crosshairsway;
}
x = g_Vars.currentplayer->speedtheta * 0.3f * xscale + g_Vars.currentplayer->gunextraaimx;
y = -g_Vars.currentplayer->speedverta * 0.1f * yscale + g_Vars.currentplayer->gunextraaimy;
// Crosshair swivel movement system
bmoveApplyCrosshairSwivel(&movedata, mlookscale, &x, &y);
#endif
bgunSwivelWithDamp(x, y, PAL ? 0.955f : 0.963f);
@@ -2189,8 +2231,10 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
#ifndef PLATFORM_N64
if (allowmcross) {
// joystick is inactive, move crosshair using the mouse
const f32 xscale = PLAYER_EXTCFG().mouseaimspeedx * 320.f / (f32)videoGetWidth();
const f32 yscale = PLAYER_EXTCFG().mouseaimspeedy * 240.f / (f32)videoGetHeight();
const f32 xcoeff = 320.f / 1080.f;
const f32 ycoeff = 240.f / 1080.f;
const f32 xscale = (PLAYER_EXTCFG().mouseaimspeedx * xcoeff) / g_Vars.currentplayer->aspect;
const f32 yscale = PLAYER_EXTCFG().mouseaimspeedy * ycoeff;
f32 x = g_Vars.currentplayer->swivelpos[0] + movedata.freelookdx * xscale;
f32 y = g_Vars.currentplayer->swivelpos[1] + movedata.freelookdy * yscale;
x = (x < -1.f) ? -1.f : ((x > 1.f) ? 1.f : x);
@@ -2371,14 +2415,6 @@ void bmoveTick(bool allowc1x, bool allowc1y, bool allowc1buttons, bool ignorec2)
void bmoveUpdateVerta(void)
{
while (g_Vars.currentplayer->vv_verta < -180) {
g_Vars.currentplayer->vv_verta += 360;
}
while (g_Vars.currentplayer->vv_verta >= 180) {
g_Vars.currentplayer->vv_verta -= 360;
}
if (g_Vars.currentplayer->vv_verta > 90) {
g_Vars.currentplayer->vv_verta = 90;
} else if (g_Vars.currentplayer->vv_verta < -90) {
@@ -2483,7 +2519,7 @@ void bmoveUpdateHead(f32 arg0, f32 arg1, f32 arg2, Mtxf *arg3, f32 arg4)
}
} else {
if (g_Vars.currentplayer->startnewbonddie) {
bheadStartDeathAnimation(g_DeathAnimations[random() % g_NumDeathAnimations], random() % 2, 0, 1);
bheadStartDeathAnimation(g_DeathAnimations[rngRandom() % g_NumDeathAnimations], rngRandom() % 2, 0, 1);
g_Vars.currentplayer->startnewbonddie = false;
}
+48 -13
View File
@@ -31,7 +31,7 @@ char var800a41c0[26];
char var800a41c0[24];
#endif
u8 g_IrScanlines[2][480];
u8 g_IrScanlines[4][480];
#if VERSION < VERSION_NTSC_1_0
u8 var800a8b58nb[0x1c0];
@@ -335,7 +335,7 @@ Gfx *bviewDrawStatic(Gfx *gdl, u32 arg1, s32 arg2)
s32 viewheight = viGetViewHeight();
s32 viewwidth = viGetViewWidth();
s32 viewleft = viGetViewLeft();
u16 *fb2 = (u16 *) PHYS_TO_K0(random() & 0xfff00);
u16 *fb2 = (u16 *) PHYS_TO_K0(rngRandom() & 0xfff00);
s32 y;
gDPPipeSync(gdl++);
@@ -344,7 +344,7 @@ Gfx *bviewDrawStatic(Gfx *gdl, u32 arg1, s32 arg2)
#ifdef PLATFORM_N64
for (y = viewtop; y < viewtop + viewheight; y++) {
gdl = bviewCopyPixels(gdl, fb2, random() % 240, 5, y, 1.0f, viewleft, viewwidth);
gdl = bviewCopyPixels(gdl, fb2, rngRandom() % 240, 5, y, 1.0f, viewleft, viewwidth);
}
#else
gDPSetCombineLERP(gdl++,
@@ -468,8 +468,8 @@ Gfx *bviewDrawFilmInterlace(Gfx *gdl, u32 colour, u32 alpha)
}
}
if (random() % 20 == 1) {
tmpy = random() % 200;
if (rngRandom() % 20 == 1) {
tmpy = rngRandom() % 200;
}
gdl = bviewCopyPixels(gdl, fb, tmpy, 5, y, 1, viewleft, viewwidth);
@@ -490,8 +490,8 @@ Gfx *bviewDrawFilmInterlace(Gfx *gdl, u32 colour, u32 alpha)
}
}
if (random() % 20 == 1) {
tmpy += random() % 200;
if (rngRandom() % 20 == 1) {
tmpy += rngRandom() % 200;
}
gDPFillRectangle(gdl++, viewleft, tmpy, viewleft + viewwidth, tmpy + 1);
@@ -762,9 +762,9 @@ Gfx *bviewDrawFisheye(Gfx *gdl, u32 colour, u32 alpha, s32 shuttertime60, s8 sta
for (i = viewtop; i < viewtop + viewheight; i++) {
if (hit == EYESPYHIT_DAMAGE) {
alpha2 = (random() % 120) + 120;
alpha2 = (rngRandom() % 120) + 120;
colour = 0xff333300 | (alpha2 & 0xff);
f22 = ((random() % 32) + (f32) FBALLOC_HEIGHT) * (1.0f / 256.0f);
f22 = ((rngRandom() % 32) + (f32) FBALLOC_HEIGHT) * (1.0f / 256.0f);
gDPSetEnvColorViaWord(gdl++, colour);
} else {
@@ -1109,6 +1109,10 @@ Gfx *bviewDrawEyespyMetrics(Gfx *gdl)
s32 x = viewleft + (viewwidth >> 1);
s32 y = viewtop + (viewheight >> 1);
#ifndef PLATFORM_N64
gDPSetSubpixelOffsetEXT(gdl++, -2, -2);
#endif
gDPFillRectangle(gdl++, x + 2, y + 0, x + 7, y + 1);
gDPFillRectangle(gdl++, x + 2, y + 0, x + 5, y + 1);
gDPFillRectangle(gdl++, x - 6, y + 0, x - 1, y + 1);
@@ -1117,6 +1121,10 @@ Gfx *bviewDrawEyespyMetrics(Gfx *gdl)
gDPFillRectangle(gdl++, x + 0, y + 2, x + 1, y + 5);
gDPFillRectangle(gdl++, x + 0, y - 6, x + 1, y - 1);
gDPFillRectangle(gdl++, x + 0, y - 4, x + 1, y - 1);
#ifndef PLATFORM_N64
gDPSetSubpixelOffsetEXT(gdl++, 0, 0);
#endif
}
if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) {
@@ -2163,7 +2171,7 @@ Gfx *bviewDrawNvLens(Gfx *gdl)
u8 green;
if (((var8007f878 & 1) != (y & 1)) != 0) {
u8 tmp = random() % 12;
u8 tmp = rngRandom() % 12;
green = 0xff - tmp;
} else {
green = 0x94;
@@ -2181,7 +2189,7 @@ Gfx *bviewDrawNvLens(Gfx *gdl)
u8 green;
if (((var8007f878 & 1) != (y & 1)) != 0) {
u8 tmp = random() % 12;
u8 tmp = rngRandom() % 12;
green = 0xff - tmp;
} else {
green = 0x94;
@@ -2348,6 +2356,10 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
gSPSetExtraGeometryModeEXT(gdl++, G_MODULATE_EXT);
#endif
// fixes off by one error w/ two top players
if (g_Vars.currentplayernum == 0 || g_Vars.currentplayernum == 1) {
scanbottom++;
}
for (i = scantop; i < scanbottom; i++) {
#if VERSION >= VERSION_NTSC_1_0
if (i & 1) {
@@ -2363,7 +2375,7 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
}
#endif
red += random() % 8;
red += rngRandom() % 8;
if (red > 255) {
red = 255;
@@ -2384,6 +2396,10 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
s32 semicirclewidth = sqrtf(sqinnerradius - (s32) (f0 * f0)) * (viewwidth / (f32) SCREEN_WIDTH_LO);
s32 semicircleright = viewcentrex + semicirclewidth;
s32 rightsidewidth = viewwidth - semicircleright;
// if playernum is 1 or 3, shift to the right by viewwidth
if (g_Vars.currentplayernum == 1 || g_Vars.currentplayernum == 3) {
rightsidewidth += viewwidth;
}
#ifdef PLATFORM_N64
// Left and right of semicircle
@@ -2397,14 +2413,22 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
gdl = bviewCopyPixels(gdl, fb, i, 5, i, 1.0f, viewleft, viewwidth);
}
#else
// Left and right of semicircle
// Scanlines to the left and right of the semicircle
gDPFillRectangle(gdl++, viewleft, i, viewcentrex, i + 1);
if (PLAYERCOUNT() <= 2 && g_Vars.currentplayernum == 0 && i == viewcentrey) {
semicircleright -= 1;
}
else if (PLAYERCOUNT() > 2 && (g_Vars.currentplayernum == 1 || g_Vars.currentplayernum == 3 ) && i == viewcentrey) {
semicircleright -= 1;
}
gDPFillRectangle(gdl++, semicircleright, i, semicircleright + rightsidewidth, i + 1);
// The semicircle itself has a static colour
gDPSetPrimColorViaWord(gdl++, 0, 0, 0xee0000ff);
gDPFillRectangle(gdl++, viewcentrex, i, viewcentrex + semicirclewidth, i + 1);
} else {
// scanlines above and below the semicircle
gDPFillRectangle(gdl++, viewleft, i, viewleft + viewwidth, i + 1);
}
#endif
@@ -2773,6 +2797,10 @@ Gfx *bviewDrawIrBinoculars(Gfx *gdl)
s32 viewleft = viGetViewLeft();
s32 viewright = viewleft + viewwidth;
s32 viewbottom = viewtop + viewheight;
// fixes off by one error w/ two top players
if (g_Vars.currentplayernum == 0 || g_Vars.currentplayernum == 1) {
viewbottom++;
}
s32 leftx = viewleft + viewwidth / 3;
s32 rightx = viewleft + (viewwidth * 2) / 3;
s32 centrey = (viewtop + viewbottom) / 2;
@@ -2790,6 +2818,13 @@ Gfx *bviewDrawIrBinoculars(Gfx *gdl)
for (y = viewtop; y < viewbottom; y++) {
s32 ytocentre = centrey - y;
s32 sqytocentre = ytocentre * ytocentre;
if (PLAYERCOUNT() <= 2) {
sqytocentre += 1;
} else if (PLAYERCOUNT() > 2) {
if (g_Vars.currentplayernum == 1 || g_Vars.currentplayernum == 3) {
sqytocentre += 1;
}
}
if (sqytocentre < sqradius) {
s32 xoffset = (viewwidth / (f32) SCREEN_WIDTH_LO) * sqrtf(sqradius - sqytocentre);
+77 -1
View File
@@ -237,6 +237,47 @@ s32 bwalkTryMoveUpwards(f32 amount)
return result;
}
bool bwalkCanMoveUpwards(f32 amount)
{
bool result;
struct coord newpos;
RoomNum rooms[8];
u32 stack;
u32 types;
f32 ymax;
f32 ymin;
f32 radius;
if (g_Vars.currentplayer->floorflags & GEOFLAG_SLOPE) {
g_Vars.enableslopes = false;
} else {
g_Vars.enableslopes = true;
}
newpos.x = g_Vars.currentplayer->prop->pos.x;
newpos.y = g_Vars.currentplayer->prop->pos.y + amount;
newpos.z = g_Vars.currentplayer->prop->pos.z;
types = g_Vars.bondcollisions ? CDTYPE_ALL : CDTYPE_BG;
playerGetBbox(g_Vars.currentplayer->prop, &radius, &ymax, &ymin);
func0f065e74(&g_Vars.currentplayer->prop->pos, g_Vars.currentplayer->prop->rooms, &newpos, rooms);
bmoveFindEnteredRoomsByPos(g_Vars.currentplayer, &newpos, rooms);
propSetPerimEnabled(g_Vars.currentplayer->prop, false);
ymin -= 0.1f;
result = cdTestVolume(&newpos, radius, rooms, types, CHECKVERTICAL_YES,
ymax - g_Vars.currentplayer->prop->pos.y,
ymin - g_Vars.currentplayer->prop->pos.y);
propSetPerimEnabled(g_Vars.currentplayer->prop, true);
g_Vars.enableslopes = true;
return (result == CDRESULT_NOCOLLISION);
}
bool bwalkCalculateNewPosition(struct coord *vel, f32 rotateamount, bool apply, f32 extrawidth, s32 checktypes)
{
s32 result = CDRESULT_NOCOLLISION;
@@ -1070,7 +1111,7 @@ void bwalkUpdateVertical(void)
SFX_JO_LANDING_05B7
};
psCreate(NULL, g_Vars.currentplayer->prop, sounds[random() % 3],
psCreate(NULL, g_Vars.currentplayer->prop, sounds[rngRandom() % 3],
-1, -1, PSFLAG_0400 | PSFLAG_IGNOREROOMS, 0, PSTYPE_NONE, 0, -1, NULL, -1, -1, -1, -1);
}
}
@@ -1168,6 +1209,41 @@ void bwalkUpdateCrouchOffsetReal(void)
}
}
bool bwalkCanUncrouch(void)
{
f32 targetoffset = 0;
if (g_Vars.currentplayer->crouchpos == CROUCHPOS_SQUAT) {
targetoffset = -90;
} else if (g_Vars.currentplayer->crouchpos == CROUCHPOS_DUCK) {
targetoffset = -45;
}
if (targetoffset != g_Vars.currentplayer->crouchoffset) {
f32 prevcrouchoffset = g_Vars.currentplayer->crouchoffset;
f32 prevcrouchoffsetreal = g_Vars.currentplayer->crouchoffsetreal;
f32 prevcrouchoffsetsmall = g_Vars.currentplayer->crouchoffsetsmall;
f32 prevcrouchoffsetrealsmall = g_Vars.currentplayer->crouchoffsetrealsmall;
f32 prevcrouchspeed = g_Vars.currentplayer->crouchspeed;
g_Vars.currentplayer->crouchoffset = targetoffset;
bwalkUpdateCrouchOffsetReal();
const bool result = bwalkCanMoveUpwards(0);
g_Vars.currentplayer->crouchoffset = prevcrouchoffset;
g_Vars.currentplayer->crouchoffsetreal = prevcrouchoffsetreal;
g_Vars.currentplayer->crouchoffsetsmall = prevcrouchoffsetsmall;
g_Vars.currentplayer->crouchoffsetrealsmall = prevcrouchoffsetrealsmall;
g_Vars.currentplayer->crouchspeed = prevcrouchspeed;
return result;
}
return true;
}
void bwalkUpdateCrouchOffset(void)
{
f32 targetoffset = 0;
+1 -5
View File
@@ -138,8 +138,6 @@ void bossfileLoad(void)
g_BossFile.usingmultipletunes = savebufferReadBits(&buffer, 1);
g_AltTitleUnlocked = savebufferReadBits(&buffer, 1);
g_AltTitleEnabled = savebufferReadBits(&buffer, 1);
func0f0d54c4(&buffer);
}
if (failed) {
@@ -168,7 +166,7 @@ void bossfileSave(void)
savebufferOr(&buffer, g_Vars.language, 4);
for (i = 0; i < ARRAYCOUNT(g_BossFile.teamnames); i++) {
func0f0d55a4(&buffer, g_BossFile.teamnames[i]);
savebufferWriteString(&buffer, g_BossFile.teamnames[i]);
}
if (g_BossFile.tracknum == -1) {
@@ -185,8 +183,6 @@ void bossfileSave(void)
savebufferOr(&buffer, g_AltTitleUnlocked, 1);
savebufferOr(&buffer, g_AltTitleEnabled, 1);
func0f0d54c4(&buffer);
fileid = bossfileFindFileId();
if (fileid == 0) {
+52 -43
View File
@@ -185,13 +185,13 @@ void botReset(struct chrdata *chr, u8 respawning)
aibot->waypoints[0] = NULL;
aibot->numwaystepstotarget = 0;
aibot->random1 = random();
aibot->random1 = rngRandom();
aibot->random1ttl60 = 0;
aibot->targetcloaktimer60 = 0;
aibot->canseecloaked = 0;
aibot->rcpcloaktimer60 = 0;
aibot->random2ttl60 = 0;
aibot->random2 = random();
aibot->random2 = rngRandom();
aibot->randomfrac = RANDOMFRAC();
aibot->cheap = 0;
@@ -262,12 +262,21 @@ void botSpawn(struct chrdata *chr, u8 respawning)
func0f02e9a0(chr, 0);
#ifndef PLATFORM_N64
if ((g_MpSetup.options & MPOPTION_SPAWNWITHWEAPON)
if (g_Vars.normmplayerisrunning
&& (g_MpSetup.options & MPOPTION_SPAWNWITHWEAPON)
&& g_MpSetup.weapons[0] != MPWEAPON_NONE
&& g_MpSetup.weapons[0] != MPWEAPON_DISABLED) {
&& g_MpSetup.weapons[0] != MPWEAPON_DISABLED
&& g_MpSetup.weapons[0] != MPWEAPON_SHIELD) {
struct mpweapon *mpweapon = &g_MpWeapons[g_MpSetup.weapons[0]];
botinvGiveSingleWeapon(chr, mpweapon->weaponnum);
botactGiveAmmoByType(aibot, mpweapon->priammotype - 1, mpweapon->priammoqty / 2);
const s32 ammotype = (g_MpSetup.weapons[0] == MPWEAPON_COMBATBOOST) ? AMMOTYPE_BOOST : mpweapon->priammotype;
if (ammotype) {
s32 startammo = mpweapon->priammoqty / 2;
if (startammo == 0) {
startammo = 1;
}
botactGiveAmmoByType(aibot, ammotype, startammo);
}
botinvSwitchToWeapon(chr, mpweapon->weaponnum, FUNC_PRIMARY);
}
#endif
@@ -1409,8 +1418,8 @@ void bot0f192a74(struct chrdata *chr)
aibot->random3ttl60 -= g_Vars.lvupdate60;
if (aibot->random3ttl60 <= 0) {
aibot->random3 = random();
aibot->random3ttl60 = TICKS(20) + random() % TICKS(20);
aibot->random3 = rngRandom();
aibot->random3ttl60 = TICKS(20) + rngRandom() % TICKS(20);
}
if (g_Vars.lvupdate240 > 0) {
@@ -1551,7 +1560,7 @@ void botChooseGeneralTarget(struct chrdata *botchr)
// However, the usage of canseecloaked appears to be botched.
// It is implemented in botIsTargetInvisible, but that function is not
// called here while canseecloaked is true.
if (random() % TICKS(4 * 60 * 60) < g_MpNumChrs * g_Vars.lvupdate60) {
if (rngRandom() % TICKS(4 * 60 * 60) < g_MpNumChrs * g_Vars.lvupdate60) {
aibot->canseecloaked = true;
}
@@ -1746,7 +1755,7 @@ s32 botFindTeammateToFollow(struct chrdata *chr, f32 range)
if ((g_MpSetup.options & MPOPTION_TEAMSENABLED)
&& chr->myaction != MA_AIBOTFOLLOW
&& (random() % 100) < chr->aibot->followchance) {
&& (rngRandom() % 100) < chr->aibot->followchance) {
f32 closestdistance = 0;
s32 closestplayernum = -1;
s32 i;
@@ -1884,8 +1893,8 @@ struct prop *botFindPickup(struct chrdata *chr, s32 criteria)
for (i = 0; i < ARRAYCOUNT(weaponnums); i++) {
if (weaponnums[i] > WEAPON_UNARMED && weaponnums[i] == weapon->weaponnum) {
if (random() % 16) {
if (weapproplist[i] == NULL || sqdist1 < weapdistlist[i] || random() % 16 == 0) {
if (rngRandom() % 16) {
if (weapproplist[i] == NULL || sqdist1 < weapdistlist[i] || rngRandom() % 16 == 0) {
weapproplist[i] = prop;
weapdistlist[i] = sqdist1;
}
@@ -1896,8 +1905,8 @@ struct prop *botFindPickup(struct chrdata *chr, s32 criteria)
ammotype = botactGetAmmoTypeByFunction(weapon->weaponnum, FUNC_PRIMARY);
if (ammotype > 0 && random() % 16) {
if (ammoproplist[ammotype] == NULL || sqdist1 < ammodistlist[ammotype] || random() % 16 == 0) {
if (ammotype > 0 && rngRandom() % 16) {
if (ammoproplist[ammotype] == NULL || sqdist1 < ammodistlist[ammotype] || rngRandom() % 16 == 0) {
ammoproplist[ammotype] = prop;
ammodistlist[ammotype] = sqdist1;
}
@@ -1920,8 +1929,8 @@ struct prop *botFindPickup(struct chrdata *chr, s32 criteria)
if (weaponnum > 0) {
for (j = 0; j < ARRAYCOUNT(weaponnums); j++) {
if (weaponnums[j] > WEAPON_UNARMED && weaponnum == weaponnums[j]) {
if (random() % 16) {
if (weapproplist[j] == NULL || sqdist2 < weapdistlist[j] || random() % 16 == 0) {
if (rngRandom() % 16) {
if (weapproplist[j] == NULL || sqdist2 < weapdistlist[j] || rngRandom() % 16 == 0) {
weapproplist[j] = prop;
weapdistlist[j] = sqdist2;
}
@@ -1931,8 +1940,8 @@ struct prop *botFindPickup(struct chrdata *chr, s32 criteria)
}
}
if (random() % 16) {
if (ammoproplist[ammotype] == NULL || sqdist2 < ammodistlist[ammotype] || random() % 16 == 0) {
if (rngRandom() % 16) {
if (ammoproplist[ammotype] == NULL || sqdist2 < ammodistlist[ammotype] || rngRandom() % 16 == 0) {
ammoproplist[ammotype] = prop;
ammodistlist[ammotype] = sqdist2;
}
@@ -1944,11 +1953,11 @@ struct prop *botFindPickup(struct chrdata *chr, s32 criteria)
if (weaponnums[i] == WEAPON_MPSHIELD) {
sqdist2 = chrGetSquaredDistanceToCoord(chr, &prop->pos);
if (random() % 16 == 0) {
if (rngRandom() % 16 == 0) {
break;
}
if (weapproplist[i] == NULL || sqdist2 < weapdistlist[i] || random() % 16 == 0) {
if (weapproplist[i] == NULL || sqdist2 < weapdistlist[i] || rngRandom() % 16 == 0) {
weapproplist[i] = prop;
weapdistlist[i] = sqdist2;
}
@@ -2399,8 +2408,8 @@ void botTickUnpaused(struct chrdata *chr)
aibot->random2ttl60 -= g_Vars.lvupdate60;
if (aibot->random2ttl60 < 0) {
aibot->random2ttl60 = TICKS(1800) + random() % TICKS(60 * 240);
aibot->random2 = random();
aibot->random2ttl60 = TICKS(1800) + rngRandom() % TICKS(60 * 240);
aibot->random2 = rngRandom();
aibot->randomfrac = RANDOMFRAC();
}
@@ -2531,7 +2540,7 @@ void botTickUnpaused(struct chrdata *chr)
if (g_MpSetup.scenario == MPSCENARIO_HOLDTHEBRIEFCASE) {
s32 numgetting = botGetCountInTeamDoingCommand(chr, AIBOTCMD_GETCASE2, false);
if (numgetting <= 0 || (numgetting < (teamsize + 1) / 2 || random() % 100 < 66)) {
if (numgetting <= 0 || (numgetting < (teamsize + 1) / 2 || rngRandom() % 100 < 66)) {
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE2);
} else {
botApplyScenarioCommand(chr, AIBOTCMD_NORMAL);
@@ -2539,7 +2548,7 @@ void botTickUnpaused(struct chrdata *chr)
} else if (g_MpSetup.scenario == MPSCENARIO_HACKERCENTRAL) {
s32 numbots = botGetCountInTeamDoingCommand(chr, AIBOTCMD_DOWNLOAD, false);
if (aibot->hasuplink || numbots <= 0 || (numbots < (teamsize + 1) / 2 || random() % 100 < 50)) {
if (aibot->hasuplink || numbots <= 0 || (numbots < (teamsize + 1) / 2 || rngRandom() % 100 < 50)) {
botApplyScenarioCommand(chr, AIBOTCMD_DOWNLOAD);
} else {
botApplyScenarioCommand(chr, AIBOTCMD_NORMAL);
@@ -2547,7 +2556,7 @@ void botTickUnpaused(struct chrdata *chr)
} else if (g_MpSetup.scenario == MPSCENARIO_POPACAP) {
s32 numchasing = botGetCountInTeamDoingCommand(chr, AIBOTCMD_POPCAP, false);
if (numchasing <= 0 || numchasing < (teamsize + 1) / 2 || random() % 100 < 50) {
if (numchasing <= 0 || numchasing < (teamsize + 1) / 2 || rngRandom() % 100 < 50) {
botApplyScenarioCommand(chr, AIBOTCMD_POPCAP);
} else {
botApplyScenarioCommand(chr, AIBOTCMD_NORMAL);
@@ -2563,7 +2572,7 @@ void botTickUnpaused(struct chrdata *chr)
if (numinhill <= 0 || numinhill < teamsize / 2) {
botApplyScenarioCommand(chr, AIBOTCMD_HOLDHILL);
} else if (numinhill > botGetNumOpponentsInHill(chr)) {
if (random() % 100 < 50) {
if (rngRandom() % 100 < 50) {
botApplyScenarioCommand(chr, AIBOTCMD_DEFHILL);
} else {
botApplyScenarioCommand(chr, AIBOTCMD_NORMAL);
@@ -2579,13 +2588,13 @@ void botTickUnpaused(struct chrdata *chr)
if (botShouldReturnCtcToken(chr)) {
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
} else if (botIsChrsCtcTokenHeld(chr)) {
if (random() % 100 < 30) {
if (rngRandom() % 100 < 30) {
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
} else {
botApplyScenarioCommand(chr, AIBOTCMD_SAVECASE);
}
} else {
if (random() % 100 < 70 || numgetting <= 0) {
if (rngRandom() % 100 < 70 || numgetting <= 0) {
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
} else {
botApplyScenarioCommand(chr, AIBOTCMD_SAVECASE);
@@ -2599,7 +2608,7 @@ void botTickUnpaused(struct chrdata *chr)
if (botShouldReturnCtcToken(chr)) {
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
} else if (botIsChrsCtcTokenHeld(chr)) {
if (numsaving <= 0 || random() % 100 < 70) {
if (numsaving <= 0 || rngRandom() % 100 < 70) {
botApplyScenarioCommand(chr, AIBOTCMD_SAVECASE);
} else {
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
@@ -2608,9 +2617,9 @@ void botTickUnpaused(struct chrdata *chr)
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
} else if (numsaving <= 0 || numsaving < teamsize / 4) {
botApplyScenarioCommand(chr, AIBOTCMD_SAVECASE);
} else if (random() % 100 < 30) {
} else if (rngRandom() % 100 < 30) {
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
} else if (random() % 100 < 30) {
} else if (rngRandom() % 100 < 30) {
botApplyScenarioCommand(chr, AIBOTCMD_SAVECASE);
} else {
botApplyScenarioCommand(chr, AIBOTCMD_NORMAL);
@@ -2619,7 +2628,7 @@ void botTickUnpaused(struct chrdata *chr)
}
// Consider changing command in 20 to 60 seconds
aibot->commandtimer60 = TICKS(1200) + random() % TICKS(2400);
aibot->commandtimer60 = TICKS(1200) + rngRandom() % TICKS(2400);
}
}
@@ -2716,7 +2725,7 @@ void botTickUnpaused(struct chrdata *chr)
s32 index;
s32 i;
index = random() % numtokens;
index = rngRandom() % numtokens;
i = (index + 1) % numtokens;
@@ -2744,7 +2753,7 @@ void botTickUnpaused(struct chrdata *chr)
aibot->gotoprop = tokens[index];
} else if (botCanFollow(chr, tokens[index]->chr)) {
newaction = MA_AIBOTFOLLOW;
aibot->canbreakfollow = random() % 4 == 0;
aibot->canbreakfollow = rngRandom() % 4 == 0;
aibot->followingplayernum = mpPlayerGetIndex(tokens[index]->chr);
}
}
@@ -2762,7 +2771,7 @@ void botTickUnpaused(struct chrdata *chr)
// Held by a teammate - follow/protect them
if (botCanFollow(chr, tokenchr)) {
newaction = MA_AIBOTFOLLOW;
aibot->canbreakfollow = random() % 4 == 0;
aibot->canbreakfollow = rngRandom() % 4 == 0;
aibot->followingplayernum = mpPlayerGetIndex(tokenchr);
}
} else {
@@ -2852,7 +2861,7 @@ void botTickUnpaused(struct chrdata *chr)
// Uplink is held by teammate - protect them
if (botCanFollow(chr, uplinkchr)) {
newaction = MA_AIBOTFOLLOW;
aibot->canbreakfollow = random() % 4 == 0;
aibot->canbreakfollow = rngRandom() % 4 == 0;
aibot->followingplayernum = mpPlayerGetIndex(uplinkchr);
}
} else {
@@ -2883,7 +2892,7 @@ void botTickUnpaused(struct chrdata *chr)
// Briefcase is held by teammate - protect them
if (botCanFollow(chr, tokenchr)) {
newaction = MA_AIBOTFOLLOW;
aibot->canbreakfollow = random() % 4 == 0;
aibot->canbreakfollow = rngRandom() % 4 == 0;
aibot->followingplayernum = mpPlayerGetIndex(tokenchr);
}
} else if (!botIsTargetInvisible(chr, tokenchr) && botPassesCowardCheck(chr, tokenchr)) {
@@ -2911,7 +2920,7 @@ void botTickUnpaused(struct chrdata *chr)
// Victim is a teammate - protect them
if (botCanFollow(chr, victimchr)) {
newaction = MA_AIBOTFOLLOW;
aibot->canbreakfollow = random() % 4 == 0;
aibot->canbreakfollow = rngRandom() % 4 == 0;
aibot->followingplayernum = mpPlayerGetIndex(victimchr);
}
} else {
@@ -2936,13 +2945,13 @@ void botTickUnpaused(struct chrdata *chr)
// Current bot has the briefcase - follow a teammate for protection
s32 playernum = -1;
if (random() % 100 < 66) {
if (rngRandom() % 100 < 66) {
playernum = botFindTeammateToFollow(chr, 100000);
}
if (playernum >= 0) {
newaction = MA_AIBOTFOLLOW;
aibot->canbreakfollow = random() % 4 == 0;
aibot->canbreakfollow = rngRandom() % 4 == 0;
aibot->followingplayernum = playernum;
}
}
@@ -2954,13 +2963,13 @@ void botTickUnpaused(struct chrdata *chr)
// Current bot is the victim - follow a teammate for protection
s32 playernum = -1;
if (random() % 100 < 66) {
if (rngRandom() % 100 < 66) {
playernum = botFindTeammateToFollow(chr, 100000);
}
if (playernum >= 0) {
newaction = MA_AIBOTFOLLOW;
aibot->canbreakfollow = random() % 4 == 0;
aibot->canbreakfollow = rngRandom() % 4 == 0;
aibot->followingplayernum = playernum;
}
}
@@ -3087,7 +3096,7 @@ void botTickUnpaused(struct chrdata *chr)
if (playernum >= 0) {
newaction = MA_AIBOTFOLLOW;
aibot->canbreakfollow = random() % 4 == 0;
aibot->canbreakfollow = rngRandom() % 4 == 0;
aibot->followingplayernum = playernum;
}
}
@@ -3427,7 +3436,7 @@ void botTickUnpaused(struct chrdata *chr)
aibot->punchtimer60[0] = TICKS(30);
}
if (random() % 3 == 0) {
if (rngRandom() % 3 == 0) {
aibot->punchtimer60[1] = aibot->punchtimer60[0] - TICKS(20);
}
break;
+1 -1
View File
@@ -223,7 +223,7 @@ bool botactShootFarsight(struct chrdata *chr, s32 arg1, struct coord *vector, st
aibot = chr->aibot;
if (aibot->weaponnum == WEAPON_FARSIGHT) {
rand = random() % 100;
rand = rngRandom() % 100;
// 3 in 10 chance of this passing
if (rand < 30) {
+1 -1
View File
@@ -149,7 +149,7 @@ void botcmdTickDistMode(struct chrdata *chr)
if (!insight) {
newmode = BOTDISTMODE_ADVANCE;
aibot->distoverrideprop = targetprop;
aibot->distoverridetimer60 = TICKS(20) + (random() % TICKS(120));
aibot->distoverridetimer60 = TICKS(20) + (rngRandom() % TICKS(120));
} else if (aibot->distoverrideprop) {
if (g_Vars.lvupdate60 < aibot->distoverridetimer60) {
aibot->distoverridetimer60 -= g_Vars.lvupdate60;
+14 -14
View File
@@ -71,14 +71,14 @@ struct aibotweaponpreference g_AibotWeaponPreferences[] = {
/*0x22*/ { 44, 156, 0, 0, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 5, 5, 2, 2, 1, 0 }, // WEAPON_REMOTEMINE
/*0x23*/ { 8, 8, 0, 0, 0, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 0, 0, 0, 0, 1, 0 }, // WEAPON_COMBATBOOST
#ifndef PLATFORM_N64 // add all classic weapons to multiplayer
/*0x24*/ { 56, 60, 84, 88, 1, 1, BOTDISTCFG_PISTOL, BOTDISTCFG_CLOSE, 30, 0, 10, 0, 1, 0 }, // WEAPON_PP9I
/*0x25*/ { 56, 60, 84, 88, 1, 1, BOTDISTCFG_PISTOL, BOTDISTCFG_CLOSE, 30, 0, 10, 0, 1, 0 }, // WEAPON_CC13
/*0x26*/ { 56, 60, 84, 88, 1, 1, BOTDISTCFG_DEFAULT, BOTDISTCFG_CLOSE, 30, 0, 10, 0, 1, 0 }, // WEAPON_KL01313
/*0x27*/ { 124, 148, 0, 0, 1, 1, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 90, 0, 30, 0, 1, 0 }, // WEAPON_KF7SPECIAL
/*0x28*/ { 116, 128, 136, 152, 1, 1, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 100, 0, 30, 0, 1, 0 }, // WEAPON_ZZT
/*0x29*/ { 124, 148, 0, 0, 1, 1, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 90, 0, 30, 0, 1, 0 }, // WEAPON_DMC
/*0x24*/ { 56, 60, 84, 88, 1, 0, BOTDISTCFG_PISTOL, BOTDISTCFG_CLOSE, 30, 0, 10, 0, 1, 0 }, // WEAPON_PP9I
/*0x25*/ { 56, 60, 84, 88, 1, 0, BOTDISTCFG_PISTOL, BOTDISTCFG_CLOSE, 30, 0, 10, 0, 1, 0 }, // WEAPON_CC13
/*0x26*/ { 56, 60, 84, 88, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_CLOSE, 30, 0, 10, 0, 1, 0 }, // WEAPON_KL01313
/*0x27*/ { 124, 148, 0, 0, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 90, 0, 30, 0, 1, 0 }, // WEAPON_KF7SPECIAL
/*0x28*/ { 116, 128, 136, 152, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 100, 0, 30, 0, 1, 0 }, // WEAPON_ZZT
/*0x29*/ { 124, 148, 0, 0, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 90, 0, 30, 0, 1, 0 }, // WEAPON_DMC
/*0x2a*/ { 156, 180, 0, 0, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 150, 0, 30, 0, 1, 0 }, // WEAPON_AR53
/*0x2b*/ { 164, 188, 0, 0, 1, 1, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 200, 0, 40, 0, 1, 0 }, // WEAPON_RCP45
/*0x2b*/ { 164, 188, 0, 0, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 200, 0, 40, 0, 1, 0 }, // WEAPON_RCP45
#else
/*0x24*/ { 0, 0, 0, 0, 0, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 0, 0, 0, 0, 1, 0 }, // WEAPON_PP9I
/*0x25*/ { 0, 0, 0, 0, 0, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 0, 0, 0, 0, 1, 0 }, // WEAPON_CC13
@@ -904,7 +904,7 @@ void botinvTick(struct chrdata *chr)
aibot->dampensuicidesttl60 -= g_Vars.lvupdate60;
if (aibot->dampensuicidesttl60 < 0) {
aibot->dampensuicidesttl60 = TICKS(3600) + random() % TICKS(60);
aibot->dampensuicidesttl60 = TICKS(3600) + rngRandom() % TICKS(60);
for (i = 0; i < ARRAYCOUNT(aibot->suicidesbygunfunc); i++) {
aibot->suicidesbygunfunc[i][0] *= 0.9f;
@@ -916,15 +916,15 @@ void botinvTick(struct chrdata *chr)
aibot->equipextrascorestimer60 -= g_Vars.lvupdate60;
if (aibot->equipextrascorestimer60 < 0) {
aibot->equipextrascorestimer60 = TICKS(600) + random() % TICKS(3000);
aibot->equipextrascorestimer60 = TICKS(600) + rngRandom() % TICKS(3000);
for (i = 0; i < ARRAYCOUNT(aibot->equipextrascores); i++) {
if (aibot->config->difficulty == BOTDIFF_MEAT) {
aibot->equipextrascores[i] = random() % 200 - 100; // -100 to +100
aibot->equipextrascores[i] = rngRandom() % 200 - 100; // -100 to +100
} else if (aibot->config->difficulty == BOTDIFF_EASY) {
aibot->equipextrascores[i] = random() % 100 - 50; // -50 to +50
aibot->equipextrascores[i] = rngRandom() % 100 - 50; // -50 to +50
} else {
aibot->equipextrascores[i] = random() % 30 - 15; // -15 to +15
aibot->equipextrascores[i] = rngRandom() % 30 - 15; // -15 to +15
}
}
}
@@ -934,8 +934,8 @@ void botinvTick(struct chrdata *chr)
aibot->random1ttl60 -= g_Vars.lvupdate60;
if (aibot->random1ttl60 < 0) {
aibot->random1ttl60 = TICKS(120) + random() % TICKS(600);
aibot->random1 = random();
aibot->random1ttl60 = TICKS(120) + rngRandom() % TICKS(600);
aibot->random1 = rngRandom();
}
if (aibot->cyclonedischarging[HAND_LEFT] == 0
+3 -3
View File
@@ -85,7 +85,7 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
if (aibot != NULL) {
chr->tude = 0;
chr->voicebox = random() % 3;
chr->voicebox = rngRandom() % 3;
if (g_HeadsAndBodies[chr->bodynum].ismale == false) {
chr->voicebox = VOICEBOX_FEMALE;
@@ -235,7 +235,7 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
aibot->realignangleframe = -1;
aibot->waypoints[0] = NULL;
aibot->numwaystepstotarget = 0;
aibot->random1 = random();
aibot->random1 = rngRandom();
aibot->random1ttl60 = 0;
for (i = 0; i < ARRAYCOUNT(aibot->killsbygunfunc); i++) {
@@ -258,7 +258,7 @@ void botmgrAllocateBot(s32 chrnum, s32 aibotnum)
aibot->canseecloaked = false;
aibot->random2ttl60 = 0;
aibot->random2 = random();
aibot->random2 = rngRandom();
aibot->randomfrac = RANDOMFRAC();
aibot->cheap = false;
#if VERSION >= VERSION_NTSC_1_0
+1 -1
View File
@@ -135,7 +135,7 @@ bool botroomFindPos(RoomNum room, struct coord *pos, f32 *angleptr, s32 *padnump
return false;
}
i = random() % totalcount;
i = rngRandom() % totalcount;
if (i < covercount) {
coverUnpack(covernums[i], &cover);
+5 -5
View File
@@ -317,7 +317,7 @@ void func0f149f18(void)
if (var800a45a0->unk470) {
for (i = 0; i < 0x4000; i++) {
var800a45a0->unk470[i] = random() % 255;
var800a45a0->unk470[i] = rngRandom() % 255;
}
}
}
@@ -1066,13 +1066,13 @@ void func0f14b394(struct var8007f8e0 *arg0)
size = align32(func0f14c814(&arg0->unk004));
for (i = 0; i < size; i++) {
arg0->unk004.textureptr[i] = random() % 0xff;
arg0->unk004.textureptr[i] = rngRandom() % 0xff;
}
size = align32(func0f14c814(&arg0->unk010));
for (i = 0; i < size; i++) {
arg0->unk010.textureptr[i] = random() % 0xff;
arg0->unk010.textureptr[i] = rngRandom() % 0xff;
}
func0f14b228(arg0);
@@ -2358,7 +2358,7 @@ void func0f14e7e0(u8 *arg0)
for (i = 0; i < 128; i++) {
for (j = 0; j < 128; j++) {
arg0[i * 128 + j] = random() % 255;
arg0[i * 128 + j] = rngRandom() % 255;
}
}
}
@@ -3151,7 +3151,7 @@ bool func0f15015c(s8 device, s32 filenum, u8 *arg2)
s32 size = 128;
for (i = 0; i < size; i++) {
arg2[i] = random();
arg2[i] = rngRandom();
}
return true;
+9
View File
@@ -400,6 +400,8 @@ struct mpconfigfull *challengeLoadConfig(s32 confignum, u8 *buffer, s32 len)
extern struct mpstrings EXT_SEG _mpstringsSSegmentRomEnd;
extern struct mpstrings EXT_SEG _mpstringsISegmentRomEnd;
extern struct mpconfig g_MpConfigs[];
BTYPE banks[][2] = {
{ (BTYPE)REF_SEG _mpstringsESegmentRomStart, (BTYPE)REF_SEG _mpstringsESegmentRomEnd },
{ (BTYPE)REF_SEG _mpstringsJSegmentRomStart, (BTYPE)REF_SEG _mpstringsJSegmentRomEnd },
@@ -421,6 +423,7 @@ struct mpconfigfull *challengeLoadConfig(s32 confignum, u8 *buffer, s32 len)
bank = banks[language_id][0];
loadedstrings = dmaExecWithAutoAlign(buffer2, bank + confignum * sizeof(struct mpstrings), sizeof(struct mpstrings));
mpconfig->config = g_MpConfigs[confignum];
mpconfig->strings = *loadedstrings;
return mpconfig;
@@ -687,6 +690,12 @@ void challengeApply(void)
for (i = 0; i < MAX_PLAYERS; i++) {
g_PlayerConfigsArray[i].base.team = 0;
}
#ifndef PLATFORM_N64
// Enable Friendly Fire option
g_MpSetup.options |= MPOPTION_FRIENDLYFIRE;
#endif
}
s32 challengeRemovePlayerLock(void)
+28 -4
View File
@@ -165,6 +165,17 @@ void cheatActivate(s32 cheat_id)
setCurrentPlayerNum(prevplayernum);
break;
case CHEAT_ALLGUNS:
#ifndef PLATFORM_N64
// Give all guns to all players
prevplayernum = g_Vars.currentplayernum;
for (playernum = 0; playernum < PLAYERCOUNT(); playernum++) {
setCurrentPlayerNum(playernum);
invSetAllGuns(true);
}
setCurrentPlayerNum(prevplayernum);
#else
// Give all guns if only one player playing
if (PLAYERCOUNT() == 1 && g_Vars.normmplayerisrunning == false) {
prevplayernum = g_Vars.currentplayernum;
@@ -176,6 +187,7 @@ void cheatActivate(s32 cheat_id)
setCurrentPlayerNum(prevplayernum);
}
#endif
break;
}
@@ -203,6 +215,16 @@ void cheatDeactivate(s32 cheat_id)
setCurrentPlayerNum(prevplayernum);
break;
case CHEAT_ALLGUNS:
#ifndef PLATFORM_N64
prevplayernum = g_Vars.currentplayernum;
for (playernum = 0; playernum < PLAYERCOUNT(); playernum++) {
setCurrentPlayerNum(playernum);
invSetAllGuns(false);
}
setCurrentPlayerNum(prevplayernum);
#else
if (PLAYERCOUNT() == 1 && g_Vars.normmplayerisrunning == false) {
prevplayernum = g_Vars.currentplayernum;
@@ -213,6 +235,7 @@ void cheatDeactivate(s32 cheat_id)
setCurrentPlayerNum(prevplayernum);
}
#endif
break;
}
@@ -309,7 +332,7 @@ MenuItemHandlerResult cheatCheckboxMenuHandler(s32 operation, struct menuitem *i
return false;
}
if (g_CheatsEnabledBank1 & (1 << item->param)) {
if (g_CheatsEnabledBank1 & (1 << (item->param - 32))) {
return true;
}
@@ -334,11 +357,12 @@ MenuItemHandlerResult cheatCheckboxMenuHandler(s32 operation, struct menuitem *i
}
} else {
// Bank 1
if (g_CheatsEnabledBank1 & (1 << item->param)) {
if (g_CheatsEnabledBank1 & (1 << (item->param - 32))) {
// We need to subtract 32 on lines like these to avoid undefined behavior, namely ensuring that all cheats are toggled correctly and regardless of build optimiaztion
if (1);
g_CheatsEnabledBank1 = g_CheatsEnabledBank1 & ~(1 << item->param);
g_CheatsEnabledBank1 = g_CheatsEnabledBank1 & ~(1 << (item->param - 32));
} else {
g_CheatsEnabledBank1 = g_CheatsEnabledBank1 | 1 << item->param;
g_CheatsEnabledBank1 = g_CheatsEnabledBank1 | (1 << (item->param - 32));
}
}
}
+31 -21
View File
@@ -1214,7 +1214,7 @@ void chrInit(struct prop *prop, u8 *ailist)
chr->cmnum2 = 0;
chr->cmnum3 = 0;
chr->cmnum4 = 0;
chr->cmcount = random() % 300;
chr->cmcount = rngRandom() % 300;
chr->footstep = 0;
chr->magicanim = -1;
chr->cover = -1;
@@ -1281,7 +1281,7 @@ void chrInit(struct prop *prop, u8 *ailist)
chr->p1p2 = g_Vars.bondplayernum;
chr->lastattacker = NULL;
chr->race = RACE_HUMAN;
chr->aimtesttimer60 = random() % TICKS(30);
chr->aimtesttimer60 = rngRandom() % TICKS(30);
chr->lastfootsample = 0;
chr->poisoncounter = 0;
chr->poisonprop = NULL;
@@ -1520,7 +1520,7 @@ void chrFlinchBody(struct chrdata *chr)
if (chr->actiontype != ACT_DEAD && chr->flinchcnt < 0) {
chr->flinchcnt = 1;
chr->hidden2 &= 0x0fff;
chr->hidden2 |= (u16)(random() << 13);
chr->hidden2 |= (u16)(rngRandom() << 13);
}
}
@@ -3681,7 +3681,7 @@ void chrEmitSparks(struct chrdata *chr, struct prop *prop, s32 hitpart, struct c
return;
}
if ((random() & 4) == 0) {
if ((rngRandom() & 4) == 0) {
struct coord coord3;
coord3.x = coord2->x * 42.0f + coord->x;
coord3.y = coord2->y * 42.0f + coord->y;
@@ -3710,7 +3710,7 @@ void chr0f0260c4(struct model *model, s32 hitpart, struct modelnode *node, struc
struct coord spd4;
struct coord spc8;
s32 spbc[3];
s32 alpha = 20 + (random() % 50);
s32 alpha = 20 + (rngRandom() % 50);
struct modelrodata_dl *rodata;
struct modelrwdata_dl *rwdata;
s32 spac = 0;
@@ -3866,13 +3866,13 @@ void chr0f0260c4(struct model *model, s32 hitpart, struct modelnode *node, struc
}
if (rwdata->gdl == rodata->opagdl) {
gdlptr = (Gfx *)((uintptr_t)rodata->colours + ((u32)UNSEGADDR(rodata->opagdl) & 0xffffff));
gdlptr = (Gfx *)((uintptr_t)rodata->colours + ((uintptr_t)UNSEGADDR(rodata->opagdl) & 0xffffff));
} else {
gdlptr = rwdata->gdl;
}
if (rodata->xlugdl) {
gdlptr2 = (Gfx *)((uintptr_t)rodata->colours + ((u32)UNSEGADDR(rodata->xlugdl) & 0xffffff));
gdlptr2 = (Gfx *)((uintptr_t)rodata->colours + ((uintptr_t)UNSEGADDR(rodata->xlugdl) & 0xffffff));
} else {
gdlptr2 = NULL;
}
@@ -3995,7 +3995,7 @@ void chrBruise(struct model *model, s32 hitpart, struct modelnode *node, struct
struct coord spd4;
struct coord spc8;
s32 spbc[3];
s32 alpha = 20 + (random() % 50);
s32 alpha = 20 + (rngRandom() % 50);
struct modelrodata_dl *rodata;
struct modelrwdata_dl *rwdata;
s32 spac = 0;
@@ -4026,13 +4026,13 @@ void chrBruise(struct model *model, s32 hitpart, struct modelnode *node, struct
// use the space... after the model definition's colour table?
// Let's hope that's not being used by other instances...
if (rwdata->gdl == rodata->opagdl) {
gdlptr = (Gfx *)((uintptr_t)rodata->colours + ((u32)UNSEGADDR(rodata->opagdl) & 0xffffff));
gdlptr = (Gfx *)((uintptr_t)rodata->colours + ((uintptr_t)UNSEGADDR(rodata->opagdl) & 0xffffff));
} else {
gdlptr = rwdata->gdl;
}
if (rodata->xlugdl) {
gdlptr2 = (Gfx *)((uintptr_t)rodata->colours + ((u32)UNSEGADDR(rodata->xlugdl) & 0xffffff));
gdlptr2 = (Gfx *)((uintptr_t)rodata->colours + ((uintptr_t)UNSEGADDR(rodata->xlugdl) & 0xffffff));
} else {
gdlptr2 = NULL;
}
@@ -4168,13 +4168,13 @@ void chrBruise(struct model *model, s32 hitpart, struct modelnode *node, struct
}
if (rwdata->gdl == rodata->opagdl) {
gdlptr = (Gfx *)((uintptr_t)rodata->colours + ((u32)UNSEGADDR(rodata->opagdl) & 0xffffff));
gdlptr = (Gfx *)((uintptr_t)rodata->colours + ((uintptr_t)UNSEGADDR(rodata->opagdl) & 0xffffff));
} else {
gdlptr = rwdata->gdl;
}
if (rodata->xlugdl) {
gdlptr2 = (Gfx *)((uintptr_t)rodata->colours + ((u32)UNSEGADDR(rodata->xlugdl) & 0xffffff));
gdlptr2 = (Gfx *)((uintptr_t)rodata->colours + ((uintptr_t)UNSEGADDR(rodata->xlugdl) & 0xffffff));
} else {
gdlptr2 = NULL;
}
@@ -4216,7 +4216,7 @@ void chrBruise(struct model *model, s32 hitpart, struct modelnode *node, struct
coordinate = vertices[i].z + (s32)spd4.f[2];
if (coordinate == bestcoords[2]) {
if ((uintptr_t)rwdata->colours == ALIGN8((u32)rodata->vertices + rodata->numvertices * sizeof(Vtx))) {
if ((uintptr_t)rwdata->colours == ALIGN8((uintptr_t)rodata->vertices + rodata->numvertices * sizeof(Vtx))) {
Col *colours = vtxstoreAllocate(rodata->numcolours, VTXSTORETYPE_CHRCOL, 0, 0);
s32 j;
@@ -4310,7 +4310,7 @@ void chrDisfigure(struct chrdata *chr, struct coord *exppos, f32 damageradius)
s32 i;
s32 j;
u32 rand = random();
u32 rand = rngRandom();
if (g_Vars.mplayerisrunning || !chrIsDead(chr)) {
return;
@@ -4363,13 +4363,13 @@ void chrDisfigure(struct chrdata *chr, struct coord *exppos, f32 damageradius)
if (rwdata->vertices != rodata->vertices
&& (uintptr_t)rwdata->colours != ALIGN8((uintptr_t)&rodata->vertices[rodata->numvertices])) {
if (rwdata->gdl == rodata->opagdl) {
gdlptr = (Gfx *)((uintptr_t)rodata->colours + ((s32)UNSEGADDR(rodata->opagdl) & 0xffffff));
gdlptr = (Gfx *)((uintptr_t)rodata->colours + ((uintptr_t)UNSEGADDR(rodata->opagdl) & 0xffffff));
} else {
gdlptr = rwdata->gdl;
}
if (rodata->xlugdl) {
gdlptr2 = (Gfx *)((uintptr_t)rodata->colours + ((s32)UNSEGADDR(rodata->xlugdl) & 0xffffff));
gdlptr2 = (Gfx *)((uintptr_t)rodata->colours + ((uintptr_t)UNSEGADDR(rodata->xlugdl) & 0xffffff));
} else {
gdlptr2 = NULL;
}
@@ -4544,7 +4544,17 @@ void chrTestHit(struct prop *prop, struct shotdata *shotdata, bool isshooting, b
if (hitpart) {
if (chrGetShield(chr) > 0.0f) {
var8005efc0 = 10.0f / model->scale;
#ifndef PLATFORM_N64
/**
* var8005efc0 > 0.0f adds a padding to bbox hit detection
* in modelTestBboxNodeForHit() that accounts for a character's
* surrounding shield. We skip this step on PC when checking
* line-of-sight hits to light artifacts because lights should
* be visible through the transparent shield.
*/
if (g_BgHitXluDisabled == false)
#endif
var8005efc0 = 10.0f / model->scale;
}
child = prop->child;
@@ -4708,7 +4718,7 @@ void chrHit(struct shotdata *shotdata, struct hit *hit)
type = g_SurfaceTypes[surfacetype];
if (type->numwallhittexes > 0) {
index = random() % type->numwallhittexes;
index = rngRandom() % type->numwallhittexes;
wallhitCreate(
&hit->hitthing.pos,
@@ -4744,7 +4754,7 @@ void chrHit(struct shotdata *shotdata, struct hit *hit)
type = g_SurfaceTypes[g_Textures[hit->hitthing.texturenum].surfacetype];
}
index = random() % type->numwallhittexes;
index = rngRandom() % type->numwallhittexes;
wallhitCreate(
&hit->hitthing.pos,
@@ -5191,7 +5201,7 @@ void shieldhitCreate(struct prop *prop, f32 shield, struct prop *arg2, struct mo
shieldhit->unk018[i] = -1;
}
shieldhit->unk011 = 2 + (random() % 6);
shieldhit->unk011 = 2 + (rngRandom() % 6);
shieldhit->shield = shield;
if (arg6) {
@@ -6495,7 +6505,7 @@ Gfx *chrRenderShield(Gfx *gdl, struct chrdata *chr, u32 alpha)
|| (chrGetShield(chr) > 0 && chr->cmcount < 10)
|| (chr->cloakfadefrac > 0 && !chr->cloakfadefinished)) {
if (chrGetShield(chr) > 0 && g_Vars.lvupdate240 > 0) {
s32 numiterations = (random() % 4) + 1;
s32 numiterations = (rngRandom() % 4) + 1;
s32 newcmnum = chr->cmnum2;
s32 candidate;
s8 operation = 0;
+127 -126
View File
@@ -1679,7 +1679,7 @@ void chrChooseStandAnimation(struct chrdata *chr, f32 mergetime)
} else if ((leftgun && rightgun) || (!leftgun && !rightgun)
|| weaponIsOneHanded(leftgun)
|| weaponIsOneHanded(rightgun)) {
modelSetAnimation(chr->model, ANIM_006A, random() % 2, 0, 0.25, mergetime);
modelSetAnimation(chr->model, ANIM_006A, rngRandom() % 2, 0, 0.25, mergetime);
modelSetAnimLooping(chr->model, 0, 16);
} else if (rightgun || leftgun) {
modelSetAnimation(chr->model, ANIM_TWO_GUN_HOLD, leftgun != NULL, 0, 0.25, mergetime);
@@ -1687,7 +1687,7 @@ void chrChooseStandAnimation(struct chrdata *chr, f32 mergetime)
modelSetAnimEndFrame(chr->model, 120);
}
} else if (race == RACE_SKEDAR) {
modelSetAnimation(chr->model, ANIM_00C0, random() % 2, 0, 0.5, mergetime);
modelSetAnimation(chr->model, ANIM_00C0, rngRandom() % 2, 0, 0.5, mergetime);
} else if (race == RACE_DRCAROLL) {
modelSetAnimation(chr->model, ANIM_013E, 0, 0, 0.5, mergetime);
} else if (race == RACE_ROBOT) {
@@ -1708,7 +1708,7 @@ void func0f02e9a0(struct chrdata *chr, f32 mergetime)
chr->act_stand.reaim = 0;
chr->act_stand.turning = TURNSTATE_OFF;
chr->act_stand.checkfacingwall = false;
chr->act_stand.wallcount = random() % 120 + 180; // 180 to 299
chr->act_stand.wallcount = rngRandom() % 120 + 180; // 180 to 299
chr->act_stand.mergetime = mergetime;
chr->act_stand.playwalkanim = false;
@@ -1750,7 +1750,7 @@ void chrStand(struct chrdata *chr)
chr->act_stand.reaim = 0;
chr->act_stand.turning = TURNSTATE_OFF;
chr->act_stand.checkfacingwall = false;
chr->act_stand.wallcount = random() % 120 + 180;
chr->act_stand.wallcount = rngRandom() % 120 + 180;
chr->sleep = 0;
chr->act_stand.playwalkanim = false;
@@ -1775,7 +1775,7 @@ void chrStand(struct chrdata *chr)
chr->act_stand.reaim = 0;
chr->act_stand.turning = TURNSTATE_OFF;
chr->act_stand.checkfacingwall = false;
chr->act_stand.wallcount = random() % 120 + 180;
chr->act_stand.wallcount = rngRandom() % 120 + 180;
chr->sleep = 0;
chr->act_stand.playwalkanim = false;
@@ -1828,7 +1828,7 @@ void chrKneelChooseAnimation(struct chrdata *chr)
|| (!leftgun && !rightgun)
|| weaponIsOneHanded(leftgun)
|| weaponIsOneHanded(rightgun)) {
bool flip = random() % 2;
bool flip = rngRandom() % 2;
modelSetAnimation(chr->model, ANIM_KNEEL_SHOOT_RIGHT_HAND, flip, 0, chrGetRangedSpeed(chr, 0.5, 0.8), 16);
modelSetAnimEndFrame(chr->model, 28);
} else if (rightgun || leftgun) {
@@ -1861,7 +1861,7 @@ void chrStartAlarmChooseAnimation(struct chrdata *chr)
if (leftgun && !rightgun) {
flip = true;
} else if ((leftgun && rightgun) || (!leftgun && !rightgun)) {
flip = random() % 2;
flip = rngRandom() % 2;
}
modelSetAnimation(chr->model, ANIM_TALKING_003D, flip, 40, 1, 16);
@@ -1884,7 +1884,7 @@ void chrStartAlarm(struct chrdata *chr)
void chrThrowGrenadeChooseAnimation(struct chrdata *chr)
{
u32 rand = random();
u32 rand = rngRandom();
if (chr->act_throwgrenade.needsequip) {
if (rand % 3 == 0) {
@@ -1933,17 +1933,17 @@ void chrSurprisedChooseAnimation(struct chrdata *chr)
if (leftgun != NULL && rightgun == NULL) {
flip = 1;
} else if ((leftgun != NULL && rightgun != NULL) || (leftgun == NULL && rightgun == NULL)) {
flip = random() & 1;
flip = rngRandom() & 1;
}
modelSetAnimation(chr->model, ANIM_003F, flip, 10, chrGetRangedSpeed(chr, 0.6f, 0.96000003f), 16);
modelSetAnimEndFrame(chr->model, 52);
} else if (chr->act_surprised.type == 2) {
modelSetAnimation(chr->model, ANIM_SURRENDER_002E, random() & 1, 0, chrGetRangedSpeed(chr, 0.35f, 0.56f), 16);
modelSetAnimation(chr->model, ANIM_SURRENDER_002E, rngRandom() & 1, 0, chrGetRangedSpeed(chr, 0.35f, 0.56f), 16);
modelSetAnimEndFrame(chr->model, 7);
} else {
u32 part = random() % 3;
modelSetAnimation(chr->model, ANIM_0040, random() & 1, 17, 0.6f, 16);
u32 part = rngRandom() % 3;
modelSetAnimation(chr->model, ANIM_0040, rngRandom() & 1, 17, 0.6f, 16);
if (part == 0) {
modelSetAnimEndFrame(chr->model, chrGetRangedSpeed(chr, 38, 8));
@@ -2014,7 +2014,7 @@ void chrSurrenderChooseAnimation(struct chrdata *chr)
struct prop *rightgun = chrGetHeldProp(chr, HAND_RIGHT);
if (rightgun || leftgun) {
modelSetAnimation(chr->model, ANIM_SURRENDER_002F, random() & 1, 0, 0.5, 16);
modelSetAnimation(chr->model, ANIM_SURRENDER_002F, rngRandom() & 1, 0, 0.5, 16);
modelSetAnimLooping(chr->model, 40, 16);
if (leftgun) {
@@ -2027,7 +2027,7 @@ void chrSurrenderChooseAnimation(struct chrdata *chr)
chr->hidden |= CHRHFLAG_DROPPINGITEM;
} else {
modelSetAnimation(chr->model, ANIM_SURRENDER_002E, random() & 1, 0, 0.5, 16);
modelSetAnimation(chr->model, ANIM_SURRENDER_002E, rngRandom() & 1, 0, 0.5, 16);
modelSetAnimLooping(chr->model, 30, 16);
}
@@ -2061,14 +2061,14 @@ void chrSidestepChooseAnimation(struct chrdata *chr)
u32 race = CHRRACE(chr);
if (leftgun && rightgun) {
flip = random() % 2;
allowflip = random() % 2;
flip = rngRandom() % 2;
allowflip = rngRandom() % 2;
} else {
if (weaponIsOneHanded(leftgun) == false
&& weaponIsOneHanded(rightgun) == false
&& (leftgun || rightgun)) {
flip = (leftgun != 0);
allowflip = random() % 2;
allowflip = rngRandom() % 2;
}
}
@@ -2126,7 +2126,7 @@ void chrJumpOutChooseAnimation(struct chrdata *chr)
flip = true;
} else if ((leftgun && rightgun) || (!leftgun && !rightgun)
|| weaponIsOneHanded(leftgun) || weaponIsOneHanded(rightgun)) {
flip = random() % 2;
flip = rngRandom() % 2;
}
if ((chr->act_jumpout.side && !flip) || (chr->act_jumpout.side == 0 && flip)) {
@@ -2167,7 +2167,7 @@ void chrRunPosChooseAnimation(struct chrdata *chr)
if ((leftgun && rightgun) || (!leftgun && !rightgun)) {
heavy = false;
flip = random() % 2;
flip = rngRandom() % 2;
} else if (weaponIsOneHanded(leftgun) || weaponIsOneHanded(rightgun)) {
heavy = false;
flip = (bool)leftgun != false;
@@ -2237,9 +2237,9 @@ void chrAttackStand(struct chrdata *chr, u32 attackflags, s32 entityid)
struct prop *rightgun2 = chrGetHeldUsableProp(chr, HAND_RIGHT);
if (leftgun2 && rightgun2) {
flip = random() % 2;
flip = rngRandom() % 2;
if (random() % 3 == 0) {
if (rngRandom() % 3 == 0) {
animgroup = g_StandLightAttackAnims[race];
firing[HAND_LEFT] = flip;
firing[HAND_RIGHT] = !flip;
@@ -2307,9 +2307,9 @@ void chrAttackKneel(struct chrdata *chr, u32 attackflags, s32 entityid)
rightgun2 = chrGetHeldUsableProp(chr, HAND_RIGHT);
if (leftgun2 && rightgun2) {
flip = random() % 2;
flip = rngRandom() % 2;
if (random() % 3 == 0) {
if (rngRandom() % 3 == 0) {
animgroup = g_KneelLightAttackAnims[race];
firing[HAND_LEFT] = flip;
firing[HAND_RIGHT] = !flip;
@@ -2368,8 +2368,8 @@ void chrAttackWalk(struct chrdata *chr, bool run)
s32 style = 0;
if (leftgun2 && rightgun2) {
flip = random() % 2;
style = random() % 3;
flip = rngRandom() % 2;
style = rngRandom() % 3;
} else {
flip = (bool)rightgun2 == false;
}
@@ -2469,14 +2469,14 @@ void chrAttackWalk(struct chrdata *chr, bool run)
chr->act_attackwalk.frame60count = 0;
#if PAL
// This is really TICKS(400.0f), but off by one bit :(
chr->act_attackwalk.frame60max = random() % (s32)(333.33331298828f * g_AttackWalkDurationScale) + TICKS(120);
chr->act_attackwalk.frame60max = rngRandom() % (s32)(333.33331298828f * g_AttackWalkDurationScale) + TICKS(120);
#else
chr->act_attackwalk.frame60max = random() % (s32)(400 * g_AttackWalkDurationScale) + TICKS(120);
chr->act_attackwalk.frame60max = rngRandom() % (s32)(400 * g_AttackWalkDurationScale) + TICKS(120);
#endif
chr->act_attackwalk.facedtarget = false;
chr->act_attackwalk.animcfg = animcfg;
chr->act_attackwalk.nextshot60 = 0;
chr->act_attackwalk.nextgun = random() % 2;
chr->act_attackwalk.nextgun = rngRandom() % 2;
chr->act_attackwalk.firegun[HAND_LEFT] = firing[HAND_LEFT];
chr->act_attackwalk.firegun[HAND_RIGHT] = firing[HAND_RIGHT];
chr->act_attackwalk.everytick[HAND_LEFT] = everytick[HAND_LEFT];
@@ -2541,10 +2541,10 @@ void chrAttackRoll(struct chrdata *chr, bool toleft)
struct prop *rightgun2 = chrGetHeldUsableProp(chr, HAND_RIGHT);
if (leftgun2 && rightgun2) {
flip = random() % 2;
flip = rngRandom() % 2;
onehanded = true;
if (random() % 3 == 0) {
if (rngRandom() % 3 == 0) {
firing[HAND_LEFT] = flip;
firing[HAND_RIGHT] = !flip;
} else {
@@ -2572,14 +2572,14 @@ void chrAttackRoll(struct chrdata *chr, bool toleft)
if ((toleft && !flip) || (!toleft && flip)) {
// Roll to left
if (random() % 2) {
if (rngRandom() % 2) {
animcfg = &g_RollAttackAnims[0];
} else {
animcfg = &g_RollAttackAnims[2];
}
} else {
// Roll to right
if (random() % 2) {
if (rngRandom() % 2) {
animcfg = &g_RollAttackAnims[1];
} else {
animcfg = &g_RollAttackAnims[3];
@@ -2633,7 +2633,7 @@ void chrAttackRoll(struct chrdata *chr, bool toleft)
chr->act_attack.animcfg = animcfg;
chr->act_attack.fired = false;
chr->act_attack.nextgun = random() % 2;
chr->act_attack.nextgun = rngRandom() % 2;
chr->act_attack.firegun[HAND_LEFT] = firing[HAND_LEFT];
chr->act_attack.firegun[HAND_RIGHT] = firing[HAND_RIGHT];
chr->act_attack.everytick[HAND_LEFT] = everytick[HAND_LEFT];
@@ -2654,10 +2654,10 @@ void chrAttackRoll(struct chrdata *chr, bool toleft)
chr->act_attack.maxshots = 1;
}
} else {
chr->act_attack.maxshots = (random() % 4) + 2;
chr->act_attack.maxshots = (rngRandom() % 4) + 2;
if (firing[HAND_RIGHT] && firing[HAND_LEFT]) {
chr->act_attack.maxshots += (random() % 4) + 2;
chr->act_attack.maxshots += (rngRandom() % 4) + 2;
}
}
@@ -2832,7 +2832,7 @@ void chrAttack(struct chrdata *chr, struct attackanimgroup **animgroups, bool fl
groupindex = 0;
}
index = random() % animgroups[groupindex]->len;
index = rngRandom() % animgroups[groupindex]->len;
animcfg = &animgroups[groupindex]->animcfg[index];
}
@@ -2885,7 +2885,7 @@ void chrAttack(struct chrdata *chr, struct attackanimgroup **animgroups, bool fl
chr->act_attack.turning = TURNSTATE_TURNING;
chr->act_attack.animcfg = animcfg;
chr->act_attack.fired = false;
chr->act_attack.nextgun = random() % 2;
chr->act_attack.nextgun = rngRandom() % 2;
chr->act_attack.firegun[HAND_LEFT] = firing[HAND_LEFT];
chr->act_attack.firegun[HAND_RIGHT] = firing[HAND_RIGHT];
chr->act_attack.everytick[HAND_LEFT] = everytick[HAND_LEFT];
@@ -2907,13 +2907,13 @@ void chrAttack(struct chrdata *chr, struct attackanimgroup **animgroups, bool fl
if (attackflags & ATTACKFLAG_SINGLESHOT) {
chr->act_attack.maxshots = 1;
} else {
chr->act_attack.maxshots = (random() % 4) + 2;
chr->act_attack.maxshots = (rngRandom() % 4) + 2;
}
// @bug: ATTACKFLAG_SINGLESHOT is not respected here if both guns
// are firing.
if (firing[HAND_RIGHT] && firing[HAND_LEFT]) {
chr->act_attack.maxshots += (random() % 4) + 2;
chr->act_attack.maxshots += (rngRandom() % 4) + 2;
}
}
@@ -3123,8 +3123,8 @@ void chrBeginDeath(struct chrdata *chr, struct coord *dir, f32 relangle, s32 hit
chr->act_die.thudframe2 = -1;
if (chr->race == RACE_DRCAROLL) {
chr->drcarollimage_left = (s32)((random() % 400) * 0.01f) + 1;
chr->drcarollimage_right = (s32)((random() % 400) * 0.01f) + 1;
chr->drcarollimage_left = (s32)((rngRandom() % 400) * 0.01f) + 1;
chr->drcarollimage_right = (s32)((rngRandom() % 400) * 0.01f) + 1;
}
chr->sleep = 0;
@@ -3170,7 +3170,7 @@ void chrBeginDeath(struct chrdata *chr, struct coord *dir, f32 relangle, s32 hit
// Consider making the chr do an animation where they slump against
// a wall or object which is behind them.
if ((relangle < 1.5705462694168f || relangle > 4.7116389274597f)
&& random() % 20 == 0
&& rngRandom() % 20 == 0
&& chr->specialdie == SPECIALDIE_NONE) {
f32 angle1;
f32 angle2 = chrGetInverseTheta(chr);
@@ -3194,7 +3194,7 @@ void chrBeginDeath(struct chrdata *chr, struct coord *dir, f32 relangle, s32 hit
if (fval1 < 150 && fval2 < 150
&& fval1 - fval2 < 10 && fval1 - fval2 > -10
&& !wasknockedout) {
struct animtablerow *row = &g_AnimTableHumanSlumped[random() % 4];
struct animtablerow *row = &g_AnimTableHumanSlumped[rngRandom() % 4];
u32 stack3;
chr->act_die.thudframe1 = row->thudframe1;
@@ -3216,7 +3216,7 @@ void chrBeginDeath(struct chrdata *chr, struct coord *dir, f32 relangle, s32 hit
// Consider making the chr do a fall forward animation.
// The player must be behind the chr for it to happen.
if (relangle > 2.3558194637299f && relangle < 3.9263656139374f
&& random() % 5 < 2
&& rngRandom() % 5 < 2
&& chr->specialdie == SPECIALDIE_NONE) {
struct animtablerow *row;
@@ -3239,7 +3239,7 @@ void chrBeginDeath(struct chrdata *chr, struct coord *dir, f32 relangle, s32 hit
}
} else {
row = &rows[1];
flip = random() % 2;
flip = rngRandom() % 2;
}
chr->act_die.thudframe1 = row->thudframe1;
@@ -3265,10 +3265,10 @@ void chrBeginDeath(struct chrdata *chr, struct coord *dir, f32 relangle, s32 hit
struct animtablerow *row;
if (chr->specialdie == SPECIALDIE_NONE) {
s32 tmp = random() % g_AnimTablesByRace[race][index].deathanimcount;
s32 tmp = rngRandom() % g_AnimTablesByRace[race][index].deathanimcount;
row = &g_AnimTablesByRace[race][index].deathanims[tmp];
} else if (chr->specialdie == SPECIALDIE_ONCHAIR) {
row = &g_SpecialDieAnims[chr->specialdie + random() % 2];
row = &g_SpecialDieAnims[chr->specialdie + rngRandom() % 2];
// chr->myspecial is the tag number of the chr's chair
if (chr->myspecial >= 0) {
@@ -3326,7 +3326,7 @@ void chrBeginDeath(struct chrdata *chr, struct coord *dir, f32 relangle, s32 hit
if (relangle > 2.3558194637299f && relangle < 3.9263656139374f) {
// Player is behind the Skedar - use specific set of anims
row = &g_AnimTablesByRace[race][1 + (random() % 6)].deathanims[random() % 3];
row = &g_AnimTablesByRace[race][1 + (rngRandom() % 6)].deathanims[rngRandom() % 3];
chr->act_die.thudframe1 = row->thudframe1;
chr->act_die.thudframe2 = row->thudframe2;
@@ -3341,7 +3341,7 @@ void chrBeginDeath(struct chrdata *chr, struct coord *dir, f32 relangle, s32 hit
if (index >= 0
&& g_AnimTablesByRace[race][index].deathanims != NULL
&& g_AnimTablesByRace[race][index].deathanimcount > 0) {
s32 tmp = random() % g_AnimTablesByRace[race][index].deathanimcount;
s32 tmp = rngRandom() % g_AnimTablesByRace[race][index].deathanimcount;
row = &g_AnimTablesByRace[race][index].deathanims[tmp];
} else {
row = &g_AnimTablesByRace[race][0].deathanims[0];
@@ -3458,7 +3458,7 @@ void chrBeginArgh(struct chrdata *chr, f32 angle, s32 hitpart)
&& hitpart == HITPART_PELVIS
&& angle > 2.3558194637299f
&& angle < 3.9263656139374f
&& random() % 5 < 2) {
&& rngRandom() % 5 < 2) {
struct animtablerow *row;
struct animtablerow rows[] = {
{ 0x013b, 0, -1, 0.5, 0, -1, -1 },
@@ -3478,7 +3478,7 @@ void chrBeginArgh(struct chrdata *chr, f32 angle, s32 hitpart)
chr->act_argh.lvframe60 = g_Vars.lvframe60;
chr->sleep = 0;
row = &rows[random() % 8];
row = &rows[rngRandom() % 8];
modelSetAnimationWithMerge(model, row->animnum, row->flip, 0, row->speed, 16, !instant);
@@ -3511,7 +3511,7 @@ void chrBeginArgh(struct chrdata *chr, f32 angle, s32 hitpart)
}
// Select a random animation for this hit location and apply it
rowindex = random() % g_AnimTablesByRace[race][index].injuryanimcount;
rowindex = rngRandom() % g_AnimTablesByRace[race][index].injuryanimcount;
row = &g_AnimTablesByRace[race][index].injuryanims[rowindex];
@@ -3654,7 +3654,7 @@ void chrYeetFromPos(struct chrdata *chr, struct coord *exppos, f32 force)
angleindex = 0;
}
subindex = random() % g_YeetAnimIndexesByRaceAngle[race][angleindex].count;
subindex = rngRandom() % g_YeetAnimIndexesByRaceAngle[race][angleindex].count;
if (race == RACE_HUMAN) {
row = &g_YeetAnimsHuman[g_YeetAnimIndexesByRaceAngle[race][angleindex].indexes[subindex]];
@@ -3678,8 +3678,8 @@ void chrYeetFromPos(struct chrdata *chr, struct coord *exppos, f32 force)
chr->act_die.drcarollimagedelay = TICKS(45);
if (chr->race == RACE_DRCAROLL) {
chr->drcarollimage_left = 1 + (s32)((random() % 400) * 0.01f);
chr->drcarollimage_right = 1 + (s32)((random() % 400) * 0.01f);
chr->drcarollimage_left = 1 + (s32)((rngRandom() % 400) * 0.01f);
chr->drcarollimage_right = 1 + (s32)((rngRandom() % 400) * 0.01f);
}
chr->sleep = 0;
@@ -3862,7 +3862,7 @@ void chrChoke(struct chrdata *chr, s32 choketype)
SFX_ARGH_MAIAN_05E1
};
soundnum = sounds[random() % 3];
soundnum = sounds[rngRandom() % 3];
nextindexmaian++;
if (nextindexmaian >= ARRAYCOUNT(sounds)) {
@@ -3878,7 +3878,7 @@ void chrChoke(struct chrdata *chr, s32 choketype)
SFX_SKEDAR_ROAR_053A,
};
soundnum = sounds[random() % 5];
soundnum = sounds[rngRandom() % 5];
nextindexskedar++;
if (nextindexskedar >= ARRAYCOUNT(sounds)) {
@@ -3891,7 +3891,7 @@ void chrChoke(struct chrdata *chr, s32 choketype)
SFX_SKEDAR_ROAR_052F,
};
soundnum = sounds[random() % 3];
soundnum = sounds[rngRandom() % 3];
nextindexskedar++;
if (nextindexskedar >= ARRAYCOUNT(sounds)) {
@@ -3978,7 +3978,7 @@ void chrChoke(struct chrdata *chr, s32 choketype)
SFX_ARGH_JO_02B3,
};
soundnum = sounds[random() % 10];
soundnum = sounds[rngRandom() % 10];
allowoverride = true;
} else {
s16 sounds[] = {
@@ -4005,21 +4005,21 @@ void chrChoke(struct chrdata *chr, s32 choketype)
SFX_GURGLE_05B2,
};
if ((random() % 8) == 0) {
soundnum = sounds[random() % 3];
if ((rngRandom() % 8) == 0) {
soundnum = sounds[rngRandom() % 3];
}
chr->soundgap = 10;
chr->soundtimer = 0;
} else if (choketype == CHOKETYPE_COUGH) {
if (male) {
if ((random() % 2) == 0) {
if ((rngRandom() % 2) == 0) {
soundnum = SFX_COUGH_04AF;
} else {
soundnum = SFX_COUGH_04B0;
}
} else {
s32 index = random() % 4;
s32 index = rngRandom() % 4;
s32 sounds[] = {
SFX_COUGH_05AB,
SFX_COUGH_05AC,
@@ -4340,8 +4340,9 @@ void chrDamage(struct chrdata *chr, f32 damage, struct coord *vector, struct gse
}
#ifndef PLATFORM_N64
// Don't damage if multiplayer and friendly fire is off
// Don't damage if team multiplayer and friendly fire is off
if (g_Vars.mplayerisrunning
&& (g_MpSetup.options & MPOPTION_TEAMSENABLED)
&& !(g_MpSetup.options & MPOPTION_FRIENDLYFIRE)
&& aprop
&& aprop != vprop
@@ -4519,13 +4520,13 @@ void chrDamage(struct chrdata *chr, f32 damage, struct coord *vector, struct gse
f32 sqdist = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff;
if (sqdist < 200 * 200) {
damage *= 4.0f + (s32)(random() % 3); // 4, 5 or 6
damage *= 4.0f + (s32)(rngRandom() % 3); // 4, 5 or 6
} else if (sqdist < 400 * 400) {
damage *= 3.0f + (s32)(random() % 2); // 3 or 4
damage *= 3.0f + (s32)(rngRandom() % 2); // 3 or 4
} else if (sqdist < 800 * 800) {
damage *= 2.0f + (s32)(random() % 2); // 2 or 3
damage *= 2.0f + (s32)(rngRandom() % 2); // 2 or 3
} else if (sqdist < 1600 * 1600) {
damage *= 1.0f + (s32)(random() % 2); // 1 or 2
damage *= 1.0f + (s32)(rngRandom() % 2); // 1 or 2
}
}
@@ -4598,7 +4599,7 @@ void chrDamage(struct chrdata *chr, f32 damage, struct coord *vector, struct gse
u16 sounds[] = { SFX_HIT_METAL_807B, SFX_HIT_METAL_8079, SFX_HATHIT_807C };
damage = 0;
psCreate(NULL, chr->prop, sounds[random() % 3], -1,
psCreate(NULL, chr->prop, sounds[rngRandom() % 3], -1,
-1, 0, 0, PSTYPE_NONE, NULL, -1, NULL, -1, -1, -1, -1);
}
}
@@ -5851,7 +5852,7 @@ void chrGoPosChooseAnimation(struct chrdata *chr)
if (race == RACE_HUMAN || race == RACE_SKEDAR) {
if ((leftgun && rightgun) || (!leftgun && !rightgun)) {
heavy = false;
flip = random() % 2;
flip = rngRandom() % 2;
} else {
if (weaponIsOneHanded(leftgun) || weaponIsOneHanded(rightgun)) {
heavy = false;
@@ -5938,7 +5939,7 @@ void chrGoPosChooseAnimation(struct chrdata *chr)
|| chr->hitpart == HITPART_RBICEP) {
anim = ANIM_01F8;
} else {
if (random() % 2) {
if (rngRandom() % 2) {
anim = ANIM_0018;
} else {
anim = ANIM_0028;
@@ -5973,7 +5974,7 @@ void chrGoPosChooseAnimation(struct chrdata *chr)
speed = 0.4;
flip = false;
} else if (male) {
if (random() % 4 == 0) {
if (rngRandom() % 4 == 0) {
speed = 0.25;
anim = ANIM_001E;
} else {
@@ -5982,7 +5983,7 @@ void chrGoPosChooseAnimation(struct chrdata *chr)
sp60 = 24;
}
} else {
if (random() % 2) {
if (rngRandom() % 2) {
anim = ANIM_005E;
} else {
anim = ANIM_005A;
@@ -6023,14 +6024,14 @@ void chrGoPosChooseAnimation(struct chrdata *chr)
} else if (stageGetIndex(g_Vars.stagenum) == STAGEINDEX_CHICAGO) {
anim = ANIM_005F;
} else if (male) {
if (random() % 2) {
if (rngRandom() % 2) {
anim = ANIM_001D;
} else {
anim = ANIM_RUNNING_ONEHANDGUN;
}
} else {
if (chr->myaction != MA_PANIC) {
if (random() % 2) {
if (rngRandom() % 2) {
anim = ANIM_005D;
} else {
anim = ANIM_0073;
@@ -6064,9 +6065,9 @@ void chrGoPosChooseAnimation(struct chrdata *chr)
anim = ANIM_01F8;
flip = true;
} else if (male) {
anim = anims[random() % 3];
anim = anims[rngRandom() % 3];
} else {
if (random() % 2) {
if (rngRandom() % 2) {
anim = ANIM_005C;
} else {
anim = ANIM_0072;
@@ -6154,7 +6155,7 @@ bool chrGoToRoomPos(struct chrdata *chr, struct coord *pos, RoomNum *room, u32 g
chr->act_gopos.flags = goposflags | GOPOSFLAG_INIT;
chr->act_gopos.turnspeed = 0;
chr->unk32c_21 = 0;
chr->act_gopos.waydata.age = random() % 100;
chr->act_gopos.waydata.age = rngRandom() % 100;
chr->act_gopos.waydata.gotaimposobj = 0;
if (!isgopos) {
@@ -6228,7 +6229,7 @@ void chrPatrolChooseAnimation(struct chrdata *chr)
if ((leftprop && rightprop) || (!leftprop && !rightprop)) {
// No weapon, or double weapons
heavy = false;
flip = random() % 2;
flip = rngRandom() % 2;
} else {
// Single weapon
if (weaponIsOneHanded(leftprop) || weaponIsOneHanded(rightprop)) {
@@ -6246,12 +6247,12 @@ void chrPatrolChooseAnimation(struct chrdata *chr)
speed = 0.5f * func0f02dff0(ANIM_0028) / func0f02dff0(ANIM_006B);
if (heavy) {
modelSetAnimation(chr->model, random() % 2 ? ANIM_0018 : ANIM_0028, flip, 0, speed, 16);
modelSetAnimation(chr->model, rngRandom() % 2 ? ANIM_0018 : ANIM_0028, flip, 0, speed, 16);
} else if (ismale) {
s32 anims[] = { ANIM_006B, ANIM_001B, ANIM_0016 };
modelSetAnimation(chr->model, anims[random() % 3], flip, 0, speed, 16);
modelSetAnimation(chr->model, anims[rngRandom() % 3], flip, 0, speed, 16);
} else {
modelSetAnimation(chr->model, random() % 2 ? ANIM_005C : ANIM_0072, flip, 0, speed, 16);
modelSetAnimation(chr->model, rngRandom() % 2 ? ANIM_005C : ANIM_0072, flip, 0, speed, 16);
}
}
} else if (race == RACE_DRCAROLL) {
@@ -6337,7 +6338,7 @@ void chrStartPatrol(struct chrdata *chr, struct path *path)
chr->act_patrol.nextstep = nextstep;
chr->act_patrol.forward = true;
chr->act_patrol.waydata.age = random() % 100;
chr->act_patrol.waydata.age = rngRandom() % 100;
chr->act_patrol.waydata.gotaimposobj = 0;
chr->act_patrol.waydata.lastvisible60 = -1;
@@ -6703,7 +6704,7 @@ bool chrCheckCanSeeTarget(struct chrdata *chr)
}
iVar8 = chrGetPercentageOfSlowness(chr, iVar8) + 1;
result = random() % iVar8 == 0;
result = rngRandom() % iVar8 == 0;
}
}
@@ -6795,7 +6796,7 @@ bool chrTrySidestep(struct chrdata *chr)
if (angle < 0.7852731347084f || angle > 5.4969120025635f
|| (angle > 2.3558194637299f && angle < 3.9263656139374f)) {
bool side = (random() % 2) == 0;
bool side = (rngRandom() % 2) == 0;
if (chrCanJumpInDirection(chr, side, 100)) {
chrSidestep(chr, side);
@@ -6833,7 +6834,7 @@ bool chrTryJumpOut(struct chrdata *chr)
// || (angle > BADDEG2RAD(135) && angle < BADDEG2RAD(225))) {
if (angle < 0.7852731347084f || angle > 5.4969120025635f
|| (angle > 2.3558194637299f && angle < BADDEG2RAD(225))) {
bool side = (random() % 2) == 0;
bool side = (rngRandom() % 2) == 0;
if (chrCanJumpInDirection(chr, side, 200)) {
chrJumpOut(chr, side);
@@ -6862,7 +6863,7 @@ bool chrTryRunSideways(struct chrdata *chr)
struct coord vector;
struct coord dstpos;
chrGetSideVectorToTarget(chr, random() % 2 == 0, &vector);
chrGetSideVectorToTarget(chr, rngRandom() % 2 == 0, &vector);
dstpos.x = vector.x * distance + prop->pos.x;
dstpos.y = prop->pos.y;
@@ -6961,7 +6962,7 @@ bool chrTryAttackRoll(struct chrdata *chr)
f32 sqdistance = x * x + y * y + z * z;
if (sqdistance >= 200 * 200) {
bool toleft = (random() % 2) == 0;
bool toleft = (rngRandom() % 2) == 0;
if (chrCanRollInDirection(chr, toleft, 200)) {
chrAttackRoll(chr, toleft);
@@ -6998,7 +6999,7 @@ bool chrTryAttackAmount(struct chrdata *chr, u32 arg1, u32 arg2, u8 lower, u8 up
}
if (lower < upper) {
percentage = ((random() % (upper - lower)) + (u32)lower) * 0.01f;
percentage = ((rngRandom() % (upper - lower)) + (u32)lower) * 0.01f;
} else {
percentage = 0;
}
@@ -7494,7 +7495,7 @@ bool chrGoToCoverProp(struct chrdata *chr)
for (numprops = 0; propnums[numprops] >= 0; numprops++);
if (numprops > 0) {
startindex = random() % numprops;
startindex = rngRandom() % numprops;
}
for (i = 0; i < numprops; i++) {
@@ -7595,7 +7596,7 @@ bool chrConsiderGrenadeThrow(struct chrdata *chr, u32 attackflags, u32 entityid)
bool done = false;
if (CHRRACE(chr) == RACE_HUMAN &&
chr->grenadeprob > (random() % 255) &&
chr->grenadeprob > (rngRandom() % 255) &&
chrGetDistanceToTarget(chr) > 200 &&
chrIsReadyForOrders(chr)) {
struct prop *target = chrGetTargetProp(chr);
@@ -7789,7 +7790,7 @@ bool chrTryPunch(struct chrdata *chr, u8 reverse)
struct punchanim *anims = NULL;
s32 race = CHRRACE(chr);
s32 animindex;
u32 chranimflags = (random() % 256 > 128) ? CHRANIMFLAG_FLIP : 0;
u32 chranimflags = (rngRandom() % 256 > 128) ? CHRANIMFLAG_FLIP : 0;
s32 chrhitradius;
s32 playerhitradius;
f32 startframe;
@@ -7800,7 +7801,7 @@ bool chrTryPunch(struct chrdata *chr, u8 reverse)
startframe = 10;
chrhitradius = 120;
playerhitradius = 120;
animindex = random() % 11;
animindex = rngRandom() % 11;
} else if (race == RACE_SKEDAR) {
anims = g_SkedarPunchAnims;
chrhitradius = 200;
@@ -7816,11 +7817,11 @@ bool chrTryPunch(struct chrdata *chr, u8 reverse)
animindex = 5;
} else if (!chr->weapons_held[HAND_RIGHT] && !chr->weapons_held[HAND_LEFT]) {
// Unarmed: Only use indexes 0 or 1
animindex = random() % 2;
animindex = rngRandom() % 2;
} else {
// Allow indexes 0-4, but if 3 or 4 then flip the anim based on
// which hand is holding the gun
animindex = random() % 5;
animindex = rngRandom() % 5;
if (animindex >= 3) {
if (!chr->weapons_held[HAND_RIGHT] || !chr->weapons_held[HAND_LEFT]) {
@@ -7997,7 +7998,7 @@ void chrTickStand(struct chrdata *chr)
|| (!leftgun && !rightgun)
|| weaponIsOneHanded(leftgun)
|| weaponIsOneHanded(rightgun)) {
modelSetAnimation(chr->model, ANIM_006B, random() % 2, 0, 0.5f, 16);
modelSetAnimation(chr->model, ANIM_006B, rngRandom() % 2, 0, 0.5f, 16);
modelSetAnimEndFrame(chr->model, animGetNumFrames(ANIM_006B) - 1);
} else {
if (rightgun || leftgun) {
@@ -8006,7 +8007,7 @@ void chrTickStand(struct chrdata *chr)
}
}
} else if (race == RACE_SKEDAR) {
modelSetAnimation(chr->model, ANIM_0392, random() % 2, 0, 0.5f, 16);
modelSetAnimation(chr->model, ANIM_0392, rngRandom() % 2, 0, 0.5f, 16);
modelSetAnimEndFrame(chr->model, animGetNumFrames(ANIM_0392) - 1);
}
} else if (chr->act_stand.flags & ATTACKFLAG_AIMATDIRECTION) {
@@ -8025,7 +8026,7 @@ void chrTickStand(struct chrdata *chr)
if (chr->prop->flags & PROPFLAG_ONANYSCREENPREVTICK) {
chr->sleep = 0;
} else {
chr->sleep = 14 + (random() % 5);
chr->sleep = 14 + (rngRandom() % 5);
}
if (chr->act_stand.checkfacingwall == false) {
@@ -8079,17 +8080,17 @@ void chrTickStand(struct chrdata *chr)
if (sp74[sp44[4]] < 200) {
index = 7;
} else if (sp44[0] == 0 || sp44[1] == 0 || sp44[2] == 0) {
if ((sp44[3] == 4 || sp44[4] == 4) && (random() % 3) == 0) {
if ((sp44[3] == 4 || sp44[4] == 4) && (rngRandom() % 3) == 0) {
if (sp44[3] == 4) {
index = 3;
} else {
index = 4;
}
} else {
index = 5 + random() % 3;
index = 5 + rngRandom() % 3;
}
} else if ((sp44[0] == 1 || sp44[0] == 7) && sp44[5] && sp44[6] && sp44[7]) {
index = 5 + random() % 3;
index = 5 + rngRandom() % 3;
}
}
@@ -8154,7 +8155,7 @@ void chrTickAnim(struct chrdata *chr)
}
if (chr->sleep <= 0 && chr->act_anim.slowupdate) {
chr->sleep = 14 + (random() % 5);
chr->sleep = 14 + (rngRandom() % 5);
}
if (modelGetAnimNum(chr->model) == ANIM_RELOAD_0209) {
@@ -8186,7 +8187,7 @@ void chrTickSurrender(struct chrdata *chr)
coord.z = -cosf(value);
if (!propchrHasClearLineInVector(chr->prop, &coord, 20)) {
modelSetAnimation(chr->model, ANIM_SURRENDER_002E, random() & 1, 30, 0.5, 16);
modelSetAnimation(chr->model, ANIM_SURRENDER_002E, rngRandom() & 1, 30, 0.5, 16);
modelSetAnimLooping(chr->model, 30, 16);
}
}
@@ -8395,7 +8396,7 @@ void chrTickDie(struct chrdata *chr)
SFX_DRCAROLL_YOU_WERE_SUPPOSED,
};
psCreate(NULL, chr->prop, phrases[random() % 5], -1,
psCreate(NULL, chr->prop, phrases[rngRandom() % 5], -1,
-1, 0, 0, PSTYPE_NONE, 0, -1, 0, -1, -1, -1, -1);
chr->voicebox = 0;
}
@@ -8404,9 +8405,9 @@ void chrTickDie(struct chrdata *chr)
if (chr->act_die.drcarollimagedelay > 0) {
chr->act_die.drcarollimagedelay -= g_Vars.lvupdate60;
} else {
chr->act_die.drcarollimagedelay = (random() % TICKS(1000)) * 0.01f + 5.0f;
chr->drcarollimage_left = 1 + (s32)((random() % 400) * 0.01f);
chr->drcarollimage_right = 1 + (s32)((random() % 400) * 0.01f);
chr->act_die.drcarollimagedelay = (rngRandom() % TICKS(1000)) * 0.01f + 5.0f;
chr->drcarollimage_left = 1 + (s32)((rngRandom() % 400) * 0.01f);
chr->drcarollimage_right = 1 + (s32)((rngRandom() % 400) * 0.01f);
}
if (g_DrCarollDyingTimer > TICKS(310)) {
@@ -8513,7 +8514,7 @@ void chrTickDruggedComingUp(struct chrdata *chr)
if (i >= 0
&& g_AnimTablesByRace[race][i].deathanims != NULL
&& g_AnimTablesByRace[race][i].deathanimcount > 0) {
s32 index = random() % g_AnimTablesByRace[race][i].deathanimcount;
s32 index = rngRandom() % g_AnimTablesByRace[race][i].deathanimcount;
row = &g_AnimTablesByRace[race][i].deathanims[index];
chr->act_die.thudframe1 = row->thudframe1;
@@ -9107,7 +9108,7 @@ bool func0f03e9f4(struct chrdata *chr, struct attackanimconfig *animcfg, bool fi
sp174 += eyeheight * (0.025f - 0.05f * RANDOMFRAC() * arg4);
}
} else if (sqdist > 1000.0f * 1000.0f) {
if ((random() % 3) == 0) {
if ((rngRandom() % 3) == 0) {
sp174 += eyeheight * (0.05f + 0.1f * RANDOMFRAC() * arg4);
} else {
sp174 -= eyeheight * (0.05f + 0.55f * RANDOMFRAC() * arg4);
@@ -10040,7 +10041,7 @@ void chrTickShoot(struct chrdata *chr, s32 handnum)
// This function can never return 2 though...
if (botactShootFarsight(chr + zero, 0, &vector, &gunpos) == 2) {
normalshoot = random() % 255 > 200;
normalshoot = rngRandom() % 255 > 200;
}
}
@@ -10077,7 +10078,7 @@ void chrTickShoot(struct chrdata *chr, s32 handnum)
// Eyespy is small and hard to hit, so make it a 50/50 chance
if (hitprop == NULL && isshootingeyespy) {
fudgeforeyespy = random() % 100 > 50;
fudgeforeyespy = rngRandom() % 100 > 50;
if (fudgeforeyespy) {
hitprop = targetprop;
@@ -10335,10 +10336,10 @@ void chrTickShoot(struct chrdata *chr, s32 handnum)
hitpos.y = targetprop->pos.y;
hitpos.z = targetprop->pos.z;
if (random() % 2) {
hitpos.y += 2 + random() % 10;
if (rngRandom() % 2) {
hitpos.y += 2 + rngRandom() % 10;
} else {
hitpos.y -= 2 + random() % 10;
hitpos.y -= 2 + rngRandom() % 10;
}
bgunPlayPropHitSound(&gset, targetprop, -1);
@@ -10844,13 +10845,13 @@ void robotSetMuzzleFlash(struct chrdata *chr, bool right, bool visible)
void robotAttack(struct chrdata *chr)
{
u32 numshots = random() % 20;
u32 numshots = rngRandom() % 20;
if (chr->unk348[0] && chr->unk348[1]) {
chr->actiontype = ACT_ROBOTATTACK;
chr->unk348[0]->beam->age = -1;
chr->unk348[0]->unk00 = random() % 3;
chr->unk348[0]->unk00 = rngRandom() % 3;
chr->unk348[0]->unk01 = 0;
chr->unk348[0]->unk08 = -1;
chr->unk348[0]->unk0c = 0.85f;
@@ -10873,7 +10874,7 @@ void robotAttack(struct chrdata *chr)
chr->act_robotattack.firing[0] = false;
chr->unk348[1]->beam->age = -1;
chr->unk348[1]->unk00 = random() % 3;
chr->unk348[1]->unk00 = rngRandom() % 3;
chr->unk348[1]->unk01 = 0;
chr->unk348[1]->unk08 = -1;
chr->unk348[1]->unk0c = 0.85f;
@@ -11166,7 +11167,7 @@ void chrTickAttackRoll(struct chrdata *chr)
f32 sp34 = 16;
if (chr->act_attack.firegun[HAND_LEFT] && chr->act_attack.firegun[HAND_RIGHT]) {
if (random() % 2 == 0) {
if (rngRandom() % 2 == 0) {
newanimcfg += 4;
} else {
newanimcfg += 8;
@@ -13211,7 +13212,7 @@ void chrTickSkJump(struct chrdata *chr)
SFX_SKEDAR_ROAR_0534,
};
psCreate(NULL, chr->prop, sounds[random() % 3], -1,
psCreate(NULL, chr->prop, sounds[rngRandom() % 3], -1,
-1, 0, 0, PSTYPE_NONE, 0, -1, 0, -1, -1, -1, -1);
modelSetAnimation(chr->model, ANIM_SKEDAR_JUMPAIR, 0, 0, -1, 16);
modelSetAnimSpeed(chr->model, 1, 0);
@@ -13599,7 +13600,7 @@ void chraTickBg(void)
spawnslen++;
if (spawnslen >= 10) {
writeindex = random() % spawnslen;
writeindex = rngRandom() % spawnslen;
chrFadeCorpse(spawns[writeindex]);
spawns[writeindex] = spawns[spawnslen - 1];
spawnslen--;
@@ -13690,7 +13691,7 @@ void chraTickBg(void)
onscreenlen++;
if (onscreenlen >= (VERSION >= VERSION_NTSC_1_0 ? 2 : 3)) {
writeindex = random() % onscreenlen;
writeindex = rngRandom() % onscreenlen;
chrFadeCorpseWhenOffScreen(onscreen[writeindex]);
onscreen[writeindex] = onscreen[onscreenlen - 1];
onscreenlen--;
@@ -13705,7 +13706,7 @@ void chraTickBg(void)
// Allow up to 5 corpses off-screen
if (offscreenlen >= (VERSION >= VERSION_NTSC_1_0 ? 5 : 6)) {
writeindex = random() % offscreenlen;
writeindex = rngRandom() % offscreenlen;
if (offscreen[writeindex]->actiontype != ACT_DEAD) {
chrBeginDead(offscreen[writeindex]);
@@ -15199,7 +15200,7 @@ struct prop *chrSpawnAtCoord(s32 bodynum, s32 headnum, struct coord *pos, RoomNu
#endif
replacechr = NULL;
startindex = random() % g_NumChrSlots;
startindex = rngRandom() % g_NumChrSlots;
index = startindex;
#if VERSION < VERSION_NTSC_1_0
@@ -15480,7 +15481,7 @@ s32 chrAssignCoverByCriteria(struct chrdata *chr, u16 criteria, s32 refdist)
} else if (criteria & COVERCRITERIA_DISTTOFETCHPROP) {
sqdist = coordGetSquaredDistanceToCoord(&gotoprop->pos, cover.pos);
} else if (userandomdist) {
sqdist = random() % 0xf000;
sqdist = rngRandom() % 0xf000;
} else {
sqdist = 0;
currefdist = 0;
@@ -16190,7 +16191,7 @@ void chrAvoid(struct chrdata *chr)
} else if (relangle > 135 && relangle < 225) {
animindex = 2;
if ((random() % 255) >= 2) {
if ((rngRandom() % 255) >= 2) {
cdresult = CDRESULT_COLLISION;
chr->chrflags &= ~CHRCFLAG_AVOIDING;
}
@@ -16198,7 +16199,7 @@ void chrAvoid(struct chrdata *chr)
animindex = 3;
chrangle += M_PI;
} else {
animindex = (random() % 100 < 50) ? 0 : 1;
animindex = (rngRandom() % 100 < 50) ? 0 : 1;
if (animindex == 0) {
chrangle -= 1.5707963705063f;
+17 -1
View File
@@ -729,7 +729,7 @@ void chraiExecute(void *entity, s32 proptype)
if (g_Vars.chrdata->aishootingatmelist >= 0
&& ailistFindById(g_Vars.chrdata->aishootingatmelist) != g_Vars.chrdata->ailist
&& g_Vars.chrdata->dodgerating > random() % 100
&& g_Vars.chrdata->dodgerating > rngRandom() % 100
&& chrHasFlag(g_Vars.chrdata, CHRFLAG1_INDARKROOM, BANK_1) == 0
&& chrHasFlag(g_Vars.chrdata, CHRFLAG0_AIVSAI, BANK_0) == 0
&& ailistFindById(g_Vars.chrdata->aishootingatmelist) != g_Vars.chrdata->ailist
@@ -814,3 +814,19 @@ u32 chraiGetCommandLength(u8 *ailist, u32 aioffset)
return 1;
}
// used by ext_setup
u32 chraiGetAilistLength(u8* list)
{
if (!list) return 0;
u8* cmd = list;
while (true) {
u8 type = cmd[1];
cmd += chraiGetCommandLength(cmd, 0);
if (type == AICMD_END) break;
}
return (u32)(cmd - list);
}
+35 -31
View File
@@ -1096,7 +1096,7 @@ bool aiTryRunToChr(void)
*/
bool aiRandom(void)
{
g_Vars.chrdata->random = random() & 0xff;
g_Vars.chrdata->random = rngRandom() & 0xff;
g_Vars.aioffset += 2;
return false;
@@ -1110,7 +1110,7 @@ bool aiIfRandomLessThan(void)
u8 *cmd = g_Vars.ailist + g_Vars.aioffset;
if ((g_Vars.chrdata && g_Vars.chrdata->random < cmd[2]) ||
(g_Vars.hovercar && ((u8)random()) < cmd[2])) {
(g_Vars.hovercar && ((u8)rngRandom()) < cmd[2])) {
g_Vars.aioffset = chraiGoToLabel(g_Vars.ailist, g_Vars.aioffset, cmd[3]);
} else {
g_Vars.aioffset += 4;
@@ -1127,7 +1127,7 @@ bool aiIfRandomGreaterThan(void)
u8 *cmd = g_Vars.ailist + g_Vars.aioffset;
if ((g_Vars.chrdata && g_Vars.chrdata->random > cmd[2]) ||
(g_Vars.hovercar && ((u8)random()) > cmd[2])) {
(g_Vars.hovercar && ((u8)rngRandom()) > cmd[2])) {
g_Vars.aioffset = chraiGoToLabel(g_Vars.ailist, g_Vars.aioffset, cmd[3]);
} else {
g_Vars.aioffset += 4;
@@ -2114,14 +2114,18 @@ bool aiIfGunUnclaimed(void)
g_Vars.aioffset += 5;
}
} else {
struct weaponobj *weapon = g_Vars.chrdata->gunprop->weapon;
struct prop *prop = g_Vars.chrdata->gunprop;
if (weapon && weapon->base.prop) {
weapon->base.flags |= OBJFLAG_FORCENOBOUNCE;
g_Vars.aioffset = chraiGoToLabel(g_Vars.ailist, g_Vars.aioffset, cmd[4]);
} else {
g_Vars.aioffset += 5;
if (prop && prop->weapon && prop->parent == NULL && prop->type == PROPTYPE_WEAPON) {
struct weaponobj *weapon = prop->weapon;
if (weapon->base.prop) {
weapon->base.flags |= OBJFLAG_FORCENOBOUNCE;
g_Vars.aioffset = chraiGoToLabel(g_Vars.ailist, g_Vars.aioffset, cmd[4]);
return false;
}
}
g_Vars.aioffset += 5;
}
return false;
@@ -2326,7 +2330,7 @@ bool aiGiveObjectToChr(void)
}
#endif
something = propPickupByPlayer(obj->prop, 0);
something = propPickupByPlayer(obj->prop, 1);
propExecuteTickOperation(obj->prop, something);
playernum = playermgrGetPlayerNumByProp(chr->prop);
obj2->hidden = (playernum << 28) | (obj2->hidden & 0x0fffffff);
@@ -5944,7 +5948,7 @@ bool aiSetTarget(void)
*/
bool aiIfPresetsTargetIsNotMyTarget(void)
{
s32 mypresetchrstarget;
s32 mypresetchrstarget = -1;
u8 *cmd = g_Vars.ailist + g_Vars.aioffset;
if (g_Vars.chrdata->chrpreset1 != -1) {
@@ -6897,7 +6901,7 @@ bool aiSayQuip(void)
bank = (s16 *) g_MaianQuipBank;
if (row > 2) {
row = random() % 2;
row = rngRandom() % 2;
}
} else if (cmd[7] == 0) {
if (g_Vars.chrdata->voicebox > 3) {
@@ -6947,7 +6951,7 @@ bool aiSayQuip(void)
// If soundgap permits talking at this time and probability passes
if (g_Vars.chrdata->soundgap == 0 || g_Vars.chrdata->soundgap * TICKS(60) < g_Vars.chrdata->soundtimer) {
if (probability > (s32) (random() % 256)) {
if (probability > (s32) (rngRandom() % 256)) {
// Try and find a chr in the same squadron who is currently talking
while (*chrnums != -2) {
loopchr = chrFindByLiteralId(*chrnums);
@@ -6972,7 +6976,7 @@ bool aiSayQuip(void)
if (!issomeonetalking
&& ((numnearbychrs == 0 && (!cmd[6] || cmd[6] == 255)) || (numnearbychrs > 0 && cmd[6] > 0))) {
rowptr = (s16 *) bank + row * 4;
column = random() % 3;
column = rngRandom() % 3;
if ((cmd[7] & 0x80) == 0) {
audioid = rowptr[1 + column];
@@ -7599,8 +7603,8 @@ bool aiShuffleInvestigationTerminals(void)
* else conditions are unreachable so only 3 of the 4 terminals can be
* selected as the destination.
*/
rand1 = random() % 3;
rand2 = random() % 3;
rand1 = rngRandom() % 3;
rand2 = rngRandom() % 3;
if (cmd[8] == 0) {
// Place the good terminal
@@ -8740,17 +8744,17 @@ bool aiSayCiStaffQuip(void)
s16 quip;
if (cmd[2] == CIQUIP_GREETING) {
quip = g_CiGreetingQuips[g_Vars.chrdata->morale][random() % 3];
quip = g_CiGreetingQuips[g_Vars.chrdata->morale][rngRandom() % 3];
psPlayFromProp((s8)cmd[3], quip, 0, g_Vars.chrdata->prop, PSTYPE_CHRTALK, 0);
}
if (cmd[2] == CIQUIP_MAIN) {
quip = g_CiMainQuips[g_Vars.chrdata->morale][random() % 3];
quip = g_CiMainQuips[g_Vars.chrdata->morale][rngRandom() % 3];
psPlayFromProp((s8)cmd[3], quip, 0, g_Vars.chrdata->prop, PSTYPE_CHRTALK, 0);
}
if (cmd[2] == CIQUIP_ANNOYED) {
quip = g_CiAnnoyedQuips[g_Vars.chrdata->morale][random() % 3];
quip = g_CiAnnoyedQuips[g_Vars.chrdata->morale][rngRandom() % 3];
psPlayFromProp((s8)cmd[3], quip, 0, g_Vars.chrdata->prop, PSTYPE_CHRTALK, 0);
}
@@ -8791,7 +8795,7 @@ bool aiDoPresetAnimation(void)
};
if (cmd[2] == 255) {
chrTryStartAnim(g_Vars.chrdata, anims[7 + (random() % 8)], 0, -1, 0, 15, 0.5);
chrTryStartAnim(g_Vars.chrdata, anims[7 + (rngRandom() % 8)], 0, -1, 0, 15, 0.5);
} else if (cmd[2] == 254) {
struct prop *prop0 = chrGetHeldProp(g_Vars.chrdata, 1);
struct prop *prop1 = chrGetHeldProp(g_Vars.chrdata, 0);
@@ -8802,7 +8806,7 @@ bool aiDoPresetAnimation(void)
chrTryStartAnim(g_Vars.chrdata, ANIM_FIX_GUN_JAM_HARD, 0, -1, 0, 5, 0.5);
}
} else if (cmd[2] == 3) {
chrTryStartAnim(g_Vars.chrdata, anims[3 + (random() & 1)], 0, -1, 0, 15, 0.5);
chrTryStartAnim(g_Vars.chrdata, anims[3 + (rngRandom() & 1)], 0, -1, 0, 15, 0.5);
} else {
chrTryStartAnim(g_Vars.chrdata, anims[cmd[2]], 0, -1, 0, 15, 0.5);
}
@@ -8951,9 +8955,9 @@ bool aiShuffleRuinsPillars(void)
struct tag *ptr2 = tagFindById(cmd[3]);
struct tag *ptr3 = tagFindById(cmd[4]);
struct tag *src;
u8 marked1index = random() % 5;
u8 marked2index = random() % 5;
u8 marked3index = random() % 5;
u8 marked1index = rngRandom() % 5;
u8 marked2index = rngRandom() % 5;
u8 marked3index = rngRandom() % 5;
u8 pillars[5];
u8 mines[5];
pillars[0] = cmd[5];
@@ -8968,11 +8972,11 @@ bool aiShuffleRuinsPillars(void)
mines[4] = cmd[17];
while (marked2index == marked1index) {
marked2index = random() % 5;
marked2index = rngRandom() % 5;
}
while (marked3index == marked2index || marked3index == marked1index) {
marked3index = random() % 5;
marked3index = rngRandom() % 5;
}
// Pillar/mine 1
@@ -9132,7 +9136,7 @@ bool aiShufflePelagicSwitches(void)
for (i = 8; i < 16; i++) {
tag = tagFindById(i);
index = random() & 7;
index = rngRandom() & 7;
if (buttonsdone[index] == 0) {
// Switch has not yet been mapped
@@ -9582,20 +9586,20 @@ bool aiSetDrCarollImages(void)
if (drcaroll) {
if (cmd[4] == 7) {
if ((g_Vars.lvframenum % 4) == 2) {
drcaroll->drcarollimage_left = random() % 6;
drcaroll->drcarollimage_left = rngRandom() % 6;
}
} else if (cmd[4] == 8) {
drcaroll->drcarollimage_left = random() % 6;
drcaroll->drcarollimage_left = rngRandom() % 6;
} else {
drcaroll->drcarollimage_left = cmd[4];
}
if (cmd[3] == 7) {
if ((g_Vars.lvframenum % 4) == 2) {
drcaroll->drcarollimage_right = random() % 6;
drcaroll->drcarollimage_right = rngRandom() % 6;
}
} else if (cmd[3] == 8) {
drcaroll->drcarollimage_right = random() % 6;
drcaroll->drcarollimage_right = rngRandom() % 6;
} else {
drcaroll->drcarollimage_right = cmd[3];
}
+39 -25
View File
@@ -24,6 +24,9 @@
#include "lib/vi.h"
#include "data.h"
#include "types.h"
#ifndef PLATFORM_N64
#include "input.h"
#endif
/**
* Credits
@@ -554,12 +557,12 @@ void creditsCreatePendingBgLayers(u32 mask)
s32 shift = i * 8;
if (g_CreditsData->unk41b0[i] == 0) {
g_CreditsData->bglayers[i + 2].type = random() % 12;
g_CreditsData->bglayers[i + 2].type = rngRandom() % 12;
g_CreditsData->bglayers[i + 2].rotspeed = creditsRandInRange(0.00223f);
g_CreditsData->bglayers[i + 2].panspeed = creditsRandInRange(0.00223f);
if (((u8)(mask >> shift) & 2)) {
g_CreditsData->bglayers[i + 2].confignum = random() % 6;
g_CreditsData->bglayers[i + 2].confignum = rngRandom() % 6;
}
}
}
@@ -642,20 +645,20 @@ void creditsResetParticles(void)
tmp = RANDOMFRAC();
g_CreditsData->particles[i].y = (tmp + tmp) * 3000.0f - 3000.0f;
g_CreditsData->particles[i].unk12 = random() % 4;
g_CreditsData->particles[i].colourindex = random() % 4;
g_CreditsData->particles[i].unk12 = rngRandom() % 4;
g_CreditsData->particles[i].colourindex = rngRandom() % 4;
g_CreditsData->particles[i].rotation = RANDOMFRAC() * M_BADTAU;
if (g_CreditsData->particleminsize < g_CreditsData->particlemaxsize) {
g_CreditsData->particles[i].size = g_CreditsData->particleminsize
+ (random() % (g_CreditsData->particlemaxsize - g_CreditsData->particleminsize));
+ (rngRandom() % (g_CreditsData->particlemaxsize - g_CreditsData->particleminsize));
} else {
g_CreditsData->particles[i].size = g_CreditsData->particleminsize;
}
g_CreditsData->particles[i].movetype = g_CreditsData->particlemovetype;
if (random() % 2 == 1) {
if (rngRandom() % 2 == 1) {
g_CreditsData->particles[i].confignum = g_CreditsData->particleconfignum1;
} else {
g_CreditsData->particles[i].confignum = g_CreditsData->particleconfignum2;
@@ -685,12 +688,12 @@ void creditsTickParticles(void)
} else {
#if VERSION >= VERSION_NTSC_1_0
if (RANDOMFRAC() < 0.007f && joyGetButtons(0, R_TRIG) == 0) {
g_CreditsData->particlecolourindex1 = random() % 4;
g_CreditsData->particlecolourindex1 = rngRandom() % 4;
g_CreditsData->particlecolourweight = 0;
}
#else
if (RANDOMFRAC() < 0.007f) {
g_CreditsData->particlecolourindex1 = random() % 4;
g_CreditsData->particlecolourindex1 = rngRandom() % 4;
g_CreditsData->particlecolourweight = 0;
}
#endif
@@ -698,28 +701,28 @@ void creditsTickParticles(void)
#if VERSION >= VERSION_NTSC_1_0
if (RANDOMFRAC() < 0.002f && joyGetButtons(0, R_TRIG) == 0) {
g_CreditsData->particlemovetype = random() % 5;
g_CreditsData->particlemovetype = rngRandom() % 5;
}
#else
if (RANDOMFRAC() < 0.002f) {
g_CreditsData->particlemovetype = random() % 5;
g_CreditsData->particlemovetype = rngRandom() % 5;
}
#endif
#if VERSION >= VERSION_NTSC_1_0
if (joyGetButtonsPressedThisFrame(0, R_TRIG)) {
g_CreditsData->particlemovetype = random() % 5;
g_CreditsData->particlemovetype = rngRandom() % 5;
if (g_CreditsData->particlecolourindex1 < 0) {
g_CreditsData->particlecolourindex1 = random() % 4;
g_CreditsData->particlecolourindex1 = rngRandom() % 4;
g_CreditsData->particlecolourweight = 0;
}
}
#endif
if (RANDOMFRAC() < 0.007f) {
g_CreditsData->particleconfignum1 = random() % 2;
g_CreditsData->particleconfignum2 = random() % 2;
g_CreditsData->particleconfignum1 = rngRandom() % 2;
g_CreditsData->particleconfignum2 = rngRandom() % 2;
}
for (i = 0; i < ARRAYCOUNT(g_CreditsData->particles); i++) {
@@ -744,20 +747,20 @@ void creditsTickParticles(void)
if (g_CreditsData->particles[i].z > 0.0f) {
g_CreditsData->particles[i].x = RANDOMFRAC() * 2.0f * 3000.0f - 3000.0f;
g_CreditsData->particles[i].y = RANDOMFRAC() * 2.0f * 3000.0f - 3000.0f;
g_CreditsData->particles[i].unk12 = random() % 4;
g_CreditsData->particles[i].colourindex = random() % 4;
g_CreditsData->particles[i].unk12 = rngRandom() % 4;
g_CreditsData->particles[i].colourindex = rngRandom() % 4;
g_CreditsData->particles[i].rotation = RANDOMFRAC() * M_BADTAU;
if (g_CreditsData->particleminsize < g_CreditsData->particlemaxsize) {
g_CreditsData->particles[i].size = g_CreditsData->particleminsize
+ random() % (g_CreditsData->particlemaxsize - g_CreditsData->particleminsize);
+ rngRandom() % (g_CreditsData->particlemaxsize - g_CreditsData->particleminsize);
} else {
g_CreditsData->particles[i].size = g_CreditsData->particleminsize;
}
g_CreditsData->particles[i].movetype = g_CreditsData->particlemovetype;
if (random() % 2 == 1) {
if (rngRandom() % 2 == 1) {
g_CreditsData->particles[i].confignum = g_CreditsData->particleconfignum1;
} else {
g_CreditsData->particles[i].confignum = g_CreditsData->particleconfignum2;
@@ -998,7 +1001,7 @@ Gfx *creditsDrawBackgroundText(Gfx *gdl, s32 x, s32 y, char *text, struct fontch
f32 f24 = i * 0.2f + g_CreditsParticleRotationFrac * 10.0f * M_BADTAU + sp98;
f32 f26 = i * 0.1f * (spread + 0.5f) + 1.0f;
if ((random() % 256) == 1) {
if ((rngRandom() % 256) == 1) {
f26 *= 10.0f;
}
@@ -1075,7 +1078,7 @@ void creditsResetSlides(void)
}
for (i = 0; i < NUM_CORE_TEAM; i++) {
s32 index = random() % (NUM_CORE_TEAM - i);
s32 index = rngRandom() % (NUM_CORE_TEAM - i);
g_CreditsData->coreteammap[i + 1] = pool[index];
@@ -1348,7 +1351,7 @@ void creditsTickSlide(void)
} while (credit && credit->more && g_CreditsData->numthisslide < 4);
for (i = 0; i < ARRAYCOUNT(g_CreditsData->unk41a8); i++) {
g_CreditsData->unk41a8[i] = random() % 3 | random() % 3 << 2 | random() % 16 << 4;
g_CreditsData->unk41a8[i] = rngRandom() % 3 | rngRandom() % 3 << 2 | rngRandom() % 16 << 4;
}
creditsCreatePendingBgLayers(0xffffffff);
@@ -1656,10 +1659,10 @@ Gfx *creditsDrawSlide(Gfx *gdl)
}
// Apply random flicker
if (settled && random() % (g_CreditsData->numthisslide * 16) == 1) {
if (settled && rngRandom() % (g_CreditsData->numthisslide * 16) == 1) {
transfrac = RANDOMFRAC() * 0.05f;
hdir = random() % 3;
vdir = random() % 3;
hdir = rngRandom() % 3;
vdir = rngRandom() % 3;
}
extray = 120 - cury / 2;
@@ -1876,11 +1879,22 @@ Gfx *creditsDraw(Gfx *gdl)
}
}
// Exit the alternative title if a button is pressed (other than L or R)
#ifdef PLATFORM_N64
#if VERSION >= VERSION_NTSC_1_0
// Exit the alternative title if a button is pressed (other than L or R)
if (g_CreditsUsingAltTitle && joyGetButtonsPressedThisFrame(0, 0xffcf))
#else
if (g_CreditsUsingAltTitle && joyGetButtons(0, 0xffff))
#endif
#else
#if VERSION >= VERSION_NTSC_1_0
// Exit to CI if a button is pressed (other than L or R), for the port
if (joyGetButtonsPressedThisFrame(0, 0xffcf) ||
inputKeyJustPressed(VK_ESCAPE))
#else
if (joyGetButtons(0, 0xffff) ||
inputKeyJustPressed(VK_ESCAPE))
#endif
#endif
{
g_TitleNextStage = STAGE_CITRAINING;
+23 -10
View File
@@ -28,6 +28,7 @@
#include "lib/lib_317f0.h"
#include "data.h"
#include "types.h"
#include "platform.h"
const char var7f1a78e0[] = "LIGHTS : Hit occured on light %d in room %d\n";
const char var7f1a7910[] = "L2(%d) -> ";
@@ -424,7 +425,7 @@ void roomInitLights(s32 roomnum)
#if VERSION < VERSION_NTSC_1_0
if (cheatIsActive(CHEAT_PERFECTDARKNESS)) {
light->brightness = 0;
light->sparkable = (random() % 2) ? true : false;
light->sparkable = (rngRandom() % 2) ? true : false;
light->healthy = false;
light->on = false;
light->sparking = false;
@@ -525,7 +526,7 @@ void roomSetLightsFaulty(s32 roomnum, s32 chance)
if (g_Rooms[roomnum].numlights) {
for (i = 0; i < g_Rooms[roomnum].numlights; i++) {
if ((random() % 100) < chance) {
if ((rngRandom() % 100) < chance) {
light->healthy = false;
light->on = false;
}
@@ -592,7 +593,11 @@ void func0f001c0c(void)
table2size = align16(g_NumPortals * 4);
table3size = align16(g_Vars.roomcount * 4);
table4size = align16((u32)var8009cae0 * (u32)var8009cae0);
#ifdef PLATFORM_64BIT
sp68 = align16(g_Vars.roomcount * 8 * 2);
#else
sp68 = align16(g_Vars.roomcount * 8);
#endif
mempGetStageFree();
@@ -975,9 +980,9 @@ bool lightTickBroken(s32 roomnum, s32 lightnum)
}
if (light->sparking) {
if ((random() % 8) == 0) {
if ((rngRandom() % 8) == 0) {
light->sparking = false;
} else if ((random() % 2) == 0) {
} else if ((rngRandom() % 2) == 0) {
struct coord spc8;
struct coord spbc;
struct coord spb0;
@@ -1031,7 +1036,7 @@ bool lightTickBroken(s32 roomnum, s32 lightnum)
room = (void *) (roomnum * sizeof(struct bgroom));
switch (random() % 4) {
switch (rngRandom() % 4) {
case 0:
if (roomnum && roomnum && roomnum);
sparktype = SPARKTYPE_LIGHT1;
@@ -1049,14 +1054,14 @@ bool lightTickBroken(s32 roomnum, s32 lightnum)
lightGetBboxCentre(roomnum, lightnum, &centre);
room = (void *) ((u8 *) g_BgRooms + (u32) room);
room = (void *) ((u8 *) g_BgRooms + (uintptr_t) room);
centre.x += room->pos.x;
centre.y += room->pos.y;
centre.z += room->pos.z;
sparksCreate(roomnum, NULL, &centre, &spa4, &sp8c, sparktype);
if ((random() % 4) == 0) {
if ((rngRandom() % 4) == 0) {
smokerooms[0] = roomnum;
smokerooms[1] = -1;
@@ -1068,7 +1073,7 @@ bool lightTickBroken(s32 roomnum, s32 lightnum)
return true;
}
} else {
if ((random() % 80) == 0) {
if ((rngRandom() % 80) == 0) {
light->sparking = true;
}
}
@@ -1120,7 +1125,7 @@ void lightsConfigureForPerfectDarknessCutscene(void)
g_Rooms[i].lightop_to_frac = 0.5f;
for (j = 0; j < g_Rooms[i].numlights; j++) {
light->sparkable = random() % 2 ? true : false;
light->sparkable = rngRandom() % 2 ? true : false;
light->healthy = true;
light->on = true;
light->sparking = false;
@@ -1145,7 +1150,7 @@ void lightsConfigureForPerfectDarknessGameplay(void)
g_Rooms[i].lightop_to_frac = 0;
for (j = 0; j < g_Rooms[i].numlights; j++) {
light->sparkable = random() % 2 ? true : false;
light->sparkable = rngRandom() % 2 ? true : false;
light->healthy = false;
light->on = false;
light->sparking = false;
@@ -1695,11 +1700,19 @@ void func0f004c6c(void)
u8 *ptr;
u8 *backupptr;
#ifdef PLATFORM_64BIT
sp44 = align16(0x2000 * 2);
sp40 = align16(g_NumPortals * 4 * 2);
sp3c = align16(g_NumPortals * 0xc * 2);
sp38 = align16(g_NumPortals * 4 * 2);
sp34 = align16(g_NumPortals * 2 * 2);
#else
sp44 = align16(0x2000);
sp40 = align16(g_NumPortals * 4);
sp3c = align16(g_NumPortals * 0xc);
sp38 = align16(g_NumPortals * 4);
sp34 = align16(g_NumPortals * 2);
#endif
for (i = 0, s4 = sp38; i < g_NumPortals; i++) {
if (i != 0) {
+6 -6
View File
@@ -79,7 +79,7 @@ void dyntexUpdateLinear(Vtx *vertices, struct dyntextype *type)
s32 i;
for (i = 0; i < type->numvertices; i++) {
Vtx *vertex = (Vtx *)((s32)vertices + g_DyntexVertices[type->vertexlistoffset + i].offset);
Vtx *vertex = (Vtx *)((uintptr_t)vertices + g_DyntexVertices[type->vertexlistoffset + i].offset);
vertex->t = g_DyntexVertices[type->vertexlistoffset + i].t + tmp;
vertex->s = g_DyntexVertices[type->vertexlistoffset + i].s;
@@ -91,7 +91,7 @@ void dyntexUpdateReset(Vtx *vertices, struct dyntextype *type)
s32 i;
for (i = 0; i < type->numvertices; i++) {
Vtx *vertex = (Vtx *)((s32)vertices + g_DyntexVertices[type->vertexlistoffset + i].offset);
Vtx *vertex = (Vtx *)((uintptr_t)vertices + g_DyntexVertices[type->vertexlistoffset + i].offset);
vertex->s = 0;
vertex->t = 0;
@@ -104,7 +104,7 @@ void dyntexUpdateMonitor(Vtx *vertices, struct dyntextype *type)
s32 i;
for (i = 0; i < type->numvertices; i++) {
Vtx *vertex = (Vtx *)((s32)vertices + g_DyntexVertices[type->vertexlistoffset + i].offset);
Vtx *vertex = (Vtx *)((uintptr_t)vertices + g_DyntexVertices[type->vertexlistoffset + i].offset);
vertex->t = g_DyntexVertices[type->vertexlistoffset + i].t - tmp;
vertex->s = g_DyntexVertices[type->vertexlistoffset + i].s;
@@ -124,7 +124,7 @@ void dyntexUpdateOcean(Vtx *vertices, struct dyntextype *type)
mainOverrideVariable("ripsize", &ripsize);
for (i = 0; i < type->numvertices; i++) {
Vtx *vertex = (Vtx *)((s32)vertices + g_DyntexVertices[type->vertexlistoffset + i].offset);
Vtx *vertex = (Vtx *)((uintptr_t)vertices + g_DyntexVertices[type->vertexlistoffset + i].offset);
angle = ((g_DyntexVertices[type->vertexlistoffset + i].t % modula) / (f32) modula + f24) * M_BADTAU;
vertex->t = g_DyntexVertices[type->vertexlistoffset + i].t + (s16) (sinf(angle) * ripsize);
@@ -140,7 +140,7 @@ void dyntexUpdateArrows(Vtx *vertices, struct dyntextype *type)
s32 i;
for (i = 0; i < type->numvertices; i++) {
Vtx *vertex = (Vtx *)((s32)vertices + g_DyntexVertices[type->vertexlistoffset + i].offset);
Vtx *vertex = (Vtx *)((uintptr_t)vertices + g_DyntexVertices[type->vertexlistoffset + i].offset);
vertex->s = g_DyntexVertices[type->vertexlistoffset + i].s + tmp;
vertex->t = g_DyntexVertices[type->vertexlistoffset + i].t;
@@ -182,7 +182,7 @@ void dyntexTickRoom(s32 roomnum, Vtx *vertices)
// @bug: Using i for both outer and inner loops
for (i = 0; i < type->numvertices; i++) {
Vtx *vertex = (Vtx *)((s32)vertices + g_DyntexVertices[type->vertexlistoffset + i].offset);
Vtx *vertex = (Vtx *)((uintptr_t)vertices + g_DyntexVertices[type->vertexlistoffset + i].offset);
g_DyntexVertices[type->vertexlistoffset + i].s = vertex->s;
g_DyntexVertices[type->vertexlistoffset + i].t = vertex->t;
+4 -4
View File
@@ -35,7 +35,7 @@
#endif
struct explosion *g_Explosions;
s32 g_MaxExplosions;
s32 g_MaxExplosions = MAX_EXPLOSIONS_DEFAULT;
s32 g_ExplosionShakeTotalTimer = 0;
s32 g_ExplosionShakeIntensityTimer = 0;
@@ -259,7 +259,7 @@ bool explosionCreate(struct prop *sourceprop, struct coord *exppos, RoomNum *exp
f32 sum = xdist * xdist + ydist * ydist + zdist * zdist;
if (sum * lodscale * lodscale > 400 * 400) {
if (random() % 2 == 0) {
if (rngRandom() % 2 == 0) {
if (sourceprop) {
smokeCreateSimple(&sourceprop->pos, sourceprop->rooms, g_ExplosionTypes[type].smoketype);
} else {
@@ -711,7 +711,7 @@ void explosionInflictDamage(struct prop *expprop)
// Flicker room lighting
for (i = 0; expprop->rooms[i] != -1; i++) {
if (random() % 2048 <= 240) {
if (rngRandom() % 2048 <= 240) {
roomFlashLighting(expprop->rooms[i], type->rangeh, 255);
}
}
@@ -1191,7 +1191,7 @@ u32 explosionTick(struct prop *prop)
// Create smoke
if (((exp->age == TICKS(15) && exp->type == EXPLOSIONTYPE_GASBARREL)
|| (exp->age == maxage - TICKS(20) && exp->type != EXPLOSIONTYPE_GASBARREL))
&& (exp->type != EXPLOSIONTYPE_BULLETHOLE || (random() % 2) == 0)) {
&& (exp->type != EXPLOSIONTYPE_BULLETHOLE || (rngRandom() % 2) == 0)) {
if (exp->source) {
smokeCreateSimple(&exp->source->pos, exp->source->rooms, type->smoketype);
} else {
-6
View File
@@ -14,12 +14,6 @@ void explosionsReset(void)
g_ExplosionShakeIntensityTimer = 0;
g_ExplosionDamageTxScale = 1;
g_MaxExplosions = MAX_EXPLOSIONS;
if (g_Vars.stagenum >= STAGE_TITLE) {
g_MaxExplosions = 0;
}
if (g_MaxExplosions == 0) {
g_Explosions = NULL;
} else {
+1 -1
View File
@@ -14,7 +14,7 @@ void explosionsStop(void)
viShake(0);
if (g_Explosions) {
for (i = 0; i < MAX_EXPLOSIONS; i++) {
for (i = 0; i < g_MaxExplosions; i++) {
if (g_Explosions[i].prop) {
propDelist(g_Explosions[i].prop);
propDisable(g_Explosions[i].prop);
+16 -16
View File
@@ -11,7 +11,7 @@
#include "data.h"
#include "types.h"
#ifndef PLATFORM_N64
#include "romdata.h"
#include "system.h"
#endif
/**
@@ -4114,7 +4114,7 @@ u32 g_FileTable[] = {
(uintptr_t) &_filenamesSegmentRomStart,
};
#else // PLATFORM_N64
u32 g_FileTable[NUM_FILES + 1]; // TODO: this is only used to get the filenum, remove this
uintptr_t g_FileTable[NUM_FILES + 1]; // TODO: this is only used to get the filenum, remove this
#endif // PLATFORM_N64
romptr_t fileGetRomAddress(s32 filenum)
@@ -4126,7 +4126,7 @@ romptr_t fileGetRomAddress(s32 filenum)
#endif
}
u32 fileGetRomSizeByTableAddress(u32 *filetableaddr)
u32 fileGetRomSizeByTableAddress(uintptr_t *filetableaddr)
{
#ifdef PLATFORM_N64
u32 size;
@@ -4146,10 +4146,10 @@ u32 fileGetRomSizeByTableAddress(u32 *filetableaddr)
s32 fileGetRomSize(s32 filenum)
{
return fileGetRomSizeByTableAddress((u32 *)&g_FileTable[filenum]);
return fileGetRomSizeByTableAddress((uintptr_t*)&g_FileTable[filenum]);
}
u32 file0f166ea8(u32 *filetableaddr)
u32 file0f166ea8(uintptr_t *filetableaddr)
{
return 0;
}
@@ -4158,7 +4158,7 @@ void fileLoad(u8 *dst, u32 allocationlen, romptr_t *romaddrptr, struct fileinfo
{
#ifndef PLATFORM_N64
// load the file first
const s32 filenum = (u32 *)romaddrptr - g_FileTable;
const s32 filenum = (uintptr_t *)romaddrptr - g_FileTable;
u32 romsize = 0;
u8 *filedata = romdataFileLoad(filenum, &romsize);
if (!filedata) {
@@ -4176,7 +4176,7 @@ void fileLoad(u8 *dst, u32 allocationlen, romptr_t *romaddrptr, struct fileinfo
dmaExec(dst, *romaddrptr, romsize);
} else {
// DMA the compressed data to scratch space then inflate
u8 *scratch = (dst + allocationlen) - ((romsize + 7) & 0xfffffff8);
u8 *scratch = (dst + allocationlen) - ((romsize + 7) & (uintptr_t)~7);
if ((uintptr_t)scratch - (uintptr_t)dst < 8) {
info->loadedsize = 0;
@@ -4209,7 +4209,7 @@ void fileLoad(u8 *dst, u32 allocationlen, romptr_t *romaddrptr, struct fileinfo
#ifndef PLATFORM_N64
// byteswap/preprocess file according to g_LoadType right after inflating it
const u32 dstsize = allocationlen ? info->loadedsize : romsize;
romdataFilePreprocess(filenum, g_LoadType, dst, dstsize);
romdataFilePreprocess(filenum, g_LoadType, dst, dstsize, &info->loadedsize);
g_LoadType = LOADTYPE_NONE;
#endif
}
@@ -4241,7 +4241,7 @@ void fileLoadPartToAddr(u16 filenum, void *memaddr, s32 offset, u32 len)
{
u32 stack[2];
if (fileGetRomSizeByTableAddress((u32 *)&g_FileTable[filenum])) {
if (fileGetRomSizeByTableAddress((uintptr_t*)&g_FileTable[filenum])) {
#ifdef PLATFORM_N64
dmaExec(memaddr, (romptr_t) g_FileTable[filenum] + offset, len);
#else
@@ -4255,11 +4255,11 @@ void fileLoadPartToAddr(u16 filenum, void *memaddr, s32 offset, u32 len)
}
}
u32 fileGetInflatedSize(s32 filenum)
u32 fileGetInflatedSize(s32 filenum, u32 loadtype)
{
u8 *ptr;
u8 buffer[0x50];
u32 *romaddrptr;
uintptr_t *romaddrptr;
#if VERSION < VERSION_NTSC_1_0
char message[128];
#endif
@@ -4283,7 +4283,7 @@ u32 fileGetInflatedSize(s32 filenum)
}
if (rzipIs1173(ptr)) {
return (ptr[2] << 16) | (ptr[3] << 8) | ptr[4];
return romdataFileGetEstimatedSize((ptr[2] << 16) | (ptr[3] << 8) | ptr[4], loadtype);
}
#if VERSION < VERSION_NTSC_1_0
@@ -4300,7 +4300,7 @@ u32 fileGetInflatedSize(s32 filenum)
return 0;
}
void *fileLoadToNew(s32 filenum, u32 method)
void *fileLoadToNew(s32 filenum, u32 method, u32 loadtype)
{
struct fileinfo *info = &g_FileInfo[filenum];
u32 stack;
@@ -4308,7 +4308,7 @@ void *fileLoadToNew(s32 filenum, u32 method)
if (method == FILELOADMETHOD_EXTRAMEM || method == FILELOADMETHOD_DEFAULT) {
if (info->loadedsize == 0) {
info->loadedsize = (fileGetInflatedSize(filenum) + 0x20) & 0xfffffff0;
info->loadedsize = (fileGetInflatedSize(filenum, loadtype) + 0x20) & 0xfffffff0;
if (method == FILELOADMETHOD_EXTRAMEM) {
info->loadedsize += 0x8000;
@@ -4317,7 +4317,7 @@ void *fileLoadToNew(s32 filenum, u32 method)
ptr = mempAlloc(info->loadedsize, MEMPOOL_STAGE);
info->allocsize = info->loadedsize;
fileLoad(ptr, info->loadedsize, (u32 *)&g_FileTable[filenum], info);
fileLoad(ptr, info->loadedsize, (uintptr_t*)&g_FileTable[filenum], info);
if (method != FILELOADMETHOD_EXTRAMEM) {
mempRealloc(ptr, info->loadedsize, MEMPOOL_STAGE);
@@ -4343,7 +4343,7 @@ void *fileLoadToAddr(s32 filenum, s32 method, u8 *ptr, u32 size)
if (method == FILELOADMETHOD_EXTRAMEM || method == FILELOADMETHOD_DEFAULT) {
info->allocsize = size;
fileLoad(ptr, size, (u32 *)&g_FileTable[filenum], info);
fileLoad(ptr, size, (uintptr_t*)&g_FileTable[filenum], info);
} else {
while (1);
}
+10 -37
View File
@@ -19,6 +19,7 @@
#include "lib/str.h"
#include "data.h"
#include "types.h"
#include "mpsetups.h"
// bss
struct fileguid g_FilemgrFileToCopy;
@@ -411,7 +412,7 @@ struct menudialogdef g_FilemgrErrorMenuDialog = {
* For a file listing, iterate the devices until the one at optionindex is found.
* Depending on operation, return the device name or index of the first file.
*/
s32 filemgrGetDeviceNameOrStartIndex(s32 listnum, s32 operation, s32 optionindex)
uintptr_t filemgrGetDeviceNameOrStartIndex(s32 listnum, s32 operation, s32 optionindex)
{
u16 names[] = {
L_OPTIONS_111, // "Game Pak"
@@ -428,7 +429,7 @@ s32 filemgrGetDeviceNameOrStartIndex(s32 listnum, s32 operation, s32 optionindex
if (g_FileLists[listnum]->devicestartindexes[i] != -1) {
if (remaining == 0) {
if (operation == MENUOP_GETOPTGROUPTEXT) {
return (s32)langGet(names[i]);
return (uintptr_t)langGet(names[i]);
}
return g_FileLists[listnum]->devicestartindexes[i];
@@ -499,11 +500,6 @@ char *filemgrMenuTextFileType(struct menuitem *item)
case FILEOP_LOAD_GAME:
case FILEOP_READ_GAME:
return langGet(names[0]);
case FILEOP_SAVE_MPSETUP:
case FILEOP_WRITE_MPSETUP:
case FILEOP_LOAD_MPSETUP:
case FILEOP_READ_MPSETUP:
return langGet(names[1]);
case FILEOP_SAVE_MPPLAYER:
case FILEOP_WRITE_MPPLAYER:
case FILEOP_LOAD_MPPLAYER:
@@ -816,12 +812,6 @@ bool filemgrAttemptOperation(s32 device, bool closeonsuccess)
g_Menus[g_MpPlayerNum].fm.fileid,
g_Menus[g_MpPlayerNum].fm.deviceserial);
break;
case FILEOP_SAVE_MPSETUP:
errnum = mpsetupfileSave(device,
g_Menus[g_MpPlayerNum].fm.fileid,
g_Menus[g_MpPlayerNum].fm.deviceserial);
showfilesaved = true;
break;
case FILEOP_WRITE_GAME:
case FILEOP_WRITE_MPSETUP:
case FILEOP_WRITE_MPPLAYER:
@@ -845,11 +835,6 @@ bool filemgrAttemptOperation(s32 device, bool closeonsuccess)
g_Menus[g_MpPlayerNum].fm.fileid,
g_Menus[g_MpPlayerNum].fm.deviceserial);
break;
case FILEOP_LOAD_MPSETUP:
errnum = mpsetupfileLoad(device,
g_Menus[g_MpPlayerNum].fm.fileid,
g_Menus[g_MpPlayerNum].fm.deviceserial);
break;
case FILEOP_READ_GAME:
case FILEOP_READ_MPSETUP:
case FILEOP_READ_MPPLAYER:
@@ -913,7 +898,7 @@ const char var7f1b31ec[] = "Multiplayer %d was using that file...\n";
*
* Return true if it worked, otherwise false.
*/
bool filemgrSaveOrLoad(struct fileguid *guid, s32 fileop, u32 playernum)
bool filemgrSaveOrLoad(struct fileguid *guid, s32 fileop, uintptr_t playernum)
{
s32 device;
@@ -1252,7 +1237,7 @@ void func0f1097d0(s32 device)
thing = memaAlloc(align16(g_FileTypeSizes[g_Menus[g_MpPlayerNum].fm.filetypeplusone - 1]));
if (thing) {
filemgrSaveOrLoad(&g_FilemgrFileToCopy, g_Menus[g_MpPlayerNum].fm.filetypeplusone + 103, (s32) thing);
filemgrSaveOrLoad(&g_FilemgrFileToCopy, g_Menus[g_MpPlayerNum].fm.filetypeplusone + 103, (uintptr_t) thing);
} else {
filemgrPushErrorDialog(FILEERROR_OUTOFMEMORY);
}
@@ -2748,6 +2733,10 @@ MenuItemHandlerResult filemgrChooseAgentListMenuHandler(s32 operation, struct me
g_GameFileGuid.fileid = file->fileid;
g_GameFileGuid.deviceserial = file->deviceserial;
filemgrSaveOrLoad(&g_GameFileGuid, FILEOP_LOAD_GAME, 0);
// load the setup file when loading the agent
mpsetupCopyAllFromPak();
mpsetupLoadCurrentFile();
}
}
break;
@@ -2780,7 +2769,7 @@ MenuDialogHandlerResult filemgrMainMenuDialog(s32 operation, struct menudialogde
g_Menus[g_MpPlayerNum].fm.filetypeplusone = 0;
filelistCreate(0, FILETYPE_GAME);
mpInit();
mpInit(true);
// Set MP player names to "Player 1" through 4 if blank
for (i = 0; i < MAX_PLAYERS; i++) {
@@ -3307,14 +3296,6 @@ struct menuitem g_FilemgrOperationsMenuItems[] = {
0,
filemgrOpenCopyFileMenuHandler,
},
{
MENUITEMTYPE_SELECTABLE,
FILETYPE_MPSETUP,
0,
L_OPTIONS_104, // "Combat Simulator Settings File"
0,
filemgrOpenCopyFileMenuHandler,
},
{
MENUITEMTYPE_SELECTABLE,
FILETYPE_MPPLAYER,
@@ -3347,14 +3328,6 @@ struct menuitem g_FilemgrOperationsMenuItems[] = {
0,
filemgrOpenDeleteFileMenuHandler,
},
{
MENUITEMTYPE_SELECTABLE,
FILETYPE_MPSETUP,
0,
L_OPTIONS_104, // "Combat Simulator Settings File"
0,
filemgrOpenDeleteFileMenuHandler,
},
{
MENUITEMTYPE_SELECTABLE,
FILETYPE_MPPLAYER,
Loaded 100 of 222 files, more files were not shown because too many files have changed in this diff. Show more