Author SHA1 Message Date
Catherine Reprobate be0293f555 update Readme links 2026-05-25 23:55:29 -07:00
fgsfds 54d35b47a0 Merge pull request #716 from jonaeru/port-net-disablemenu
[port-net] Disable all menus in Perfect Menu except Network Game and Change Agent
2026-05-02 12:20:13 +02:00
Jonaeru 04a518840f Add "Player Setup" menu to "Join Game" menu
Add `MENUDIALOGFLAG_STARTSELECTS` to the "Network Game" menu
Remove `MENUDIALOGFLAG_IGNOREBACK` from the "Join Network Game" menu
2026-04-26 20:59:32 +09:00
Jonaeru 68df5343ba Disable all menus in Perfect Menu except Network Game and Change Agent 2026-04-25 00:53:00 +09:00
fgsfds aead1bc4c4 port-net: kick ci 2026-04-11 22:13:44 +02:00
fgsfds b86cc88991 port-net: update netplay.md
doing this mostly to kick CI
2025-12-31 21:10:42 +01:00
fgsfds d946e332ae port: net: don't transfer projectile/embedded flags in damage event 2025-09-28 10:26:50 +02:00
fgsfds 57041735cb port: net: fix build on newer mingw versions 2025-08-03 14:15:10 +02:00
fgsfds f3ce20fb6e port: net: fix laptop gun altfire on clients; better autogun sync 2025-04-27 19:52:28 +02:00
fgsfds 75d1886da1 port: net: load mpsetups from mpsetups.bin when entering host menu 2025-04-27 17:36:03 +02:00
fgsfds a582068c21 port: net: sync prop damage 2025-04-27 16:41:33 +02:00
fgsfds 4c1e9ece94 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2025-04-27 16:01:37 +02:00
fgsfds 4b8e1d52b5 port: move menuAlt functions to menu.c and make them global 2025-04-27 15:54:39 +02:00
fgsfds a9ccc61f96 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2025-04-27 15:45:45 +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 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 110876b036 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2025-03-16 09:18:31 +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 ae7b21cf56 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2025-03-02 13:38:12 +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 e8a57d7f6f Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2025-02-22 11:28:12 +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 2362444efd Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2025-02-11 20:06:26 +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 f5251fa1b9 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2025-01-05 15:46:00 +01:00
fgsfds 4f7817a0ca port: forgot the constant 2025-01-05 15:45:42 +01:00
fgsfds da4e5e4832 what the fuck git 2025-01-05 15:44:14 +01:00
fgsfds 5ebce756ed Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2025-01-05 15:43:52 +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 839ef7cc44 thank you git very cool 2025-01-05 12:44:51 +01:00
fgsfds c597915466 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2025-01-05 12:33:15 +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 5db911a58b Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-29 09:58:04 +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 5425c21c83 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-23 20:40:38 +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 abe04c0dda Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-19 18:33:29 +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 7721297dc8 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-17 11:09:06 +01: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 44c5a4c213 port-net: note that switch is not supported 2024-11-16 15:39:13 +01:00
fgsfds 7677b40b06 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-16 15:38:27 +01:00
fgsfds d747588323 ci: only build the port branch for nswitch 2024-11-16 15:37:43 +01:00
fgsfds f948fc06f2 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-16 15:30:34 +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 26c24d62aa Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-16 12:56:01 +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 9a484c1aea Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-15 19:14:04 +01:00
fgsfds 08afb2d90a readme: fix formatting 2024-11-15 19:13:53 +01:00
fgsfds 3f45d41de6 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-15 19:13:07 +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 6ddebf8aa6 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-15 01:36:54 +01: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 6d20ed25fb Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-14 18:46:15 +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 112f6da972 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-13 09:09:47 +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 80cd44d8e2 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-13 08:55:19 +01:00
fgsfds 5d9fe034ea tools: fix assetmgr on python <= 3.8 2024-11-13 08:55:04 +01:00
fgsfds 3ff2f9e0ec Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-13 08:51:43 +01:00
fgsfds 1d7c381ce2 port: cmake: fix stdc++ linking on windows; restore the icon 2024-11-13 08:50:35 +01:00
fgsfds 8b8eedcdfc port-net: fix artifact links 2024-11-12 23:20:22 +01:00
fgsfds 1398f5d0f5 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-12 23:18:53 +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 4d96fab71f Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-11-12 14:46:26 +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 796241d443 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-09-02 11:03:24 +02: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 3455708e38 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-09-02 10:07:04 +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 ae0ba57c24 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-08-06 16:54:36 +02: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 f7435e0ead Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-08-05 11:42:49 +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 fceacee0e2 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-08-04 11:09:30 +02: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. 55ab679a81 port: give Cloaking Device at respawn if cheat is active 2024-05-19 23:51:40 -07:00
fgsfds a5a2970b67 Merge branch 'port' into port-net 2024-05-19 19:45:37 +02: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 0d6a5f2d0f Merge branch 'port' into port-net 2024-05-18 19:33:21 +02:00
fgsfds dce96a4a3d port: add separate extra buttons for accept/cancel 2024-05-18 19:32:34 +02:00
fgsfds c5ab7d20df Merge branch 'port' into port-net 2024-05-18 19:18:36 +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 d53dd8c48f Merge branch 'port' into port-net 2024-05-18 19:02:30 +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 edced1d0e2 Merge branch 'port' into port-net 2024-05-15 14:11:30 +02:00
fgsfds e8e513fecb port: possible fix for #401 2024-05-15 14:11:24 +02:00
fgsfds 7cc389bc69 Merge branch 'port' into port-net 2024-05-15 13:39:19 +02:00
fgsfds 4601a9c318 port: only respect friendly fire setting in team games 2024-05-15 13:39:12 +02:00
fgsfds 5e03342562 Merge branch 'port' into port-net 2024-05-15 12:29:45 +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 30e987eb50 Merge branch 'port' into port-net 2024-05-15 12:13:43 +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 e5f142b110 Merge branch 'port' into port-net 2024-05-14 23:16:48 +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 95bf97a2c1 Merge branch 'port' into port-net 2024-05-14 22:56:54 +02:00
fgsfds 9530924c21 port: add mouse navigation toggle to options 2024-05-14 22:56:47 +02:00
fgsfds f52fa8f759 Merge branch 'port' into port-net 2024-05-14 22:53:08 +02:00
fgsfds 2ba192d411 port: make menu mouse flag global 2024-05-14 22:53:02 +02:00
fgsfds ff4321673b port: net: add note about regions 2024-05-14 22:24:10 +02:00
fgsfds 7590f0bdc3 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-05-14 22:23:00 +02:00
fgsfds bf8192ee84 Update README.md 2024-05-14 22:21:14 +02:00
fgsfds 70882d8a32 Merge branch 'port' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-05-14 22:17:09 +02:00
fgsfds 45ec35172d ci: fix executable names on linux 2024-05-14 22:04:27 +02:00
fgsfds 045d5d2e46 Merge branch 'port-net' of https://github.com/fgsfdsfgs/perfect_dark into port-net 2024-05-14 22:00:44 +02:00
fgsfds 926e4dce28 ci: autobuild pal and jpn and include them in release 2024-05-14 21:59:44 +02:00
fgsfds 7fabc68e95 Merge branch 'port' into port-net 2024-05-14 21:06:26 +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 948a3e0c51 Merge branch 'port' into port-net 2024-05-14 20:33:50 +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 7ffc1d393b Update README.md 2024-05-14 12:10:52 +02:00
fgsfds aba98349ae Merge branch 'port' into port-net 2024-05-14 12:07:19 +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
218 changed files with 13368 additions and 7080 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
+275 -13
View File
@@ -25,44 +25,306 @@ 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: bilelmoussaoui/flatpak-github-actions:freedesktop-23.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.fgsfdsfgs.perfect_dark.flatpak
manifest-path: dist/linux/io.github.fgsfdsfgs.perfect_dark.yaml
cache-key: flatpak-builder-${{ github.sha }}
upload-artifact: false
# - name: Build Flatpak bundle
# run: |
# cd dist/linux/
# flatpak-builder build --force-clean io.github.fgsfdsfgs.perfect_dark.yaml
# flatpak build-export export build
# flatpak build-bundle export io.github.fgsfdsfgs.perfect_dark.flatpak io.github.fgsfdsfgs.perfect_dark
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: io.github.fgsfdsfgs.perfect_dark.flatpak
path: io.github.fgsfdsfgs.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.fgsfdsfgs.perfect_dark.flatpak/io.github.fgsfdsfgs.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
+358
View File
@@ -0,0 +1,358 @@
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)
# 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
)
# 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 ws2_32 winmm 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 -lws2_32 -lwinmm -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
+116 -33
View File
@@ -6,7 +6,7 @@ This branch of the port contains an **extremely** early and experimental impleme
**DISCLAIMER:** This is **NOT READY** for prime time. Use at your own risk if you are not a developer.
**Do not create issues about problems in this branch until this disclaimer is gone.**
See [this file](https://github.com/fgsfdsfgs/perfect_dark/blob/port-net/docs/netplay.md) for more information on how this works.
See [this file](https://github.com/perfect-dark-pc-port/perfect_dark/blob/port-net/docs/netplay.md) for more information on how this works.
## Original description
@@ -41,32 +41,57 @@ 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) of the netplay branch for supported platforms:
* [i686-windows (`port-net`)](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port-net/pd-i686-windows.zip)
* [i686-linux (`port-net`)](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port-net/pd-i686-linux.zip)
Latest [automatic builds](https://github.com/perfect-dark-pc-port/perfect_dark/actions) of the netplay branch for supported platforms:
* [x86_64-windows (`port-net`)](https://nightly.link/perfect-dark-pc-port/perfect_dark/workflows/c-cpp/port-net/pd-x86_64-windows.zip)
* [i686-windows (`port-net`)](https://nightly.link/perfect-dark-pc-port/perfect_dark/workflows/c-cpp/port-net/pd-i686-windows.zip)
* [x86_64-linux (`port-net`)](https://nightly.link/perfect-dark-pc-port/perfect_dark/workflows/c-cpp/port-net/pd-x86_64-linux.zip)
* [i686-linux (`port-net`)](https://nightly.link/perfect-dark-pc-port/perfect_dark/workflows/c-cpp/port-net/pd-i686-linux.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).
If you are looking for regular builds (the `port` branch), see [this link](https://github.com/perfect-dark-pc-port/perfect_dark/blob/port/README.md#download).
## Running
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`).
Additional information can be found in the [wiki](https://github.com/fgsfdsfgs/perfect_dark/wiki).
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.
A GPU supporting OpenGL 3.0 or above is required to run the port.
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.
Note that users with different ROMs can't play netgames with each other.
Additional information can be found in the [wiki](https://github.com/perfect-dark-pc-port/perfect_dark/wiki).
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.
`port-net` currently does not work on the Switch.
## Controls
@@ -102,43 +127,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 -b port-net --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.
`git clone -b port-net --recursive https://github.com/perfect-dark-pc-port/perfect_dark.git && cd perfect_dark`
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 -b port-net --recursive https://github.com/fgsfdsfgs/perfect_dark.git && cd perfect_dark`
`git clone -b port-net --recursive https://github.com/perfect-dark-pc-port/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/perfect-dark-pc-port/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/perfect-dark-pc-port/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;
* 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.fgsfdsfgs.perfect_dark.sh
Icon=io.github.fgsfdsfgs.perfect_dark
Terminal=false
Type=Application
Categories=Game;ActionGame;
StartupNotify=false
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>io.github.fgsfdsfgs.perfect_dark</id>
<name>Perfect Dark</name>
<developer id="io.github.fgsfdsfgs.perfect_dark">
<name>Perfect Dark Contributors</name>
<url>https://github.com/fgsfdsfgs/perfect_dark/graphs/contributors</url>
</developer>
<launchable type="desktop-id">io.github.fgsfdsfgs.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">https://gitlab.com/fpiesche/dxx-rebirth-assets/-/raw/c6e7e79eebe92905f84f07a635ffab5122a94bd1/d1x/screenshots/retromode.png</image>
<caption>"Retro mode": the default graphics setup, like the original game but in high resolution</caption>
<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

+39
View File
@@ -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
+41
View File
@@ -0,0 +1,41 @@
app-id: io.github.fgsfdsfgs.perfect_dark
runtime: org.freedesktop.Platform
runtime-version: "23.08"
sdk: org.freedesktop.Sdk
command: io.github.fgsfdsfgs.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.fgsfdsfgs.perfect_dark.sh
- type: file
path: io.github.fgsfdsfgs.perfect_dark.png
- type: file
path: io.github.fgsfdsfgs.perfect_dark.metainfo.xml
- type: file
path: io.github.fgsfdsfgs.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 -1
View File
@@ -37,7 +37,6 @@ Expect nothing to work right.
### Known issues
* Clients can't throw laptop guns.
* Clients see rocket rotation incorrectly.
* Clients can't use Slayer fly-by-wire rockets and they will not correctly sync if the server uses them.
* Clients can't use the alt fire mode on the FarSight and probably a couple other guns.
@@ -45,3 +44,4 @@ Expect nothing to work right.
* Most likely only Combat works properly.
* Sims don't work in netgames.
* Bandwidth consumption on the server is pretty large on the default settings, especially with 8 players.
+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);
+1 -3
View File
@@ -44,7 +44,7 @@ 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_texture_cache_clear(void);
void gfx_texture_cache_delete(const uint8_t *orig_addr);
int gfx_create_framebuffer(uint32_t width, uint32_t height, int upscale, int autoresize);
@@ -52,7 +52,5 @@ void gfx_resize_framebuffer(int fb, uint32_t width, uint32_t height, int upscale
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
+296 -195
View File
@@ -32,6 +32,7 @@ struct ShaderProgram {
uint8_t num_attribs;
GLint frame_count_location;
GLint noise_scale_location;
GLint three_point_filter_locations[2];
};
struct Framebuffer {
@@ -54,9 +55,12 @@ static std::vector<Framebuffer> framebuffers;
static size_t current_framebuffer;
static float current_noise_scale;
static FilteringMode current_filter_mode = FILTER_LINEAR;
static bool current_textures_linear_filter[2] = {false, false};
static int gl_glsl_version = 130;
static char gl_glsl_version_str[16] = "130";
static GLenum gl_mirror_clamp = GL_MIRROR_CLAMP_TO_EDGE;
static bool gl_es = false;
static bool gl_core_profile = false;
static int gfx_opengl_get_max_texture_size() {
@@ -94,6 +98,12 @@ static void gfx_opengl_set_uniforms(struct ShaderProgram* prg) {
if (prg->noise_scale_location >= 0) {
glUniform1f(prg->noise_scale_location, current_noise_scale);
}
if (prg->three_point_filter_locations[0] >= 0) {
glUniform1i(prg->three_point_filter_locations[0], current_textures_linear_filter[0]);
}
if (prg->three_point_filter_locations[1] >= 0) {
glUniform1i(prg->three_point_filter_locations[1], current_textures_linear_filter[1]);
}
}
static void gfx_opengl_unload_shader(struct ShaderProgram* old_prg) {
@@ -234,144 +244,138 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
size_t num_floats = 4;
// Vertex shader
#ifdef __APPLE__
append_line(vs_buf, &vs_len, "#version 410 core");
append_line(vs_buf, &vs_len, "in vec4 aVtxPos;");
#else
append_line(vs_buf, &vs_len, "#version 110");
append_line(vs_buf, &vs_len, "attribute vec4 aVtxPos;");
#endif
vs_len += sprintf(vs_buf + vs_len, "#version %s\n", gl_glsl_version_str);
if (gl_es) {
append_line(vs_buf, &vs_len, "precision mediump float;");
}
if (gl_glsl_version >= 130) {
append_line(vs_buf, &vs_len, "#define INPUT in");
append_line(vs_buf, &vs_len, "#define OUTPUT out");
} else {
append_line(vs_buf, &vs_len, "#define INPUT attribute");
append_line(vs_buf, &vs_len, "#define OUTPUT varying");
}
append_line(vs_buf, &vs_len, "INPUT vec4 aVtxPos;");
for (int i = 0; i < 2; i++) {
if (cc_features.used_textures[i]) {
#ifdef __APPLE__
vs_len += sprintf(vs_buf + vs_len, "in vec2 aTexCoord%d;\n", i);
vs_len += sprintf(vs_buf + vs_len, "out vec2 vTexCoord%d;\n", i);
#else
vs_len += sprintf(vs_buf + vs_len, "attribute vec2 aTexCoord%d;\n", i);
vs_len += sprintf(vs_buf + vs_len, "varying vec2 vTexCoord%d;\n", i);
#endif
vs_len += sprintf(vs_buf + vs_len, "INPUT vec2 aTexCoord%d;\n", i);
vs_len += sprintf(vs_buf + vs_len, "OUTPUT vec2 vTexCoord%d;\n", i);
num_floats += 2;
for (int j = 0; j < 2; j++) {
if (cc_features.clamp[i][j]) {
#ifdef __APPLE__
vs_len += sprintf(vs_buf + vs_len, "in float aTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
vs_len += sprintf(vs_buf + vs_len, "out float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
#else
vs_len += sprintf(vs_buf + vs_len, "attribute float aTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
vs_len += sprintf(vs_buf + vs_len, "varying float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
#endif
vs_len += sprintf(vs_buf + vs_len, "INPUT float aTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
vs_len += sprintf(vs_buf + vs_len, "OUTPUT float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
num_floats += 1;
}
}
}
}
if (cc_features.opt_fog) {
#ifdef __APPLE__
append_line(vs_buf, &vs_len, "in vec4 aFog;");
append_line(vs_buf, &vs_len, "out vec4 vFog;");
#else
append_line(vs_buf, &vs_len, "attribute vec4 aFog;");
append_line(vs_buf, &vs_len, "varying vec4 vFog;");
#endif
append_line(vs_buf, &vs_len, "INPUT vec4 aFog;");
append_line(vs_buf, &vs_len, "OUTPUT vec4 vFog;");
num_floats += 4;
}
if (cc_features.opt_grayscale) {
#ifdef __APPLE__
append_line(vs_buf, &vs_len, "in vec4 aGrayscaleColor;");
append_line(vs_buf, &vs_len, "out vec4 vGrayscaleColor;");
#else
append_line(vs_buf, &vs_len, "attribute vec4 aGrayscaleColor;");
append_line(vs_buf, &vs_len, "varying vec4 vGrayscaleColor;");
#endif
append_line(vs_buf, &vs_len, "INPUT vec4 aGrayscaleColor;");
append_line(vs_buf, &vs_len, "OUTPUT vec4 vGrayscaleColor;");
num_floats += 4;
}
for (int i = 0; i < cc_features.num_inputs; i++) {
#ifdef __APPLE__
vs_len += sprintf(vs_buf + vs_len, "in vec%d aInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
vs_len += sprintf(vs_buf + vs_len, "out vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
#else
vs_len += sprintf(vs_buf + vs_len, "attribute vec%d aInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
vs_len += sprintf(vs_buf + vs_len, "varying vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
#endif
vs_len += sprintf(vs_buf + vs_len, "INPUT vec%d aInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
vs_len += sprintf(vs_buf + vs_len, "OUTPUT vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
num_floats += cc_features.opt_alpha ? 4 : 3;
}
append_line(vs_buf, &vs_len, "void main() {");
for (int i = 0; i < 2; i++) {
if (cc_features.used_textures[i]) {
vs_len += sprintf(vs_buf + vs_len, "vTexCoord%d = aTexCoord%d;\n", i, i);
vs_len += sprintf(vs_buf + vs_len, " vTexCoord%d = aTexCoord%d;\n", i, i);
for (int j = 0; j < 2; j++) {
if (cc_features.clamp[i][j]) {
vs_len += sprintf(vs_buf + vs_len, "vTexClamp%s%d = aTexClamp%s%d;\n", j == 0 ? "S" : "T", i,
vs_len += sprintf(vs_buf + vs_len, " vTexClamp%s%d = aTexClamp%s%d;\n", j == 0 ? "S" : "T", i,
j == 0 ? "S" : "T", i);
}
}
}
}
if (cc_features.opt_fog) {
append_line(vs_buf, &vs_len, "vFog = aFog;");
append_line(vs_buf, &vs_len, " vFog = aFog;");
}
if (cc_features.opt_grayscale) {
append_line(vs_buf, &vs_len, "vGrayscaleColor = aGrayscaleColor;");
append_line(vs_buf, &vs_len, " vGrayscaleColor = aGrayscaleColor;");
}
for (int i = 0; i < cc_features.num_inputs; i++) {
vs_len += sprintf(vs_buf + vs_len, "vInput%d = aInput%d;\n", i + 1, i + 1);
vs_len += sprintf(vs_buf + vs_len, " vInput%d = aInput%d;\n", i + 1, i + 1);
}
append_line(vs_buf, &vs_len, " gl_Position = aVtxPos;");
if (!GLAD_GL_ARB_depth_clamp) {
// HACK: workaround for no GL_DEPTH_CLAMP
append_line(vs_buf, &vs_len, " gl_Position.z *= 0.3f;");
}
append_line(vs_buf, &vs_len, "gl_Position = aVtxPos;");
append_line(vs_buf, &vs_len, "}");
// Fragment shader
#ifdef __APPLE__
append_line(fs_buf, &fs_len, "#version 410 core");
#else
append_line(fs_buf, &fs_len, "#version 130");
#endif
fs_len += sprintf(fs_buf + fs_len, "#version %s\n", gl_glsl_version_str);
if (gl_es) {
append_line(fs_buf, &fs_len, "precision mediump float;");
}
if (gl_glsl_version >= 130) {
append_line(fs_buf, &fs_len, "#define INPUT in");
append_line(fs_buf, &fs_len, "#define OUTPUT_COLOR outColor");
append_line(fs_buf, &fs_len, "#define SAMPLE_TEX(tex, uv) texture(tex, uv)");
} else {
append_line(fs_buf, &fs_len, "#define INPUT varying");
append_line(fs_buf, &fs_len, "#define OUTPUT_COLOR gl_FragColor");
append_line(fs_buf, &fs_len, "#define SAMPLE_TEX(tex, uv) texture2D(tex, uv)");
}
// Reference approach to color wrapping as per GLideN64
// Return wrapped value of x in interval [low, high)
append_line(fs_buf, &fs_len, "#define WRAP(x, low, high) mod((x)-(low), (high)-(low)) + (low)");
append_line(fs_buf, &fs_len, "#define TEX_OFFSET(tex, uv, texSize, off) SAMPLE_TEX(tex, uv - (off)/texSize)");
// append_line(fs_buf, &fs_len, "precision mediump float;");
for (int i = 0; i < 2; i++) {
if (cc_features.used_textures[i]) {
#ifdef __APPLE__
fs_len += sprintf(fs_buf + fs_len, "in vec2 vTexCoord%d;\n", i);
#else
fs_len += sprintf(fs_buf + fs_len, "varying vec2 vTexCoord%d;\n", i);
#endif
fs_len += sprintf(fs_buf + fs_len, "INPUT vec2 vTexCoord%d;\n", i);
for (int j = 0; j < 2; j++) {
if (cc_features.clamp[i][j]) {
#ifdef __APPLE__
fs_len += sprintf(fs_buf + fs_len, "in float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
#else
fs_len += sprintf(fs_buf + fs_len, "varying float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
#endif
fs_len += sprintf(fs_buf + fs_len, "INPUT float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
}
}
}
}
if (cc_features.opt_fog) {
#ifdef __APPLE__
append_line(fs_buf, &fs_len, "in vec4 vFog;");
#else
append_line(fs_buf, &fs_len, "varying vec4 vFog;");
#endif
append_line(fs_buf, &fs_len, "INPUT vec4 vFog;");
}
if (cc_features.opt_grayscale) {
#ifdef __APPLE__
append_line(fs_buf, &fs_len, "in vec4 vGrayscaleColor;");
#else
append_line(fs_buf, &fs_len, "varying vec4 vGrayscaleColor;");
#endif
append_line(fs_buf, &fs_len, "INPUT vec4 vGrayscaleColor;");
}
for (int i = 0; i < cc_features.num_inputs; i++) {
#ifdef __APPLE__
fs_len += sprintf(fs_buf + fs_len, "in vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
#else
fs_len += sprintf(fs_buf + fs_len, "varying vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
#endif
fs_len += sprintf(fs_buf + fs_len, "INPUT vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
}
if (cc_features.used_textures[0]) {
append_line(fs_buf, &fs_len, "uniform sampler2D uTex0;");
if (current_filter_mode == FILTER_THREE_POINT)
append_line(fs_buf, &fs_len, "uniform int three_point_filter0;");
}
if (cc_features.used_textures[1]) {
append_line(fs_buf, &fs_len, "uniform sampler2D uTex1;");
if (current_filter_mode == FILTER_THREE_POINT)
append_line(fs_buf, &fs_len, "uniform int three_point_filter1;");
}
append_line(fs_buf, &fs_len, "uniform int frame_count;");
@@ -382,92 +386,97 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
append_line(fs_buf, &fs_len, " return fract(sin(random) * 143758.5453);");
append_line(fs_buf, &fs_len, "}");
if (current_filter_mode == FILTER_THREE_POINT) {
append_line(fs_buf, &fs_len, "vec4 filter3point(in sampler2D tex, in vec2 texCoord, in vec2 texSize) {");
append_line(fs_buf, &fs_len, " vec2 offset = fract(texCoord*texSize - vec2(0.5));");
append_line(fs_buf, &fs_len, " offset -= step(1.0, offset.x + offset.y);");
append_line(fs_buf, &fs_len, " vec4 c0 = TEX_OFFSET(tex, texCoord, texSize, offset);");
append_line(fs_buf, &fs_len, " vec4 c1 = TEX_OFFSET(tex, texCoord, texSize, vec2(offset.x - sign(offset.x), offset.y));");
append_line(fs_buf, &fs_len, " vec4 c2 = TEX_OFFSET(tex, texCoord, texSize, vec2(offset.x, offset.y - sign(offset.y)));");
append_line(fs_buf, &fs_len, " return c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0);");
append_line(fs_buf, &fs_len, "}");
}
if (cc_features.opt_blur) {
// blur filter, used for menu backgrounds
// used to be two for loops from 0 to 4, but apparently intel drivers crashed trying to unroll it
// used to have a const weight array, but apparently drivers for the GT620 don't like const array initializers
append_line(fs_buf, &fs_len, R"(
lowp vec4 hookTexture2D(in sampler2D t, in vec2 uv, in vec2 tsize) {
lowp vec4 cw = vec4(0.0);
for (int i = 0; i < 16; ++i) {
vec2 xy = vec2(float(i & 3), float(i >> 2));
lowp float w = 0.009947 - length(xy) * 0.001;
cw += vec4(texture2D(t, uv + (vec2(-1.5) + xy) / tsize).rgb * w, w);
}
return vec4(cw.rgb / cw.a, 1.0);
})"
);
} else if (current_filter_mode == FILTER_THREE_POINT) {
#if __APPLE__
append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture(tex, texCoord - (off)/texSize)");
#else
append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture2D(tex, texCoord - (off)/texSize)");
#endif
append_line(fs_buf, &fs_len, "vec4 filter3point(in sampler2D tex, in vec2 texCoord, in vec2 texSize) {");
append_line(fs_buf, &fs_len, " vec2 offset = fract(texCoord*texSize - vec2(0.5));");
append_line(fs_buf, &fs_len, " offset -= step(1.0, offset.x + offset.y);");
append_line(fs_buf, &fs_len, " vec4 c0 = TEX_OFFSET(offset);");
append_line(fs_buf, &fs_len, " vec4 c1 = TEX_OFFSET(vec2(offset.x - sign(offset.x), offset.y));");
append_line(fs_buf, &fs_len, " vec4 c2 = TEX_OFFSET(vec2(offset.x, offset.y - sign(offset.y)));");
append_line(fs_buf, &fs_len, " return c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0);");
append_line(fs_buf, &fs_len, "}");
append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {");
append_line(fs_buf, &fs_len, " return filter3point(tex, uv, texSize);");
if (current_filter_mode == FILTER_THREE_POINT)
append_line(fs_buf, &fs_len, "lowp vec4 hookTexture2D(in sampler2D t, in vec2 uv, in vec2 texSize, in int three_point_filter) {");
else
append_line(fs_buf, &fs_len, "lowp vec4 hookTexture2D(in sampler2D t, in vec2 uv, in vec2 texSize) {");
append_line(fs_buf, &fs_len, " lowp vec4 cw = vec4(0.0);");
append_line(fs_buf, &fs_len, " for (int i = 0; i < 16; ++i) {");
append_line(fs_buf, &fs_len, " vec2 xy = vec2(float(i & 3), float(i >> 2));");
append_line(fs_buf, &fs_len, " lowp float w = 0.009947 - length(xy) * 0.001;");
append_line(fs_buf, &fs_len, " vec2 scaled_uv = uv + (vec2(-1.5) + xy) / texSize;");
if (current_filter_mode == FILTER_THREE_POINT)
append_line(fs_buf, &fs_len, " lowp vec4 tex = mix(SAMPLE_TEX(t, scaled_uv), filter3point(t, scaled_uv, texSize), three_point_filter);");
else
append_line(fs_buf, &fs_len, " lowp vec4 tex = SAMPLE_TEX(t, scaled_uv);");
append_line(fs_buf, &fs_len, " cw += vec4(tex.rgb * w, w);");
append_line(fs_buf, &fs_len, " }");
append_line(fs_buf, &fs_len, " return vec4(cw.rgb / cw.a, 1.0);");
append_line(fs_buf, &fs_len, "}");
} else {
append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {");
#if __APPLE__
append_line(fs_buf, &fs_len, " return texture(tex, uv);");
#else
append_line(fs_buf, &fs_len, " return texture2D(tex, uv);");
#endif
append_line(fs_buf, &fs_len, "}");
if (current_filter_mode == FILTER_THREE_POINT) {
append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize, in int three_point_filter) {");
append_line(fs_buf, &fs_len, " return mix(SAMPLE_TEX(tex, uv), filter3point(tex, uv, texSize), three_point_filter);");
append_line(fs_buf, &fs_len, "}");
} else {
append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {");
append_line(fs_buf, &fs_len, " return SAMPLE_TEX(tex, uv);");
append_line(fs_buf, &fs_len, "}");
}
}
#if __APPLE__
append_line(fs_buf, &fs_len, "out vec4 outColor;");
#endif
if (gl_glsl_version >= 130) {
append_line(fs_buf, &fs_len, "out vec4 outColor;");
}
append_line(fs_buf, &fs_len, "void main() {");
// Reference approach to color wrapping as per GLideN64
// Return wrapped value of x in interval [low, high)
append_line(fs_buf, &fs_len, "#define WRAP(x, low, high) mod((x)-(low), (high)-(low)) + (low)");
for (int i = 0; i < 2; i++) {
if (cc_features.used_textures[i]) {
bool s = cc_features.clamp[i][0], t = cc_features.clamp[i][1];
fs_len += sprintf(fs_buf + fs_len, "vec2 texSize%d = textureSize(uTex%d, 0);\n", i, i);
fs_len += sprintf(fs_buf + fs_len, " vec2 texSize%d = vec2(textureSize(uTex%d, 0));\n", i, i);
if (!s && !t) {
fs_len += sprintf(fs_buf + fs_len, "vec2 vTexCoordAdj%d = vTexCoord%d;\n", i, i);
fs_len += sprintf(fs_buf + fs_len, " vec2 vTexCoordAdj%d = vTexCoord%d;\n", i, i);
} else {
if (s && t) {
fs_len += sprintf(fs_buf + fs_len,
"vec2 vTexCoordAdj%d = clamp(vTexCoord%d, 0.5 / texSize%d, "
" vec2 vTexCoordAdj%d = clamp(vTexCoord%d, 0.5 / texSize%d, "
"vec2(vTexClampS%d, vTexClampT%d));\n",
i, i, i, i, i);
} else if (s) {
fs_len += sprintf(fs_buf + fs_len,
"vec2 vTexCoordAdj%d = vec2(clamp(vTexCoord%d.s, 0.5 / "
" vec2 vTexCoordAdj%d = vec2(clamp(vTexCoord%d.s, 0.5 / "
"texSize%d.s, vTexClampS%d), vTexCoord%d.t);\n",
i, i, i, i, i);
} else {
fs_len += sprintf(fs_buf + fs_len,
"vec2 vTexCoordAdj%d = vec2(vTexCoord%d.s, clamp(vTexCoord%d.t, "
" vec2 vTexCoordAdj%d = vec2(vTexCoord%d.s, clamp(vTexCoord%d.t, "
"0.5 / texSize%d.t, vTexClampT%d));\n",
i, i, i, i, i);
}
}
fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = hookTexture2D(uTex%d, vTexCoordAdj%d, texSize%d);\n", i, i, i, i);
if (current_filter_mode == FILTER_THREE_POINT)
fs_len += sprintf(fs_buf + fs_len, " vec4 texVal%d = hookTexture2D(uTex%d, vTexCoordAdj%d, texSize%d, three_point_filter%d);\n", i, i, i, i, i);
else
fs_len += sprintf(fs_buf + fs_len, " vec4 texVal%d = hookTexture2D(uTex%d, vTexCoordAdj%d, texSize%d);\n", i, i, i, i);
}
}
append_line(fs_buf, &fs_len, cc_features.opt_alpha ? "vec4 texel;" : "vec3 texel;");
append_line(fs_buf, &fs_len, cc_features.opt_alpha ? " vec4 texel;" : " vec3 texel;");
for (int c = 0; c < (cc_features.opt_2cyc ? 2 : 1); c++) {
append_str(fs_buf, &fs_len, "texel = ");
append_str(fs_buf, &fs_len, " texel = ");
if (!cc_features.color_alpha_same[c] && cc_features.opt_alpha) {
append_str(fs_buf, &fs_len, "vec4(");
append_formula(fs_buf, &fs_len, cc_features.c[c], cc_features.do_single[c][0],
@@ -484,56 +493,50 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
append_line(fs_buf, &fs_len, ";");
if (c == 0) {
append_str(fs_buf, &fs_len, "texel = WRAP(texel, -1.01, 1.01);");
append_line(fs_buf, &fs_len, " texel = WRAP(texel, -1.01, 1.01);");
}
}
append_str(fs_buf, &fs_len, "texel = WRAP(texel, -0.51, 1.51);");
append_str(fs_buf, &fs_len, "texel = clamp(texel, 0.0, 1.0);");
append_line(fs_buf, &fs_len, " texel = WRAP(texel, -0.51, 1.51);");
append_line(fs_buf, &fs_len, " texel = clamp(texel, 0.0, 1.0);");
// TODO discard if alpha is 0?
if (cc_features.opt_fog) {
if (cc_features.opt_alpha) {
append_line(fs_buf, &fs_len, "texel = vec4(mix(texel.rgb, vFog.rgb, vFog.a), texel.a);");
append_line(fs_buf, &fs_len, " texel = vec4(mix(texel.rgb, vFog.rgb, vFog.a), texel.a);");
} else {
append_line(fs_buf, &fs_len, "texel = mix(texel, vFog.rgb, vFog.a);");
append_line(fs_buf, &fs_len, " texel = mix(texel, vFog.rgb, vFog.a);");
}
}
if (cc_features.opt_texture_edge && cc_features.opt_alpha) {
append_line(fs_buf, &fs_len, "if (texel.a > 0.19) texel.a = 1.0; else discard;");
append_line(fs_buf, &fs_len, " if (texel.a > 0.19) texel.a = 1.0; else discard;");
}
if (cc_features.opt_alpha && cc_features.opt_noise) {
append_line(fs_buf, &fs_len,
"texel.a *= floor(clamp(random(vec3(floor(gl_FragCoord.xy * noise_scale), float(frame_count))) + "
" texel.a *= floor(clamp(random(vec3(floor(gl_FragCoord.xy * noise_scale), float(frame_count))) + "
"texel.a, 0.0, 1.0));");
}
if (cc_features.opt_grayscale) {
append_line(fs_buf, &fs_len, "float intensity = (texel.r + texel.g + texel.b) / 3.0;");
append_line(fs_buf, &fs_len, "vec3 new_texel = vGrayscaleColor.rgb * intensity;");
append_line(fs_buf, &fs_len, "texel.rgb = mix(texel.rgb, new_texel, vGrayscaleColor.a);");
append_line(fs_buf, &fs_len, " float intensity = (texel.r + texel.g + texel.b) / 3.0;");
append_line(fs_buf, &fs_len, " vec3 new_texel = vGrayscaleColor.rgb * intensity;");
append_line(fs_buf, &fs_len, " texel.rgb = mix(texel.rgb, new_texel, vGrayscaleColor.a);");
}
if (cc_features.opt_alpha) {
if (cc_features.opt_alpha_threshold) {
append_line(fs_buf, &fs_len, "if (texel.a < 8.0 / 256.0) discard;");
append_line(fs_buf, &fs_len, " if (texel.a < 8.0 / 256.0) discard;");
}
if (cc_features.opt_invisible) {
append_line(fs_buf, &fs_len, "texel.a = 0.0;");
append_line(fs_buf, &fs_len, " texel.a = 0.0;");
}
#if __APPLE__
append_line(fs_buf, &fs_len, "outColor = texel;");
#else
append_line(fs_buf, &fs_len, "gl_FragColor = texel;");
#endif
append_line(fs_buf, &fs_len, " OUTPUT_COLOR = texel;");
} else {
#if __APPLE__
append_line(fs_buf, &fs_len, "outColor = vec4(texel, 1.0);");
#else
append_line(fs_buf, &fs_len, "gl_FragColor = vec4(texel, 1.0);");
#endif
append_line(fs_buf, &fs_len, " OUTPUT_COLOR = vec4(texel, 1.0);");
}
append_line(fs_buf, &fs_len, "}");
vs_buf[vs_len] = '\0';
@@ -574,6 +577,11 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program);
glDetachShader(shader_program, vertex_shader);
glDetachShader(shader_program, fragment_shader);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
size_t cnt = 0;
struct ShaderProgram* prg = &shader_program_pool[make_pair(shader_id0, shader_id1)];
@@ -640,6 +648,8 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
prg->frame_count_location = glGetUniformLocation(shader_program, "frame_count");
prg->noise_scale_location = glGetUniformLocation(shader_program, "noise_scale");
prg->three_point_filter_locations[0] = glGetUniformLocation(shader_program, "three_point_filter0");
prg->three_point_filter_locations[1] = glGetUniformLocation(shader_program, "three_point_filter1");
gfx_opengl_load_shader(prg);
@@ -657,6 +667,14 @@ static void gfx_opengl_shader_get_info(struct ShaderProgram* prg, uint8_t* num_i
used_textures[1] = prg->used_textures[1];
}
static void gfx_opengl_clear_shaders(void) {
glUseProgram(0);
for (auto& pair : shader_program_pool) {
glDeleteProgram(pair.second.opengl_program_id);
}
shader_program_pool.clear();
}
static GLuint gfx_opengl_new_texture(void) {
GLuint ret;
glGenTextures(1, &ret);
@@ -667,9 +685,11 @@ static void gfx_opengl_delete_texture(uint32_t texID) {
glDeleteTextures(1, &texID);
}
static void gfx_opengl_select_texture(int tile, GLuint texture_id) {
static void gfx_opengl_select_texture(int tile, GLuint texture_id, bool linear_filter) {
glActiveTexture(GL_TEXTURE0 + tile);
glBindTexture(GL_TEXTURE_2D, texture_id);
current_textures_linear_filter[tile] = linear_filter;
}
static void gfx_opengl_upload_texture(const uint8_t* rgba32_buf, uint32_t width, uint32_t height) {
@@ -699,28 +719,52 @@ static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gfx_cm_to_opengl(cmt));
}
static void gfx_opengl_set_depth_test_and_mask(bool depth_test, bool z_upd) {
if (depth_test || z_upd) {
static void gfx_opengl_set_depth_mode(bool depth_test, bool depth_update, bool depth_compare, bool depth_source_prim, uint16_t zmode) {
if (depth_test) {
glEnable(GL_DEPTH_TEST);
glDepthMask(z_upd ? GL_TRUE : GL_FALSE);
glDepthFunc(depth_test ? GL_LEQUAL : GL_ALWAYS);
current_depth_mask = z_upd;
glDepthMask(depth_update ? GL_TRUE : GL_FALSE);
current_depth_mask = depth_update;
if (depth_compare) {
switch (zmode) {
case ZMODE_INTER:
glDepthFunc(GL_LEQUAL);
glDisable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0, 0);
break;
case ZMODE_OPA:
case ZMODE_XLU:
if (depth_source_prim) {
glDepthFunc(GL_LEQUAL);
} else {
glDepthFunc(GL_LESS);
}
glDisable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0, 0);
break;
case ZMODE_DEC:
glDepthFunc(GL_LEQUAL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-2, -2);
break;
}
} else {
glDepthFunc(GL_ALWAYS);
glDisable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0, 0);
}
} else {
glDisable(GL_DEPTH_TEST);
}
}
static void gfx_opengl_set_depth_range(float znear, float zfar) {
glDepthRange(znear, zfar);
}
static void gfx_opengl_set_zmode_decal(bool zmode_decal) {
if (zmode_decal) {
glPolygonOffset(-2, -2);
glEnable(GL_POLYGON_OFFSET_FILL);
if (glDepthRangef) {
glDepthRangef(znear, zfar);
} else {
glPolygonOffset(0, 0);
glDisable(GL_POLYGON_OFFSET_FILL);
glDepthRange(znear, zfar);
}
}
@@ -791,18 +835,6 @@ static bool gfx_opengl_supports_framebuffers(void) {
return (glad_glBlitFramebuffer && glad_glRenderbufferStorageMultisample);
}
if (GLAD_GL_EXT_framebuffer_object && GLAD_GL_EXT_framebuffer_blit && GLAD_GL_EXT_framebuffer_multisample) {
// because of the way glad works we'll have to copy the pointers over
glad_glGenFramebuffers = glad_glGenFramebuffersEXT;
glad_glGenRenderbuffers = glad_glGenRenderbuffersEXT;
glad_glDeleteFramebuffers = glad_glDeleteFramebuffersEXT;
glad_glDeleteRenderbuffers = glad_glDeleteRenderbuffersEXT;
glad_glBindFramebuffer = glad_glBindFramebufferEXT;
glad_glBindRenderbuffer = glad_glBindRenderbufferEXT;
glad_glFramebufferRenderbuffer = glad_glFramebufferRenderbufferEXT;
glad_glFramebufferTexture2D = glad_glFramebufferTexture2DEXT;
glad_glRenderbufferStorage = glad_glRenderbufferStorageEXT;
glad_glRenderbufferStorageMultisample = glad_glRenderbufferStorageMultisampleEXT;
glad_glBlitFramebuffer = glad_glBlitFramebufferEXT;
// sanity check
return (glad_glFramebufferRenderbuffer && glad_glBlitFramebuffer && glad_glRenderbufferStorageMultisample);
}
@@ -867,11 +899,52 @@ static void *gl_load_proc(const char *name) {
return NULL;
}
static void gfx_opengl_init_extensions(void) {
// patch up some extension values and pointers
if (!GLAD_GL_ARB_depth_clamp) {
if (GLAD_GL_EXT_depth_clamp || GLAD_GL_NV_depth_clamp) {
GLAD_GL_ARB_depth_clamp = 1;
} else if (!gl_es && GLVersion.major >= 3) {
// GL3.2+ should have depth_clamp as part of the spec, but some devices don't report it for some reason
GLAD_GL_ARB_depth_clamp = (GLVersion.major > 3 || (GLVersion.major == 3 && GLVersion.minor >= 2));
}
}
if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) {
GLAD_GL_ARB_texture_mirror_clamp_to_edge = GLAD_GL_EXT_texture_mirror_clamp_to_edge;
}
if (GLVersion.major < 3 && !GLAD_GL_ARB_framebuffer_object) {
if (GLAD_GL_EXT_framebuffer_object && GLAD_GL_EXT_framebuffer_blit && GLAD_GL_EXT_framebuffer_multisample) {
// because of the way glad works we'll have to copy the pointers over
glad_glGenFramebuffers = glad_glGenFramebuffersEXT;
glad_glGenRenderbuffers = glad_glGenRenderbuffersEXT;
glad_glDeleteFramebuffers = glad_glDeleteFramebuffersEXT;
glad_glDeleteRenderbuffers = glad_glDeleteRenderbuffersEXT;
glad_glBindFramebuffer = glad_glBindFramebufferEXT;
glad_glBindRenderbuffer = glad_glBindRenderbufferEXT;
glad_glFramebufferRenderbuffer = glad_glFramebufferRenderbufferEXT;
glad_glFramebufferTexture2D = glad_glFramebufferTexture2DEXT;
glad_glRenderbufferStorage = glad_glRenderbufferStorageEXT;
glad_glRenderbufferStorageMultisample = glad_glRenderbufferStorageMultisampleEXT;
glad_glBlitFramebuffer = glad_glBlitFramebufferEXT;
}
}
}
static void gfx_opengl_init(void) {
if (!gladLoadGLLoader(gl_load_proc) || glGetString == NULL || glEnable == NULL) {
sysFatalError("Could not load OpenGL.\nReported SDL error: %s", SDL_GetError());
}
// check if we're using ES or core, which have more limited feature sets
int val = 0;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &val);
gl_core_profile = (val == SDL_GL_CONTEXT_PROFILE_CORE);
gl_es = (val == SDL_GL_CONTEXT_PROFILE_ES);
gfx_opengl_init_extensions();
if (sysArgCheck("--debug-gl")) {
gfx_opengl_enable_debug();
// dump version info as early as possible
@@ -885,7 +958,7 @@ static void gfx_opengl_init(void) {
}
if (!gfx_opengl_supports_shaders()) {
sysLogPrintf(LOG_WARNING, "GL: GLSL 1.30 unsupported");
sysLogPrintf(LOG_WARNING, "GL: GLSL 1.30 may be unsupported");
// maybe replace this with sysFatalError, though the GLSL compiler will cause that later anyway
}
@@ -901,20 +974,35 @@ static void gfx_opengl_init(void) {
gl_mirror_clamp = GL_MIRRORED_REPEAT;
}
if ((GLVersion.major == 3 && GLVersion.minor >= 2) || GLVersion.major > 3) {
// check if we're using core profile, which is more strict
int val = 0;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &val);
gl_core_profile = (val == SDL_GL_CONTEXT_PROFILE_CORE);
// determine GLSL version
if (gl_es) {
// ES has its own numbering scheme, but it should support 300 even on 3.1 and 3.2
gl_glsl_version = 300;
snprintf(gl_glsl_version_str, sizeof(gl_glsl_version_str), "%d es", gl_glsl_version);
} else if (!gl_core_profile) {
// in compat profile we can just request the lowest possible
gl_glsl_version = 130;
snprintf(gl_glsl_version_str, sizeof(gl_glsl_version_str), "%d", gl_glsl_version);
} else {
// otherwise we have to pick a specific version
if (GLVersion.major == 3 && GLVersion.minor == 2) {
// 3.2core is the earliest core version and it follows the old numbering scheme
gl_glsl_version = 150;
} else {
// 3.3+ follow the new numbering scheme
gl_glsl_version = GLVersion.major * 100 + GLVersion.minor * 10;
}
snprintf(gl_glsl_version_str, sizeof(gl_glsl_version_str), "%d core", gl_glsl_version);
}
sysLogPrintf(LOG_NOTE, "GL: using GLSL version %s", gl_glsl_version_str);
glGenBuffers(1, &opengl_vbo);
glBindBuffer(GL_ARRAY_BUFFER, opengl_vbo);
if (gl_core_profile) {
if (gl_core_profile || gl_es) {
// warn user that funny things can happen
sysLogPrintf(LOG_WARNING, "GL: using core profile, watch out for errors");
// core will explode if we don't use a VAO for our VBO
sysLogPrintf(LOG_WARNING, "GL: using core profile or ES, watch out for errors");
// core/es will explode if we don't use a VAO for our VBO
glGenVertexArrays(1, &opengl_vao);
glBindVertexArray(opengl_vao);
}
@@ -1045,12 +1133,23 @@ bool gfx_opengl_start_draw_to_framebuffer(int fb_id, float noise_scale) {
}
}
void gfx_opengl_clear_framebuffer() {
void gfx_opengl_clear_framebuffer(bool clear_color, bool clear_depth) {
glDisable(GL_SCISSOR_TEST);
glDepthMask(GL_TRUE);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(current_depth_mask ? GL_TRUE : GL_FALSE);
GLbitfield mask = 0;
if (clear_color) {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
mask |= GL_COLOR_BUFFER_BIT;
}
if (clear_depth) {
glDepthMask(GL_TRUE);
mask |= GL_DEPTH_BUFFER_BIT;
}
glClear(mask);
if (clear_depth) {
glDepthMask(current_depth_mask ? GL_TRUE : GL_FALSE);
}
glEnable(GL_SCISSOR_TEST);
}
@@ -1078,6 +1177,8 @@ void gfx_opengl_select_texture_fb(int fb_id) {
// glDisable(GL_DEPTH_TEST);
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, framebuffers[fb_id].clrbuf);
current_textures_linear_filter[0] = true;
}
void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top, bool flip_y, bool use_back) {
@@ -1120,7 +1221,8 @@ void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top, bool
}
if (fb_src == 0) {
glReadBuffer(use_back ? GL_BACK : GL_FRONT);
// GLES does not support GL_FRONT here
glReadBuffer((use_back || gl_es) ? GL_BACK : GL_FRONT);
} else {
glReadBuffer(GL_COLOR_ATTACHMENT0);
}
@@ -1136,7 +1238,6 @@ void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top, bool
void gfx_opengl_set_texture_filter(FilteringMode mode) {
current_filter_mode = mode;
gfx_texture_cache_clear();
}
FilteringMode gfx_opengl_get_texture_filter(void) {
@@ -1152,13 +1253,13 @@ struct GfxRenderingAPI gfx_opengl_api = {
gfx_opengl_create_and_load_new_shader,
gfx_opengl_lookup_shader,
gfx_opengl_shader_get_info,
gfx_opengl_clear_shaders,
gfx_opengl_new_texture,
gfx_opengl_select_texture,
gfx_opengl_upload_texture,
gfx_opengl_set_sampler_parameters,
gfx_opengl_set_depth_test_and_mask,
gfx_opengl_set_depth_mode,
gfx_opengl_set_depth_range,
gfx_opengl_set_zmode_decal,
gfx_opengl_set_viewport,
gfx_opengl_set_scissor,
gfx_opengl_set_use_alpha,
+72 -69
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,7 +550,7 @@ 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->select_texture(i, texture_id, false);
gfx_rapi->set_sampler_parameters(i, false, 0, 0);
*n = node;
return false;
@@ -1240,25 +1239,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) {
@@ -1584,7 +1576,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 +1640,27 @@ 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
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;
}
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 +1718,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 +1972,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 +1985,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 +2374,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 +2491,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 +2545,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 +2650,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 +2660,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 +2692,18 @@ extern "C" void gfx_set_target_fps(int fps) {
gfx_wapi->set_target_fps(fps);
}
extern "C" void gfx_set_texture_filter(enum FilteringMode mode) {
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();
gfx_rapi->set_texture_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 +2735,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 +2761,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();
}
+4 -4
View File
@@ -23,13 +23,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 (*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);
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 (*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,7 +45,7 @@ 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);
+150 -29
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);
}
@@ -96,11 +112,19 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
posY = 100;
}
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);
};
+766 -844
View File
File diff suppressed because it is too large. Load diff
+842 -1492
View File
File diff suppressed because it is too large. Load diff
+1
View File
@@ -10,5 +10,6 @@ void conTick(void);
void conPrint(s32 showmsg, const char *s);
void conPrintf(s32 showmsg, const char *fmt, ...);
void conPrintLn(s32 showmsg, const char *s);
s32 conIsOpen(void);
#endif
+2
View File
@@ -1150,6 +1150,7 @@ extern "C" {
return t;
}
#ifndef __MINGW32__
int clock_gettime(int X, struct timespec* tv) {
LARGE_INTEGER t;
FILETIME f;
@@ -1193,6 +1194,7 @@ extern "C" {
return 0;
}
#endif
#elif __APPLE__ && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200 || __IPHONE_OS_VERSION_MIN_REQUIRED < 100000) && !defined(CLOCK_MONOTONIC)
#define CLOCK_MONOTONIC 0
+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
+118 -82
View File
@@ -17,88 +17,108 @@
#define CONT_NUM_BUTTONS 32 // not including the stick axes
enum virtkey {
/* 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_RCTRL = 228,
VK_RSHIFT = 229,
/* 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
@@ -125,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);
@@ -152,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);
@@ -186,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);
@@ -219,19 +245,29 @@ void inputSetDefaultKeyBinds(s32 cidx, s32 n64mode);
void inputClearLastKey(void);
s32 inputGetLastKey(void);
// 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 inputTextHandler(char *out, const u32 outSize, s32 *curCol, s32 oskCharsOnly);
void inputClearClipboard(void);
const char *inputGetClipboard(void);
// get/set Input.MouseDefaultLocked
s32 inputGetMouseDefaultLocked(void);
void inputSetMouseDefaultLocked(s32 defaultLocked);
// 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
@@ -10,7 +10,7 @@ extern const char *g_RomName;
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);
@@ -22,5 +22,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
@@ -37,6 +37,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
+28 -1
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,18 +32,38 @@ 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);
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 videoGetAverageFPS(void);
f64 videoGetLastRenderTime(void);
void videoCapFramerate(s32 limit);
void videoSetWindowOffset(s32 x, s32 y);
void videoSetFullscreen(s32 fs);
void videoSetFullscreenMode(s32 mode);
void videoSetTextureFilter(u32 filter);
void videoSetTextureFilter2D(s32 filter);
void videoSetDetailTextures(s32 detail);
void videoCapFramerate(s32 limit);
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);
s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize);
void videoSetFramebuffer(s32 target);
@@ -50,4 +75,6 @@ s32 videoFramebuffersSupported(void);
void videoResetTextureCache(void);
void videoFreeCachedTexture(const void *texptr);
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;
}
+8 -1
View File
@@ -192,7 +192,9 @@ void conTick(void)
const s32 button = inputKeyPressed(VK_GRAVE);
if (button && !conButton) {
conOpen = !conOpen;
g_MenuKeyboardPlayer = -1;
if (conOpen) {
inputClearLastTextChar();
inputStartTextInput();
} else {
inputStopTextInput();
@@ -202,7 +204,7 @@ void conTick(void)
conButton = button;
if (conOpen) {
if (inputTextHandler(conInput, CON_COLS, &conInputCol)) {
if (inputTextHandler(conInput, CON_COLS, &conInputCol, false)) {
if (g_NetMode) {
netChat(NULL, conInput);
}
@@ -211,3 +213,8 @@ void conTick(void)
}
}
}
s32 conIsOpen(void)
{
return conOpen;
}
+14 -2
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"
@@ -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
}
+197 -52
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,16 +74,22 @@ static s32 connectedMask = 0;
static s32 numJoysticks = 0;
static s32 useHIDAPI = 1;
static s32 useRawInput = 1;
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;
@@ -107,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",
@@ -173,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
@@ -213,6 +226,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 },
};
@@ -323,6 +338,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)
@@ -654,6 +677,38 @@ 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");
#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 (useRawInput) {
SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT, "1");
}
if (!SDL_WasInit(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC)) {
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC);
}
@@ -678,7 +733,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
@@ -748,12 +805,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]);
@@ -808,8 +875,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;
@@ -818,10 +889,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);
}
}
}
}
@@ -919,6 +998,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];
@@ -988,6 +1077,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;
}
@@ -1069,9 +1165,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]) {
@@ -1085,9 +1185,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) {
@@ -1117,10 +1226,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)
@@ -1129,32 +1239,28 @@ 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;
if (mouseLocked) {
mdx = mouseSensX * (f32)mouseDX / 100.0f;
mdy = mouseSensY * (f32)mouseDY / 100.0f;
} else {
mdx = 0.f;
mdy = 0.f;
}
if (dx) *dx = mdx;
if (dy) *dy = mdy;
f32 mdx = 0.f, mdy = 0.f;
if (mouseLocked) {
mdx = mouseSensX * ((f32)mouseDX / 3.5f) * 0.022f;
mdy = mouseSensY * ((f32)mouseDY / 3.5f) * 0.022f;
}
if (dx) *dx = mdx;
if (dy) *dy = mdy;
}
void inputMouseGetAbsScaledDelta(f32 *dx, f32 *dy)
void inputMouseGetAbsScaledDelta(f32* dx, f32* dy)
{
f32 mdx, mdy;
if (mouseLocked) {
mdx = fabsf(mouseSensX) * (f32)mouseDX / 100.0f;
mdy = fabsf(mouseSensY) * (f32)mouseDY / 100.0f;
} else {
mdx = 0.f;
mdy = 0.f;
}
if (dx) *dx = mdx;
if (dy) *dy = mdy;
f32 mdx = 0.f, mdy = 0.f;
if (mouseLocked) {
mdx = fabsf(mouseSensX) * ((f32)mouseDX / 3.5f) * 0.022f;
mdy = fabsf(mouseSensY) * ((f32)mouseDY / 3.5f) * 0.022f;
}
if (dx) *dx = mdx;
if (dy) *dy = mdy;
}
void inputMouseGetSpeed(f32 *x, f32 *y)
@@ -1177,21 +1283,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);
}
}
@@ -1287,14 +1413,20 @@ char inputGetLastTextChar(void)
return lastChar;
}
s32 inputTextHandler(char *out, const u32 outSize, s32 *curCol)
static inline s32 filterChar(const char ch)
{
const s32 ctrlHeld = inputKeyPressed(VK_LCTRL) || inputKeyPressed(VK_RCTRL);
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();
if (chr && isprint(chr)) {
const s32 valid = chr && (oskCharsOnly ? filterChar(chr) : isprint(chr));
if (valid) {
if (*curCol < outSize - 1) {
out[(*curCol)++] = chr;
out[*curCol] = '\0';
@@ -1363,14 +1495,26 @@ void inputStopTextInput(void)
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);
configRegisterInt("Input.MouseLockMode", &mouseLockMode, MLOCK_OFF, MLOCK_AUTO);
configRegisterFloat("Input.MouseSpeedX", &mouseSensX, -10.f, 10.f);
configRegisterFloat("Input.MouseSpeedY", &mouseSensY, -10.f, 10.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 };
@@ -1387,6 +1531,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
+5
View File
@@ -91,6 +91,7 @@ static void cleanup(void)
netDisconnect();
inputSaveBinds();
configSave(CONFIG_PATH);
videoShutdown();
crashShutdown();
// TODO: actually shut down all subsystems
}
@@ -113,6 +114,8 @@ int main(int argc, const char **argv)
romdataInit();
netInit();
g_ValidGbcRomFound = romdataCheckGbcRom();
gameInit();
if (fsGetModDir()) {
@@ -174,6 +177,7 @@ 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);
@@ -194,5 +198,6 @@ PD_CONSTRUCTOR static void gameConfigInit(void)
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);
}
}
+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 = -1;
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);
}
+2 -2
View File
@@ -221,14 +221,14 @@ static inline void netClientRecordMove(struct netclient *cl, const struct player
move->ucmd |= UCMD_SQUAT;
}
if (pl->gunctrl.switchtoweaponnum >= 0) {
if (pl->gunctrl.switchtoweaponnum >= 0 && !pl->gunctrl.throwing) {
move->ucmd |= UCMD_SELECT;
move->weaponnum = pl->gunctrl.switchtoweaponnum;
} else {
move->weaponnum = -1;
}
if (pl->gunctrl.dualwielding) {
if (pl->gunctrl.dualwielding && !pl->gunctrl.throwing) {
move->ucmd |= UCMD_SELECT_DUAL;
if ((move->ucmd ^ cl->outmove[1].ucmd) & UCMD_SELECT_DUAL) {
move->ucmd |= UCMD_SELECT;
+40 -4
View File
@@ -9,13 +9,17 @@
#include "game/mainmenu.h"
#include "game/menu.h"
#include "game/gamefile.h"
#include "game/filelist.h"
#include "video.h"
#include "input.h"
#include "config.h"
#include "mpsetups.h"
#include "net/net.h"
extern MenuItemHandlerResult menuhandlerMainMenuCombatSimulator(s32 operation, struct menuitem *item, union handlerdata *data);
extern MenuItemHandlerResult menuhandlerMpAdvancedSetup(s32 operation, struct menuitem *item, union handlerdata *data);
extern struct menuitem g_MpPlayerSetup234MenuItems[];
extern struct menudialogdef g_NetJoinPlayerSetupMenuDialog;
static s32 g_NetMenuMaxPlayers = NET_MAX_CLIENTS;
static s32 g_NetMenuPort = NET_DEFAULT_PORT;
@@ -60,6 +64,9 @@ MenuItemHandlerResult menuhandlerHostStart(s32 operation, struct menuitem *item,
{
if (operation == MENUOP_SET) {
if (netStartServer(g_NetMenuPort, g_NetMenuMaxPlayers) == 0) {
// load the setup file when entering the Combat Simulator
mpsetupCopyAllFromPak();
mpsetupLoadCurrentFile();
menuhandlerMainMenuCombatSimulator(MENUOP_SET, NULL, NULL);
menuhandlerMpAdvancedSetup(MENUOP_SET, NULL, NULL);
}
@@ -117,7 +124,7 @@ struct menudialogdef g_NetHostMenuDialog = {
(uintptr_t)"Host Network Game",
g_NetHostMenuItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT,
MENUDIALOGFLAG_LITERAL_TEXT | MENUDIALOGFLAG_STARTSELECTS,
NULL,
};
@@ -236,7 +243,7 @@ static MenuItemHandlerResult menuhandlerEnterJoinAddress(s32 operation, struct m
return 0;
}
if (inputTextHandler(g_NetJoinAddr, NET_MAX_ADDR, &g_NetJoinAddrPtr) < 0) {
if (inputTextHandler(g_NetJoinAddr, NET_MAX_ADDR, &g_NetJoinAddrPtr, false) < 0) {
// escape has been pressed, stop editing
inputStopTextInput();
menuPopDialog();
@@ -269,6 +276,18 @@ MenuItemHandlerResult menuhandlerJoinStart(s32 operation, struct menuitem *item,
return 0;
}
static MenuItemHandlerResult menuhandlerJoinPlayerSetup(s32 operation, struct menuitem *item, union handlerdata *data)
{
if (operation == MENUOP_SET) {
// load MP player file
filelistCreate(0, FILETYPE_MPPLAYER);
filelistsTick();
menuPushDialog(&g_NetJoinPlayerSetupMenuDialog);
}
return 0;
}
struct menuitem g_NetJoinMenuItems[] = {
{
MENUITEMTYPE_SELECTABLE,
@@ -278,6 +297,14 @@ struct menuitem g_NetJoinMenuItems[] = {
(uintptr_t)&menutextJoinAddress,
menuhandlerJoinAddress,
},
{
MENUITEMTYPE_SELECTABLE,
0,
0,
L_MPMENU_028, // "Player Setup"
0,
menuhandlerJoinPlayerSetup,
},
{
MENUITEMTYPE_SELECTABLE,
0,
@@ -310,7 +337,7 @@ struct menudialogdef g_NetJoinMenuDialog = {
(uintptr_t)"Join Network Game",
g_NetJoinMenuItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT | MENUDIALOGFLAG_STARTSELECTS | MENUDIALOGFLAG_IGNOREBACK,
MENUDIALOGFLAG_LITERAL_TEXT | MENUDIALOGFLAG_STARTSELECTS,
NULL,
};
@@ -381,6 +408,15 @@ struct menudialogdef g_NetMenuDialog = {
(uintptr_t)"Network Game",
g_NetMenuItems,
NULL,
MENUDIALOGFLAG_MPLOCKABLE | MENUDIALOGFLAG_LITERAL_TEXT,
MENUDIALOGFLAG_MPLOCKABLE | MENUDIALOGFLAG_LITERAL_TEXT | MENUDIALOGFLAG_STARTSELECTS,
NULL,
};
struct menudialogdef g_NetJoinPlayerSetupMenuDialog = {
MENUDIALOGTYPE_DEFAULT,
L_MPMENU_028, // "Player Setup"
g_MpPlayerSetup234MenuItems,
NULL,
MENUDIALOGFLAG_DROPOUTONCLOSE | MENUDIALOGFLAG_STARTSELECTS,
NULL,
};
+25 -10
View File
@@ -31,6 +31,20 @@
/* utils */
static inline u32 netbufReadHidden(struct netbuf *buf)
{
u32 hidden = netbufReadU32(buf);
// swap owner player numbers to match server
const u8 ownerclid = (hidden & 0xf0000000) >> 28;
if (ownerclid < NET_MAX_CLIENTS) {
const u8 ownerplayernum = g_NetClients[ownerclid].playernum;
hidden = (hidden & 0x0fffffff) | (ownerplayernum << 28);
}
return hidden;
}
static inline u32 netbufWriteRooms(struct netbuf *buf, const s16 *rooms, const s32 num)
{
for (s32 i = 0; i < num; ++i) {
@@ -930,6 +944,7 @@ u32 netmsgSvcPropSpawnWrite(struct netbuf *dst, struct prop *prop)
const u8 ownerplayernum = (prop->obj->hidden & 0xf0000000) >> 28;
netbufWriteU8(dst, autogun->ammoquantity);
netbufWriteU8(dst, autogun->firecount);
netbufWriteU8(dst, autogun->targetteam);
netbufWriteU8(dst, g_Vars.players[ownerplayernum]->client->id);
}
break;
@@ -1049,9 +1064,13 @@ u32 netmsgSvcPropSpawnRead(struct netbuf *src, struct netclient *srccl)
// thrown laptop?
const u8 ammocount = netbufReadU8(src);
const u8 firecount = netbufReadU8(src);
const u8 targetteam = netbufReadU8(src);
const u8 clid = netbufReadU8(src);
struct chrdata *ownerchr = g_NetClients[clid].player->prop->chr;
struct autogunobj *obj = laptopDeploy(modelnum, NULL, ownerchr);
obj->ammoquantity = ammocount;
obj->firecount = firecount;
obj->targetteam = targetteam;
prop = obj->base.prop;
}
}
@@ -1086,7 +1105,7 @@ u32 netmsgSvcPropSpawnRead(struct netbuf *src, struct netclient *srccl)
const u32 flags = netbufReadU32(src);
const u32 flags2 = netbufReadU32(src);
const u32 flags3 = netbufReadU32(src);
u32 hidden = netbufReadU32(src);
const u32 hidden = netbufReadHidden(src);
const u8 hidden2 = netbufReadU8(src);
const u16 extrascale = netbufReadU16(src);
const s16 pad = netbufReadS16(src);
@@ -1115,15 +1134,11 @@ u32 netmsgSvcPropSpawnRead(struct netbuf *src, struct netclient *srccl)
prop->obj->projectile->powerlimit240 = TICKS(1200);
prop->obj->projectile->smoketimer240 = TICKS(24);
}
if (type == PROPTYPE_WEAPON && (prop->obj->projectile->flags & PROJECTILEFLAG_00000002)) {
if ((type == PROPTYPE_WEAPON && (prop->obj->projectile->flags & PROJECTILEFLAG_00000002)) || objtype == OBJTYPE_AUTOGUN) {
// this is a thrown projectile, play throw sound
psCreate(NULL, prop, SFX_THROW, -1, -1, 0, 0, PSTYPE_NONE, NULL, -1, NULL, -1, -1, -1, -1);
}
}
// swap owner player numbers to match server
u8 ownerplayernum = (hidden & 0xf0000000) >> 28;
ownerplayernum = g_NetClients[ownerplayernum].playernum;
hidden = (hidden & 0x0fffffff) | (ownerplayernum << 28);
prop->obj->flags = flags;
prop->obj->flags2 = flags2;
prop->obj->flags3 = flags3;
@@ -1155,7 +1170,7 @@ u32 netmsgSvcPropDamageWrite(struct netbuf *dst, struct prop *prop, f32 damage,
netbufWriteF32(dst, damage);
netbufWriteS8(dst, weaponnum);
netbufWriteS8(dst, playernum);
netbufWriteU32(dst, prop->obj->hidden);
netbufWriteU32(dst, prop->obj->hidden & ~(OBJHFLAG_PROJECTILE | OBJHFLAG_EMBEDDED));
return dst->error;
}
@@ -1167,13 +1182,13 @@ u32 netmsgSvcPropDamageRead(struct netbuf *src, struct netclient *srccl)
const f32 damage = netbufReadF32(src);
const s8 weaponnum = netbufReadS8(src);
const s8 playernum = netbufReadS8(src);
const u32 hidden = netbufReadU32(src);
const u32 hidden = netbufReadHidden(src);
if (srccl->state < CLSTATE_GAME) {
return src->error;
}
if (prop && prop->obj && prop->type != PROPTYPE_PLAYER && prop->type != PROPTYPE_CHR && !src->error) {
prop->obj->damage = damagepre;
prop->obj->hidden = hidden;
prop->obj->hidden = hidden | (prop->obj->hidden & (OBJHFLAG_PROJECTILE | OBJHFLAG_EMBEDDED));
objDamage(prop->obj, -damage, &pos, weaponnum, playernum);
}
return src->error;
@@ -1284,7 +1299,7 @@ u32 netmsgSvcPropDoorRead(struct netbuf *src, struct netclient *srccl)
const u8 clid = netbufReadU8(src);
const s8 doormode = netbufReadS8(src);
const u32 flags = netbufReadU32(src);
const u32 hidden = netbufReadU32(src);
const u32 hidden = netbufReadHidden(src);
struct netclient *actcl = (clid == NET_NULL_CLIENT) ? NULL : &g_NetClients[clid];
+378 -39
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;
}
@@ -142,15 +171,17 @@ static MenuItemHandlerResult menuhandlerMouseSpeedX(s32 operation, struct menuit
if (x < 0.f) {
data->slider.value = 0;
} else if (x > 10.f) {
data->slider.value = 100;
data->slider.value = 1000;
} 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);
}
return 0;
@@ -166,15 +197,17 @@ static MenuItemHandlerResult menuhandlerMouseSpeedY(s32 operation, struct menuit
if (y < 0.f) {
data->slider.value = 0;
} else if (y > 10.f) {
data->slider.value = 100;
data->slider.value = 1000;
} 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);
}
return 0;
@@ -187,14 +220,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 +242,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 +264,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 +296,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 +325,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Mouse Speed X",
100,
1000,
menuhandlerMouseSpeedX,
},
{
@@ -286,7 +333,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Mouse Speed Y",
100,
1000,
menuhandlerMouseSpeedY,
},
{
@@ -294,7 +341,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Crosshair Speed X",
100,
1000,
menuhandlerMouseAimSpeedX,
},
{
@@ -302,7 +349,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Crosshair Speed Y",
100,
1000,
menuhandlerMouseAimSpeedY,
},
{
@@ -310,7 +357,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
(uintptr_t)"Radial Menu Speed",
100,
1000,
menuhandlerRadialMenuSpeed,
},
{
@@ -551,8 +598,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 +701,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 +903,25 @@ 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 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 +935,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[] = {
@@ -775,25 +1006,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,
@@ -810,9 +1105,17 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
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 +1125,14 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
0,
menuhandlerCenterHUD,
},
{
MENUITEMTYPE_CHECKBOX,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"GE64-style Muzzle Flashes",
0,
menuhandlerGeMuzzleFlashes,
},
{
MENUITEMTYPE_SLIDER,
0,
@@ -908,6 +1219,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 +1270,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;
@@ -1211,6 +1538,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 +1648,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 +1687,8 @@ struct menuitem g_ExtendedBindsMenuItems[] = {
DEFINE_MENU_BIND(),
DEFINE_MENU_BIND(),
DEFINE_MENU_BIND(),
DEFINE_MENU_BIND(),
DEFINE_MENU_BIND(),
{
MENUITEMTYPE_SEPARATOR,
0,
+4 -2
View File
@@ -228,6 +228,8 @@ void mainInit(void)
joyInit();
joyReset();
var8005d9b0 = rmonIsDisabled();
g_Is4Mb = (osGetMemSize() <= 0x400000);
g_VmShowStats = 0;
@@ -260,7 +262,7 @@ void mainInit(void)
frametimeInit();
profileInit();
smokesInit();
mpInit();
mpInit(true);
pheadInit();
paksInit();
pheadInit2();
@@ -579,7 +581,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;
}
+107
View File
@@ -0,0 +1,107 @@
#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);
#if MAX_PLAYERS > 4
// make space for the extra players
cfg->setup.chrslots = (cfg->setup.chrslots & 0x000f) | ((cfg->setup.chrslots & 0x0ff0) << 4);
#endif
// 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;
const char *g_RomName = ROMDATA_ROM_NAME;
@@ -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
@@ -41,7 +41,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
@@ -300,6 +300,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);
+273 -24
View File
@@ -6,36 +6,63 @@
#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 f64 vidLastRenderTime;
static s32 vidNumModes = 1;
static displaymode vidModeDefault;
static displaymode *vidModes = &vidModeDefault;
static s32 texFilter = FILTER_LINEAR;
static s32 texFilter2D = true;
static s32 texDetail = true;
static s32 texDetail = false;
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);
s32 videoInit(void)
{
@@ -61,23 +88,18 @@ 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);
initDone = true;
return 0;
@@ -89,6 +111,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 +133,35 @@ void videoEndFrame(void)
gfx_end_frame();
endTime = wmAPI->get_time();
++frames;
++framesPerSec;
++fpsNumFrames;
const f64 flipTime = wmAPI->get_time();
accumDelta += flipTime - endTime;
endTime = flipTime;
vidLastRenderTime = endTime - startTime;
if (endTime >= fpsTime) {
char tmp[128];
snprintf(tmp, sizeof(tmp), "fps %3u frt %lf frm %u", framesPerSec, endTime - startTime, frames);
vidAvgFPS = fpsNumFrames ? ((f64)fpsNumFrames / accumDelta) : 0.f;
fpsNumFrames = 0;
accumDelta = 0.0;
snprintf(tmp, sizeof(tmp), "fps %4.1f frt %lf frm %u", vidAvgFPS, vidLastRenderTime, frames);
wmAPI->set_window_title(tmp);
framesPerSec = 0;
fpsTime = endTime + 1.0;
fpsTime = endTime + vidDisplayFPSInterval;
}
}
f64 videoGetLastRenderTime(void)
{
return vidLastRenderTime;
}
f32 videoGetAverageFPS(void)
{
return vidAvgFPS;
}
void videoClearScreen(void)
{
videoStartFrame();
@@ -165,19 +206,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;
@@ -203,7 +384,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 +408,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)
@@ -246,6 +460,33 @@ 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);
@@ -282,6 +523,11 @@ void videoFreeCachedTexture(const void *texptr)
gfx_texture_cache_delete(texptr);
}
void videoShutdown(void)
{
free(vidModes);
}
PD_CONSTRUCTOR static void videoConfigInit(void)
{
configRegisterInt("Video.DefaultFullscreen", &vidFullscreen, 0, 1);
@@ -289,10 +535,13 @@ 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);
+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;
+22 -15
View File
@@ -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
@@ -763,7 +764,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 +1469,7 @@ void bgReset(s32 stagenum)
u32 section2compsize;
u32 section2start;
u32 section1compsize;
u32 scratch;
uintptr_t scratch;
var8007fc0c = 8;
@@ -1509,6 +1510,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 +1535,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 +1604,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 +1612,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 +2004,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 +2822,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 +2863,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 +2944,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 +3647,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 +4250,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;
+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++) {
+66 -68
View File
@@ -54,6 +54,7 @@
#include "data.h"
#include "types.h"
#ifndef PLATFORM_N64
#include "platform.h"
#include "game/stagetable.h"
#include "video.h"
#include "net/net.h"
@@ -167,8 +168,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,
@@ -892,7 +898,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) {
@@ -3796,17 +3802,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;
@@ -3828,7 +3834,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");
@@ -3846,6 +3852,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");
@@ -3856,7 +3865,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;
@@ -3927,7 +3936,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);
@@ -3940,7 +3949,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;
@@ -4089,8 +4098,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();
@@ -4117,8 +4126,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();
@@ -4159,8 +4168,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;
}
@@ -4186,18 +4195,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;
@@ -6465,7 +6474,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;
@@ -6522,7 +6531,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;
@@ -6539,11 +6548,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;
@@ -6551,36 +6560,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;
@@ -6589,12 +6598,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;
}
@@ -6618,7 +6627,7 @@ s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, s32 *
}
*ptr = 6;
len += 4;
len += sizeof(uintptr_t);
return len;
}
@@ -7211,7 +7220,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);
@@ -10983,7 +10992,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
@@ -11049,7 +11057,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.
@@ -11224,17 +11232,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);
@@ -11266,8 +11264,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) {
@@ -11346,8 +11344,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;
@@ -11411,8 +11409,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) {
@@ -11485,7 +11483,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;
@@ -11563,8 +11561,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;
@@ -11587,7 +11585,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)];
@@ -11662,8 +11660,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;
+25 -9
View File
@@ -978,6 +978,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
@@ -1099,7 +1105,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()) {
@@ -1430,10 +1438,9 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
aimoffhist[i] = !aimonhist[i];
}
#ifdef AVOID_UB
if (numsamples)
#endif
g_Vars.currentplayer->insightaimmode = aimonhist[numsamples - 1];
if (numsamples > 0) {
g_Vars.currentplayer->insightaimmode = aimonhist[numsamples - 1];
}
}
if (!lvIsPaused()) {
@@ -1774,6 +1781,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;
@@ -1815,6 +1823,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
@@ -1996,7 +2008,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;
}
@@ -2004,7 +2018,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 ?
@@ -2390,8 +2404,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);
@@ -2684,7 +2700,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
@@ -299,6 +299,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;
@@ -1132,7 +1173,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);
}
}
@@ -1230,6 +1271,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) {
+50 -42
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;
@@ -264,10 +264,18 @@ void botSpawn(struct chrdata *chr, u8 respawning)
#ifndef PLATFORM_N64
if ((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 +1417,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 +1559,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 +1754,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 +1892,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 +1904,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 +1928,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 +1939,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 +1952,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 +2407,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 +2539,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 +2547,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 +2555,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 +2571,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 +2587,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 +2607,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 +2616,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 +2627,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 +2724,7 @@ void botTickUnpaused(struct chrdata *chr)
s32 index;
s32 i;
index = random() % numtokens;
index = rngRandom() % numtokens;
i = (index + 1) % numtokens;
@@ -2744,7 +2752,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 +2770,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 +2860,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 +2891,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 +2919,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 +2944,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 +2962,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 +3095,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 +3435,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
@@ -406,6 +406,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 },
@@ -427,6 +429,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;
@@ -693,6 +696,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)
+20 -20
View File
@@ -1216,7 +1216,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;
@@ -1283,7 +1283,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;
@@ -1522,7 +1522,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);
}
}
@@ -3683,7 +3683,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;
@@ -3712,7 +3712,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;
@@ -3868,13 +3868,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;
}
@@ -3997,7 +3997,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;
@@ -4028,13 +4028,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;
}
@@ -4170,13 +4170,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;
}
@@ -4218,7 +4218,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;
@@ -4312,7 +4312,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;
@@ -4365,13 +4365,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;
}
@@ -4718,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,
@@ -4754,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,
@@ -5201,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) {
@@ -6505,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
@@ -1683,7 +1683,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);
@@ -1691,7 +1691,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) {
@@ -1712,7 +1712,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;
@@ -1754,7 +1754,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;
@@ -1779,7 +1779,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;
@@ -1832,7 +1832,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) {
@@ -1865,7 +1865,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);
@@ -1888,7 +1888,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) {
@@ -1937,17 +1937,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));
@@ -2018,7 +2018,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) {
@@ -2031,7 +2031,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);
}
@@ -2065,14 +2065,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;
}
}
@@ -2130,7 +2130,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)) {
@@ -2171,7 +2171,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;
@@ -2241,9 +2241,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;
@@ -2311,9 +2311,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;
@@ -2372,8 +2372,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;
}
@@ -2473,14 +2473,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];
@@ -2545,10 +2545,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 {
@@ -2576,14 +2576,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];
@@ -2637,7 +2637,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];
@@ -2658,10 +2658,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;
}
}
@@ -2836,7 +2836,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];
}
@@ -2889,7 +2889,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];
@@ -2911,13 +2911,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;
}
}
@@ -3127,8 +3127,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;
@@ -3174,7 +3174,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);
@@ -3198,7 +3198,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;
@@ -3220,7 +3220,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;
@@ -3243,7 +3243,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;
@@ -3269,10 +3269,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) {
@@ -3330,7 +3330,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;
@@ -3345,7 +3345,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];
@@ -3462,7 +3462,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 },
@@ -3482,7 +3482,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);
@@ -3515,7 +3515,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];
@@ -3658,7 +3658,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]];
@@ -3682,8 +3682,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;
@@ -3866,7 +3866,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)) {
@@ -3882,7 +3882,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)) {
@@ -3895,7 +3895,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)) {
@@ -3982,7 +3982,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[] = {
@@ -4009,21 +4009,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,
@@ -4389,8 +4389,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
@@ -4570,13 +4571,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
}
}
@@ -4649,7 +4650,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);
}
}
@@ -5908,7 +5909,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;
@@ -5995,7 +5996,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;
@@ -6030,7 +6031,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 {
@@ -6039,7 +6040,7 @@ void chrGoPosChooseAnimation(struct chrdata *chr)
sp60 = 24;
}
} else {
if (random() % 2) {
if (rngRandom() % 2) {
anim = ANIM_005E;
} else {
anim = ANIM_005A;
@@ -6080,14 +6081,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;
@@ -6121,9 +6122,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;
@@ -6211,7 +6212,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) {
@@ -6285,7 +6286,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)) {
@@ -6303,12 +6304,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) {
@@ -6394,7 +6395,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;
@@ -6760,7 +6761,7 @@ bool chrCheckCanSeeTarget(struct chrdata *chr)
}
iVar8 = chrGetPercentageOfSlowness(chr, iVar8) + 1;
result = random() % iVar8 == 0;
result = rngRandom() % iVar8 == 0;
}
}
@@ -6852,7 +6853,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);
@@ -6890,7 +6891,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);
@@ -6919,7 +6920,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;
@@ -7018,7 +7019,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);
@@ -7055,7 +7056,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;
}
@@ -7551,7 +7552,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++) {
@@ -7652,7 +7653,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);
@@ -7846,7 +7847,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;
@@ -7857,7 +7858,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;
@@ -7873,11 +7874,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]) {
@@ -8054,7 +8055,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) {
@@ -8063,7 +8064,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) {
@@ -8082,7 +8083,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) {
@@ -8136,17 +8137,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;
}
}
@@ -8211,7 +8212,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) {
@@ -8243,7 +8244,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);
}
}
@@ -8452,7 +8453,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;
}
@@ -8461,9 +8462,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)) {
@@ -8570,7 +8571,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;
@@ -9164,7 +9165,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);
@@ -10097,7 +10098,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;
}
}
@@ -10134,7 +10135,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;
@@ -10392,10 +10393,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);
@@ -10901,13 +10902,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;
@@ -10930,7 +10931,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;
@@ -11223,7 +11224,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;
@@ -13268,7 +13269,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);
@@ -13656,7 +13657,7 @@ void chraTickBg(void)
spawnslen++;
if (spawnslen >= 10) {
writeindex = random() % spawnslen;
writeindex = rngRandom() % spawnslen;
chrFadeCorpse(spawns[writeindex]);
spawns[writeindex] = spawns[spawnslen - 1];
spawnslen--;
@@ -13747,7 +13748,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--;
@@ -13762,7 +13763,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]);
@@ -15256,7 +15257,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
@@ -15605,7 +15606,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;
@@ -16315,7 +16316,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;
}
@@ -16323,7 +16324,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);
}
+34 -30
View File
@@ -1100,7 +1100,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;
@@ -1114,7 +1114,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;
@@ -1131,7 +1131,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;
@@ -2118,14 +2118,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;
@@ -5948,7 +5952,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) {
@@ -6925,7 +6929,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) {
@@ -6975,7 +6979,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);
@@ -7000,7 +7004,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];
@@ -7627,8 +7631,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
@@ -8768,17 +8772,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);
}
@@ -8819,7 +8823,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);
@@ -8830,7 +8834,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);
}
@@ -8979,9 +8983,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];
@@ -8996,11 +9000,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
@@ -9160,7 +9164,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
@@ -9610,20 +9614,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;
+3 -3
View File
@@ -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);
}
}
@@ -1199,7 +1199,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 {
+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);
}
Loaded 100 of 218 files, more files were not shown because too many files have changed in this diff. Show more