Attempting to update to the latest version of the port
This commit is contained in:
parent
982af95fc2
commit
1c474865a9
2
Makefile
2
Makefile
|
|
@ -462,7 +462,7 @@ ifeq ($(ENABLE_OPENGL),1)
|
|||
GFX_LDFLAGS :=
|
||||
ifeq ($(TARGET_WINDOWS),1)
|
||||
GFX_CFLAGS += $(shell sdl2-config --cflags) -DGLEW_STATIC
|
||||
GFX_LDFLAGS += $(shell sdl2-config --libs) -lglew32 -lopengl32 -lwinmm -limm32 -lversion -loleaut32 -lsetupapi
|
||||
GFX_LDFLAGS += $(shell sdl2-config --libs) -Llib -lpthread -lglew32 -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -static
|
||||
endif
|
||||
ifeq ($(TARGET_LINUX),1)
|
||||
GFX_CFLAGS += $(shell sdl2-config --cflags)
|
||||
|
|
|
|||
194
README.md
194
README.md
|
|
@ -1,9 +1,6 @@
|
|||
# Super Mario 64 Port
|
||||
# Super Mario 64 Port Thingy
|
||||
|
||||
- This repo contains a full decompilation of Super Mario 64 (J), (U), and (E) with minor exceptions in the audio subsystem.
|
||||
- Naming and documentation of the source code and data structures are in progress.
|
||||
- Efforts to decompile the Shindou ROM steadily advance toward a matching build.
|
||||
- Beyond Nintendo 64, it can also target Linux and Windows natively.
|
||||
Stuff from my earlier Super Mario 64 ABE ported to the PC port with a ton of new features. This README file is going to be replaced eventually with something more proper.
|
||||
|
||||
This repo does not include all assets necessary for compiling the game.
|
||||
A prior copy of the game is required to extract the assets.
|
||||
|
|
@ -13,9 +10,9 @@ A prior copy of the game is required to extract the assets.
|
|||
### Linux
|
||||
|
||||
1. Install prerequisites (Ubuntu): `sudo apt install -y git build-essential pkg-config libusb-1.0-0-dev libsdl2-dev`.
|
||||
2. Clone the repo: `git clone https://github.com/sm64-port/sm64-port.git`.
|
||||
3. Place a Super Mario 64 ROM called `baserom.<VERSION>.z64` into the project folder for asset extraction, where `VERSION` can be `us`, `jp`, or `eu`.
|
||||
4. Run `make` to build. Qualify the version through `make VERSION=<VERSION>`. Add `-j4` to improve build speed (hardware dependent based on the amount of CPU cores available).
|
||||
2. Clone the repo: `git clone https://github.com/MorsGames/sm64-port.git`.
|
||||
3. Place a Super Mario 64 ROM called `baserom.<VERSION>.z64` into the project folder for asset extraction. For `VERSION` only `us` is properly supported.
|
||||
4. Run `make` to build. Add `-j4` to improve build speed (hardware dependent based on the amount of CPU cores available).
|
||||
5. The executable binary will be located at `build/<VERSION>_pc/sm64.<VERSION>.f3dex2e`.
|
||||
|
||||
### Windows
|
||||
|
|
@ -25,182 +22,7 @@ A prior copy of the game is required to extract the assets.
|
|||
a. 64-bit: Launch "MSYS2 MinGW 64-bit" and install: `pacman -S git make python3 mingw-w64-x86_64-gcc`
|
||||
b. 32-bit (will also work on 64-bit machines): Launch "MSYS2 MinGW 32-bit" and install: `pacman -S git make python3 mingw-w64-i686-gcc`
|
||||
* Do **NOT** install `gcc`.
|
||||
3. Clone the repo: `git clone https://github.com/sm64-port/sm64-port.git` and enter it `cd sm64-port`.
|
||||
4. Place a *Super Mario 64* ROM called `baserom.<VERSION>.z64` into the project folder for asset extraction, where `VERSION` can be `us`, `jp`, or `eu`.
|
||||
5. Run `make` to build. Qualify the version through `make VERSION=<VERSION>`. Add `-j4` to improve build speed (hardware dependent based on the amount of CPU cores available).
|
||||
3. Clone the repo: `git clone https://github.com/MorsGames/sm64-port.git` and enter it `cd sm64-port`.
|
||||
4. Place a *Super Mario 64* ROM called `baserom.<VERSION>.z64` into the project folder for asset extraction. For `VERSION` only `us` is properly supported.
|
||||
5. Run `make` to build. Add `-j4` to improve build speed (hardware dependent based on the amount of CPU cores available).
|
||||
6. The executable binary will be located at `build/<VERSION>_pc/sm64.<VERSION>.f3dex2e.exe`.
|
||||
|
||||
### Debugging
|
||||
|
||||
The code can be debugged using `gdb`. On Linux install the `gdb` package and execute `gdb <executable>`. On MSYS2 install by executing `pacman -S winpty gdb` and execute `winpty gdb <executable>`. The `winpty` program makes sure the keyboard works correctly in the terminal. In the Makefile, make sure you compile the sources using `-g` rather than `-O2` to include debugging symbols. See any online tutorial for how to use gdb.
|
||||
|
||||
## Quick Start ROM building (for Ubuntu)
|
||||
|
||||
1. Install prerequisites: `sudo apt install -y build-essential git binutils-mips-linux-gnu python3`.
|
||||
2. Clone the repo from within Linux: `git clone https://github.com/n64decomp/sm64.git`.
|
||||
3. Place a Super Mario 64 ROM called `baserom.<VERSION>.z64` into the project folder for asset extraction, where `VERSION` can be `us`, `jp`, or `eu`.
|
||||
4. Run `make` to build. Qualify the version through `make TARGET_N64=1 VERSION=<VERSION>`. Add `-j4` to improve build speed (hardware dependent based on the amount of CPU cores available).
|
||||
|
||||
Ensure the repo path length does not exceed 255 characters. Long path names result in build errors.
|
||||
|
||||
## Installation for ROM building
|
||||
|
||||
### Windows
|
||||
|
||||
Install WSL and a distro of your choice following
|
||||
[Windows Subsystem for Linux Installation Guide for Windows 10.](https://docs.microsoft.com/en-us/windows/wsl/install-win10)
|
||||
We recommend either Debian or Ubuntu 18.04 Linux distributions under WSL.
|
||||
Note: WSL1 does not currently support Ubuntu 20.04.
|
||||
|
||||
Next, clone the SM64 repo from within the Linux shell:
|
||||
`git clone https://github.com/n64decomp/sm64.git`
|
||||
|
||||
Then continue following the directions in the [Linux](#linux) installation section below.
|
||||
|
||||
### Linux
|
||||
|
||||
There are 3 steps to set up a working build.
|
||||
|
||||
#### Step 1: Install dependencies
|
||||
|
||||
The build system has the following package requirements:
|
||||
* ``binutils-mips``
|
||||
* ``python3 >= 3.6``
|
||||
* ``qemu-irix`` (When building without GCC)
|
||||
|
||||
Dependency installation instructions for common Linux distros are provided below:
|
||||
|
||||
##### Debian / Ubuntu
|
||||
To install build dependencies:
|
||||
```
|
||||
sudo apt install -y build-essential git binutils-mips-linux-gnu python3
|
||||
```
|
||||
|
||||
Download latest package from [qemu-irix Releases.](https://github.com/n64decomp/qemu-irix/releases)
|
||||
|
||||
Install this package with:
|
||||
```
|
||||
sudo dpkg -i qemu-irix-2.11.0-2169-g32ab296eef_amd64.deb
|
||||
```
|
||||
|
||||
##### Arch Linux
|
||||
To install build dependencies:
|
||||
```
|
||||
sudo pacman -S base-devel python
|
||||
```
|
||||
Install the following AUR packages:
|
||||
* [mips64-elf-binutils](https://aur.archlinux.org/packages/mips64-elf-binutils) (AUR)
|
||||
* [qemu-irix-git](https://aur.archlinux.org/packages/qemu-irix-git) (AUR)
|
||||
|
||||
|
||||
##### Other Linux distributions
|
||||
|
||||
Most modern Linux distributions should have equivalent packages to the other two listed above.
|
||||
You may have to use a different version of GNU binutils. Listed below are fully compatible binutils
|
||||
distributions with support in the makefile, and examples of distros that offer them:
|
||||
|
||||
* `mips64-elf-` (Arch AUR)
|
||||
* `mips-linux-gnu-` (Ubuntu and other Debian-based distros)
|
||||
* `mips64-linux-gnu-` (RHEL/CentOS/Fedora)
|
||||
|
||||
You may also use [Docker](#docker-installation) to handle installing an image with minimal dependencies.
|
||||
|
||||
#### Step 2: Copy baserom(s) for asset extraction
|
||||
|
||||
For each version (jp/us/eu) for which you want to build a ROM, put an existing ROM at
|
||||
`./baserom.<VERSION>.z64` for asset extraction.
|
||||
|
||||
##### Step 3: Build the ROM
|
||||
|
||||
Run `make` to build the ROM (defaults to `VERSION=us`).
|
||||
Other examples:
|
||||
```
|
||||
make VERSION=jp -j4 # build (J) version instead with 4 jobs
|
||||
make VERSION=eu COMPARE=0 # build (EU) version but do not compare ROM hashes
|
||||
```
|
||||
|
||||
Resulting artifacts can be found in the `build` directory.
|
||||
|
||||
The full list of configurable variables are listed below, with the default being the first listed:
|
||||
|
||||
* ``VERSION``: ``us``, ``jp``, ``eu``, ``sh`` (WIP)
|
||||
* ``GRUCODE``: ``f3d_old``, ``f3d_new``, ``f3dex``, ``f3dex2``, ``f3dzex``
|
||||
* ``COMPARE``: ``1`` (compare ROM hash), ``0`` (do not compare ROM hash)
|
||||
* ``NON_MATCHING``: Use functionally equivalent C implementations for non-matchings. Also will avoid instances of undefined behavior.
|
||||
* ``CROSS``: Cross-compiler tool prefix (Example: ``mips64-elf-``).
|
||||
* ``QEMU_IRIX``: Path to a ``qemu-irix`` binary.
|
||||
* ``TARGET_N64``: ``0`` If set to one, will build an N64 ROM. An unmodified repository will produce one of the following ROMs depending on what ``VERSION`` is set to:
|
||||
|
||||
* sm64.jp.z64 `sha1: 8a20a5c83d6ceb0f0506cfc9fa20d8f438cafe51`
|
||||
* sm64.us.z64 `sha1: 9bef1128717f958171a4afac3ed78ee2bb4e86ce`
|
||||
* sm64.eu.z64 `sha1: 4ac5721683d0e0b6bbb561b58a71740845dceea9`
|
||||
|
||||
|
||||
### macOS
|
||||
|
||||
Installing Docker is the recommended avenue for macOS users. This project does not support macOS natively due to lack of macOS host support.
|
||||
|
||||
### Docker Installation
|
||||
|
||||
#### Create Docker image
|
||||
|
||||
Create the docker image with `docker build -t sm64`.
|
||||
|
||||
#### Build
|
||||
|
||||
To build, mount the local filesystem into the Docker container and build the ROM with `docker run`.
|
||||
|
||||
##### macOS example for (U):
|
||||
```
|
||||
docker run --rm --mount type=bind,source="$(pwd)",destination=/sm64 sm64 make VERSION=us -j4
|
||||
```
|
||||
|
||||
##### Linux example for (U):
|
||||
For a Linux host, Docker needs to be instructed which user should own the output files:
|
||||
```
|
||||
docker run --rm --mount type=bind,source="$(pwd)",destination=/sm64 --user $UID:$UID sm64 make VERSION=us -j4
|
||||
```
|
||||
|
||||
Resulting artifacts can be found in the `build` directory.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
sm64
|
||||
├── actors: object behaviors, geo layout, and display lists
|
||||
├── asm: handwritten assembly code, rom header
|
||||
│ └── non_matchings: asm for non-matching sections
|
||||
├── assets: animation and demo data
|
||||
│ ├── anims: animation data
|
||||
│ └── demos: demo data
|
||||
├── bin: C files for ordering display lists and textures
|
||||
├── build: output directory
|
||||
├── data: behavior scripts, misc. data
|
||||
├── doxygen: documentation infrastructure
|
||||
├── enhancements: example source modifications
|
||||
├── include: header files
|
||||
├── levels: level scripts, geo layout, and display lists
|
||||
├── lib: SDK library code
|
||||
├── rsp: audio and Fast3D RSP assembly code
|
||||
├── sound: sequences, sound samples, and sound banks
|
||||
├── src: C source code for game
|
||||
│ ├── audio: audio code
|
||||
│ ├── buffers: stacks, heaps, and task buffers
|
||||
│ ├── engine: script processing engines and utils
|
||||
│ ├── game: behaviors and rest of game source
|
||||
│ ├── goddard: Mario intro screen
|
||||
│ ├── menu: title screen and file, act, and debug level selection menus
|
||||
│ └── pc: port code, audio and video renderer
|
||||
├── text: dialog, level names, act names
|
||||
├── textures: skybox and generic texture data
|
||||
└── tools: build tools
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Pull requests are welcome. For major changes, please open an issue first to
|
||||
discuss what you would like to change.
|
||||
|
||||
Run `clang-format` on your code to ensure it meets the project's coding standards.
|
||||
|
||||
Official Discord: https://discord.gg/7bcNTPK
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ typedef struct {
|
|||
u16 button;
|
||||
s8 stick_x; /* -80 <= stick_x <= 80 */
|
||||
s8 stick_y; /* -80 <= stick_y <= 80 */
|
||||
s8 stick2_x; /* -80 <= stick_x <= 80 */
|
||||
s8 stick2_y; /* -80 <= stick_y <= 80 */
|
||||
u8 errnum;
|
||||
} OSContPad;
|
||||
|
||||
|
|
|
|||
|
|
@ -172,6 +172,9 @@ enum DialogId {
|
|||
DIALOG_167,
|
||||
DIALOG_168,
|
||||
DIALOG_169,
|
||||
DIALOG_170,
|
||||
DIALOG_171,
|
||||
DIALOG_172,
|
||||
DIALOG_COUNT
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -296,6 +296,7 @@
|
|||
#define ACT_GETTING_BLOWN 0x010208B8 // (0x0B8 | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_THROWN_FORWARD 0x010208BD // (0x0BD | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_THROWN_BACKWARD 0x010208BE // (0x0BE | ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)
|
||||
#define ACT_WALL_SLIDE 0x000008BF // (0x0BF | ACT_FLAG_AIR) New addition!
|
||||
|
||||
// group 0x0C0: submerged actions
|
||||
#define ACT_WATER_IDLE 0x380022C0 // (0x0C0 | ACT_FLAG_STATIONARY | ACT_FLAG_SWIMMING | ACT_FLAG_PAUSE_EXIT | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT)
|
||||
|
|
|
|||
|
|
@ -140,6 +140,14 @@
|
|||
#define TEXT_FILE_MARIO_B _("MARIO B")
|
||||
#define TEXT_FILE_MARIO_C _("MARIO C")
|
||||
#define TEXT_FILE_MARIO_D _("MARIO D")
|
||||
#define TEXT_FILE_HARD_A _("HARD A")
|
||||
#define TEXT_FILE_HARD_B _("HARD B")
|
||||
#define TEXT_FILE_HARD_C _("HARD C")
|
||||
#define TEXT_FILE_HARD_D _("HARD D")
|
||||
#define TEXT_FILE_HARDCORE_A _("PERMADEATH A")
|
||||
#define TEXT_FILE_HARDCORE_B _("PERMADEATH B")
|
||||
#define TEXT_FILE_HARDCORE_C _("PERMADEATH C")
|
||||
#define TEXT_FILE_HARDCORE_D _("PERMADEATH D")
|
||||
|
||||
// Menu Options
|
||||
#define TEXT_SCORE _("SCORE")
|
||||
|
|
|
|||
|
|
@ -30,6 +30,11 @@ struct Controller
|
|||
/*0x12*/ u16 buttonPressed;
|
||||
/*0x14*/ OSContStatus *statusData;
|
||||
/*0x18*/ OSContPad *controllerData;
|
||||
/*0x00*/ s16 rawStick2X; //
|
||||
/*0x02*/ s16 rawStick2Y; //
|
||||
/*0x04*/ float stick2X; // [-64, 64] positive is right
|
||||
/*0x08*/ float stick2Y; // [-64, 64] positive is up
|
||||
/*0x0C*/ float stick2Mag; // distance from center [0, 64]
|
||||
#ifdef VERSION_SH
|
||||
/*0x1C*/ int port;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "make_const_nonconst.h"
|
||||
#include "levels/ending/header.h"
|
||||
#include "levels/intro/header.h"
|
||||
|
||||
const LevelScript level_ending_entry[] = {
|
||||
/*0*/ INIT_LEVEL(),
|
||||
|
|
@ -32,6 +33,8 @@ const LevelScript level_ending_entry[] = {
|
|||
/*14*/ SLEEP(/*frames*/ 120),
|
||||
/*15*/ CALL(/*arg*/ 0, /*func*/ lvl_play_the_end_screen_sound),
|
||||
// L1:
|
||||
/*17*/ SLEEP(/*frames*/ 1),
|
||||
/*18*/ JUMP(level_ending_entry + 17),
|
||||
/*17*/ CALL_LOOP(/*arg*/ 1, /*func*/ credits_wait_for_reset),
|
||||
/*18*/ TRANSITION(/*transType*/ WARP_TRANSITION_FADE_INTO_COLOR, /*time*/ 75, /*color*/ 0x00, 0x00, 0x00),
|
||||
/*19*/ SLEEP(/*frames*/ 240),
|
||||
/*20*/ EXECUTE(/*seg*/ 0x14, /*script*/ _introSegmentRomStart, /*scriptEnd*/ _introSegmentRomEnd, /*entry*/ level_intro_entry_2),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,38 +20,38 @@
|
|||
STUB_LEVEL( "", LEVEL_UNKNOWN_1, COURSE_NONE, 20000, 0x00, 0x00, 0x00, _, _)
|
||||
STUB_LEVEL( "", LEVEL_UNKNOWN_2, COURSE_NONE, 20000, 0x00, 0x00, 0x00, _, _)
|
||||
STUB_LEVEL( "", LEVEL_UNKNOWN_3, COURSE_NONE, 20000, 0x00, 0x00, 0x00, _, _)
|
||||
DEFINE_LEVEL("TERESA OBAKE", LEVEL_BBH, COURSE_BBH, bbh, spooky, 28000, 0x28, 0x28, 0x28, sDynBbh, sCamBBH)
|
||||
DEFINE_LEVEL("YYAMA1 % YSLD1", LEVEL_CCM, COURSE_CCM, ccm, snow, 17000, 0x10, 0x38, 0x38, _, sCamCCM)
|
||||
DEFINE_LEVEL("SELECT ROOM", LEVEL_CASTLE, COURSE_NONE, castle_inside, inside, 20000, 0x20, 0x20, 0x30, _, sCamCastle)
|
||||
DEFINE_LEVEL("HORROR DUNGEON", LEVEL_HMC, COURSE_HMC, hmc, cave, 16000, 0x28, 0x28, 0x28, sDynHmc, sCamHMC)
|
||||
DEFINE_LEVEL("SABAKU % PYRMD", LEVEL_SSL, COURSE_SSL, ssl, generic, 15000, 0x08, 0x30, 0x30, _, sCamSSL)
|
||||
DEFINE_LEVEL("BATTLE FIELD", LEVEL_BOB, COURSE_BOB, bob, generic, 15000, 0x08, 0x08, 0x08, _, _)
|
||||
DEFINE_LEVEL("YUKIYAMA2", LEVEL_SL, COURSE_SL, sl, snow, 14000, 0x10, 0x28, 0x28, _, sCamSL)
|
||||
DEFINE_LEVEL("POOL KAI", LEVEL_WDW, COURSE_WDW, wdw, grass, 17000, 0x10, 0x18, 0x18, sDynWdw, _)
|
||||
DEFINE_LEVEL("WTDG % TINBOTU", LEVEL_JRB, COURSE_JRB, jrb, water, 20000, 0x10, 0x18, 0x18, sDynJrb, _)
|
||||
DEFINE_LEVEL("BIG WORLD", LEVEL_THI, COURSE_THI, thi, grass, 20000, 0x0c, 0x0c, 0x20, _, sCamTHI)
|
||||
DEFINE_LEVEL("CLOCK TOWER", LEVEL_TTC, COURSE_TTC, ttc, machine, 18000, 0x18, 0x18, 0x18, _, _)
|
||||
DEFINE_LEVEL("RAINBOW CRUISE", LEVEL_RR, COURSE_RR, rr, sky, 20000, 0x20, 0x20, 0x20, _, sCamRR)
|
||||
DEFINE_LEVEL("MAIN MAP", LEVEL_CASTLE_GROUNDS, COURSE_NONE, castle_grounds, outside, 25000, 0x08, 0x08, 0x08, _, _)
|
||||
DEFINE_LEVEL("EXT1 YOKO SCRL", LEVEL_BITDW, COURSE_BITDW, bitdw, sky, 16000, 0x28, 0x28, 0x28, _, _)
|
||||
DEFINE_LEVEL("EXT7 HORI MINI", LEVEL_VCUTM, COURSE_VCUTM, vcutm, outside, 30000, 0x28, 0x28, 0x28, _, _)
|
||||
DEFINE_LEVEL("EXT2 TIKA LAVA", LEVEL_BITFS, COURSE_BITFS, bitfs, sky, 16000, 0x28, 0x28, 0x28, _, _)
|
||||
DEFINE_LEVEL("EXT9 SUISOU", LEVEL_SA, COURSE_SA, sa, inside, 20000, 0x10, 0x10, 0x10, _, _)
|
||||
DEFINE_LEVEL("EXT3 HEAVEN", LEVEL_BITS, COURSE_BITS, bits, sky, 16000, 0x28, 0x28, 0x28, _, _)
|
||||
DEFINE_LEVEL("FIREB1 % INVLC", LEVEL_LLL, COURSE_LLL, lll, fire, 22000, 0x08, 0x30, 0x30, _, _)
|
||||
DEFINE_LEVEL("WATER LAND", LEVEL_DDD, COURSE_DDD, ddd, water, 17000, 0x10, 0x20, 0x20, sDynDdd, _)
|
||||
DEFINE_LEVEL("MOUNTAIN", LEVEL_WF, COURSE_WF, wf, grass, 13000, 0x08, 0x08, 0x08, _, _)
|
||||
DEFINE_LEVEL("BIG BOOS HAUNT", LEVEL_BBH, COURSE_BBH, bbh, spooky, 28000, 0x28, 0x28, 0x28, sDynBbh, sCamBBH)
|
||||
DEFINE_LEVEL("CC MOUNTAIN", LEVEL_CCM, COURSE_CCM, ccm, snow, 17000, 0x10, 0x38, 0x38, _, sCamCCM)
|
||||
DEFINE_LEVEL("CASTLE INSIDE", LEVEL_CASTLE, COURSE_NONE, castle_inside, inside, 20000, 0x20, 0x20, 0x30, _, sCamCastle)
|
||||
DEFINE_LEVEL("HAY MAE CAE", LEVEL_HMC, COURSE_HMC, hmc, cave, 16000, 0x28, 0x28, 0x28, sDynHmc, sCamHMC)
|
||||
DEFINE_LEVEL("S SAND LAND", LEVEL_SSL, COURSE_SSL, ssl, generic, 15000, 0x08, 0x30, 0x30, _, sCamSSL)
|
||||
DEFINE_LEVEL("BO BATTLEFIELD", LEVEL_BOB, COURSE_BOB, bob, generic, 15000, 0x08, 0x08, 0x08, _, _)
|
||||
DEFINE_LEVEL("SNOWMANS LAND", LEVEL_SL, COURSE_SL, sl, snow, 14000, 0x10, 0x28, 0x28, _, sCamSL)
|
||||
DEFINE_LEVEL("WET DRY WORLD", LEVEL_WDW, COURSE_WDW, wdw, grass, 17000, 0x10, 0x18, 0x18, sDynWdw, _)
|
||||
DEFINE_LEVEL("OLLY ROGER BAY", LEVEL_JRB, COURSE_JRB, jrb, water, 20000, 0x10, 0x18, 0x18, sDynJrb, _)
|
||||
DEFINE_LEVEL("TH ISLAND", LEVEL_THI, COURSE_THI, thi, grass, 20000, 0x0c, 0x0c, 0x20, _, sCamTHI)
|
||||
DEFINE_LEVEL("TICK TOCK CLOCK", LEVEL_TTC, COURSE_TTC, ttc, machine, 18000, 0x18, 0x18, 0x18, _, _)
|
||||
DEFINE_LEVEL("RAINBOW RIDE", LEVEL_RR, COURSE_RR, rr, sky, 20000, 0x20, 0x20, 0x20, _, sCamRR)
|
||||
DEFINE_LEVEL("CASTLE GROUNDS", LEVEL_CASTLE_GROUNDS, COURSE_NONE, castle_grounds, outside, 25000, 0x08, 0x08, 0x08, _, _)
|
||||
DEFINE_LEVEL("B IN DARK WORLD", LEVEL_BITDW, COURSE_BITDW, bitdw, sky, 16000, 0x28, 0x28, 0x28, _, _)
|
||||
DEFINE_LEVEL("ANISH CAP", LEVEL_VCUTM, COURSE_VCUTM, vcutm, outside, 30000, 0x28, 0x28, 0x28, _, _)
|
||||
DEFINE_LEVEL("B IN FIRE SEA", LEVEL_BITFS, COURSE_BITFS, bitfs, sky, 16000, 0x28, 0x28, 0x28, _, _)
|
||||
DEFINE_LEVEL("SECRET AUARIUM", LEVEL_SA, COURSE_SA, sa, inside, 20000, 0x10, 0x10, 0x10, _, _)
|
||||
DEFINE_LEVEL("B IN THE SKY", LEVEL_BITS, COURSE_BITS, bits, sky, 16000, 0x28, 0x28, 0x28, _, _)
|
||||
DEFINE_LEVEL("LETHAL LAA LAND", LEVEL_LLL, COURSE_LLL, lll, fire, 22000, 0x08, 0x30, 0x30, _, _)
|
||||
DEFINE_LEVEL("DIRE DIRE DOCKS", LEVEL_DDD, COURSE_DDD, ddd, water, 17000, 0x10, 0x20, 0x20, sDynDdd, _)
|
||||
DEFINE_LEVEL("WHOMPS FORTRESS", LEVEL_WF, COURSE_WF, wf, grass, 13000, 0x08, 0x08, 0x08, _, _)
|
||||
DEFINE_LEVEL("ENDING", LEVEL_ENDING, COURSE_CAKE_END, ending, generic, 20000, 0x00, 0x00, 0x00, _, _)
|
||||
DEFINE_LEVEL("URANIWA", LEVEL_CASTLE_COURTYARD, COURSE_NONE, castle_courtyard, outside, 20000, 0x08, 0x08, 0x08, _, _)
|
||||
DEFINE_LEVEL("EXT4 MINI SLID", LEVEL_PSS, COURSE_PSS, pss, mountain, 20000, 0x28, 0x28, 0x28, _, _)
|
||||
DEFINE_LEVEL("IN THE FALL", LEVEL_COTMC, COURSE_COTMC, cotmc, cave, 18000, 0x28, 0x28, 0x28, _, sCamCotMC)
|
||||
DEFINE_LEVEL("EXT6 MARIO FLY", LEVEL_TOTWC, COURSE_TOTWC, totwc, sky, 20000, 0x20, 0x20, 0x20, _, _)
|
||||
DEFINE_LEVEL("KUPPA1", LEVEL_BOWSER_1, COURSE_BITDW, bowser_1, generic, VAL_DIFF, 0x40, 0x40, 0x40, _, _)
|
||||
DEFINE_LEVEL("EXT8 BLUE SKY", LEVEL_WMOTR, COURSE_WMOTR, wmotr, generic, 20000, 0x28, 0x28, 0x28, _, _)
|
||||
DEFINE_LEVEL("CASTLE COURTYARD", LEVEL_CASTLE_COURTYARD, COURSE_NONE, castle_courtyard, outside, 20000, 0x08, 0x08, 0x08, _, _)
|
||||
DEFINE_LEVEL("SECRET SLIDE", LEVEL_PSS, COURSE_PSS, pss, mountain, 20000, 0x28, 0x28, 0x28, _, _)
|
||||
DEFINE_LEVEL("C OF METAL CAP", LEVEL_COTMC, COURSE_COTMC, cotmc, cave, 18000, 0x28, 0x28, 0x28, _, sCamCotMC)
|
||||
DEFINE_LEVEL("T OF WING CAP", LEVEL_TOTWC, COURSE_TOTWC, totwc, sky, 20000, 0x20, 0x20, 0x20, _, _)
|
||||
DEFINE_LEVEL("BOWSER 1", LEVEL_BOWSER_1, COURSE_BITDW, bowser_1, generic, VAL_DIFF, 0x40, 0x40, 0x40, _, _)
|
||||
DEFINE_LEVEL("WMOTR", LEVEL_WMOTR, COURSE_WMOTR, wmotr, generic, 20000, 0x28, 0x28, 0x28, _, _)
|
||||
STUB_LEVEL( "", LEVEL_UNKNOWN_32, COURSE_NONE, 20000, 0x70, 0x00, 0x00, _, _)
|
||||
DEFINE_LEVEL("KUPPA2", LEVEL_BOWSER_2, COURSE_BITFS, bowser_2, fire, VAL_DIFF, 0x40, 0x40, 0x40, _, _)
|
||||
DEFINE_LEVEL("KUPPA3", LEVEL_BOWSER_3, COURSE_BITS, bowser_3, generic, VAL_DIFF, 0x40, 0x40, 0x40, _, _)
|
||||
DEFINE_LEVEL("BOWSER 2", LEVEL_BOWSER_2, COURSE_BITFS, bowser_2, fire, VAL_DIFF, 0x40, 0x40, 0x40, _, _)
|
||||
DEFINE_LEVEL("BOWSER 3", LEVEL_BOWSER_3, COURSE_BITS, bowser_3, generic, VAL_DIFF, 0x40, 0x40, 0x40, _, _)
|
||||
STUB_LEVEL( "", LEVEL_UNKNOWN_35, COURSE_NONE, 20000, 0x00, 0x00, 0x00, _, _)
|
||||
DEFINE_LEVEL("DONKEY % SLID2", LEVEL_TTM, COURSE_TTM, ttm, mountain, 15000, 0x08, 0x08, 0x08, _, _)
|
||||
DEFINE_LEVEL("TT MOUNTAIN", LEVEL_TTM, COURSE_TTM, ttm, mountain, 15000, 0x08, 0x08, 0x08, _, _)
|
||||
STUB_LEVEL( "", LEVEL_UNKNOWN_37, COURSE_NONE, 20000, 0x00, 0x00, 0x00, _, _)
|
||||
STUB_LEVEL( "", LEVEL_UNKNOWN_38, COURSE_NONE, 20000, 0x00, 0x00, 0x00, sDynUnk38, _)
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ const LevelScript level_main_menu_entry_2[] = {
|
|||
/*37*/ TRANSITION(/*transType*/ WARP_TRANSITION_FADE_INTO_COLOR, /*time*/ 16, /*color*/ 0xFF, 0xFF, 0xFF),
|
||||
/*39*/ SLEEP(/*frames*/ 16),
|
||||
/*40*/ CLEAR_LEVEL(),
|
||||
/*41*/ SLEEP_BEFORE_EXIT(/*frames*/ 1),
|
||||
/*41*/ SLEEP_BEFORE_EXIT(/*frames*/ 9), //MORS NOTE: This was changed from 1 to simulate the load times.
|
||||
// L1:
|
||||
/*42*/ EXIT(),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -250,7 +250,8 @@ u8 sDialogSpeaker[] = {
|
|||
/*13*/ _, _, TUXIE, _, _, _, _, _, _, _,
|
||||
/*14*/ _, _, _, _, _, _, _, _, _, _,
|
||||
/*15*/ WIGLR, WIGLR, WIGLR, _, _, _, _, _, _, _,
|
||||
/*16*/ _, YOSHI, _, _, _, _, _, _, WIGLR, _
|
||||
/*16*/ _, YOSHI, _, _, _, _, _, _, WIGLR, _,
|
||||
/*NW*/ _, TUXIE, TUXIE
|
||||
};
|
||||
#undef _
|
||||
STATIC_ASSERT(ARRAY_COUNT(sDialogSpeaker) == DIALOG_COUNT, "change this array if you are adding dialogs");
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
#include "graph_node.h"
|
||||
#include "surface_collision.h"
|
||||
|
||||
#include "game/settings.h"
|
||||
|
||||
// Macros for retrieving arguments from behavior scripts.
|
||||
#define BHV_CMD_GET_1ST_U8(index) (u8)((gCurBhvCommand[index] >> 24) & 0xFF) // unused
|
||||
#define BHV_CMD_GET_2ND_U8(index) (u8)((gCurBhvCommand[index] >> 16) & 0xFF)
|
||||
|
|
@ -988,6 +990,14 @@ void cur_obj_update(void) {
|
|||
cur_obj_enable_rendering_if_mario_in_room();
|
||||
} else if ((objFlags & OBJ_FLAG_COMPUTE_DIST_TO_MARIO) && gCurrentObject->collisionData == NULL) {
|
||||
if (!(objFlags & OBJ_FLAG_ACTIVE_FROM_AFAR)) {
|
||||
if (gDisableDrawDistance) {
|
||||
if (distanceFromMario <= gCurrentObject->oDrawingDistance && gCurrentObject->oHeldState == HELD_FREE)
|
||||
{
|
||||
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
|
||||
gCurrentObject->activeFlags &= ~ACTIVE_FLAG_FAR_AWAY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If the object has a render distance, check if it should be shown.
|
||||
if (distanceFromMario > gCurrentObject->oDrawingDistance) {
|
||||
// Out of render distance, hide the object.
|
||||
|
|
@ -1000,4 +1010,5 @@ void cur_obj_update(void) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
#include "surface_collision.h"
|
||||
#include "surface_load.h"
|
||||
|
||||
#include "game/settings.h"
|
||||
|
||||
/**************************************************
|
||||
* WALLS *
|
||||
**************************************************/
|
||||
|
|
@ -403,6 +405,7 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
|
|||
f32 oo;
|
||||
f32 height;
|
||||
struct Surface *floor = NULL;
|
||||
f32 peak = -11000.0f;
|
||||
|
||||
// Iterate through the list of floors until there are no more floors.
|
||||
while (surfaceNode != NULL) {
|
||||
|
|
@ -461,10 +464,15 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
|
|||
*pheight = height;
|
||||
floor = surf;
|
||||
break;
|
||||
|
||||
// floor cucking fix, shoutouts to kaze and whoever josh is
|
||||
if (gCollisionFixes && peak < height) {
|
||||
peak = height;
|
||||
*pheight = height;
|
||||
floor = surf;
|
||||
}
|
||||
}
|
||||
|
||||
//! (Surface Cucking) Since only the first floor is returned and not the highest,
|
||||
// higher floors can be "cucked" by lower floors.
|
||||
return floor;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@
|
|||
#include "game/mario.h"
|
||||
#include "game/object_list_processor.h"
|
||||
#include "surface_load.h"
|
||||
#include "game/game_init.h"
|
||||
|
||||
#include "game/settings.h"
|
||||
|
||||
s32 unused8038BE90;
|
||||
|
||||
|
|
@ -787,7 +790,7 @@ void load_object_collision_model(void) {
|
|||
}
|
||||
}
|
||||
|
||||
if (marioDist < gCurrentObject->oDrawingDistance) {
|
||||
if (marioDist < gCurrentObject->oDrawingDistance || gDisableDrawDistance) {
|
||||
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
|
||||
} else {
|
||||
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
#include "save_file.h"
|
||||
#include "level_table.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
struct SpawnInfo gPlayerSpawnInfos[1];
|
||||
struct GraphNode *D_8033A160[0x100];
|
||||
struct Area gAreaData[8];
|
||||
|
|
@ -238,6 +240,8 @@ void load_area(s32 index) {
|
|||
|
||||
load_obj_warp_nodes();
|
||||
geo_call_global_function_nodes(&gCurrentArea->unk04->node, GEO_CONTEXT_AREA_LOAD);
|
||||
|
||||
gCanMirror = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -256,6 +260,10 @@ void load_mario_area(void) {
|
|||
func_80320890();
|
||||
load_area(gMarioSpawnInfo->areaIndex);
|
||||
|
||||
gCanMirror = 1;
|
||||
if (gEncoreMode)
|
||||
gReimportTextures = 1;
|
||||
|
||||
if (gCurrentArea->index == gMarioSpawnInfo->areaIndex) {
|
||||
gCurrentArea->flags |= 0x01;
|
||||
spawn_objects_from_info(0, gMarioSpawnInfo);
|
||||
|
|
@ -369,7 +377,9 @@ void render_game(void) {
|
|||
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH,
|
||||
SCREEN_HEIGHT - BORDER_HEIGHT);
|
||||
if (!gHideHud) {
|
||||
render_hud();
|
||||
}
|
||||
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
render_text_labels();
|
||||
|
|
|
|||
|
|
@ -460,10 +460,12 @@ static void boo_act_4(void) {
|
|||
// If there are no remaining "minion" boos, show the dialog of the Big Boo
|
||||
if (cur_obj_nearest_object_with_behavior(bhvGhostHuntBoo) == NULL) {
|
||||
dialogID = DIALOG_108;
|
||||
gBooDialogueWasSaid = 0;
|
||||
} else {
|
||||
dialogID = DIALOG_107;
|
||||
}
|
||||
|
||||
if (!gBooDialogueWasSaid) {
|
||||
if (cur_obj_update_dialog(2, 2, dialogID, 0)) {
|
||||
create_sound_spawner(SOUND_OBJ_DYING_ENEMY1);
|
||||
obj_mark_for_deletion(o);
|
||||
|
|
@ -471,6 +473,9 @@ static void boo_act_4(void) {
|
|||
if (dialogID == DIALOG_108) { // If the Big Boo should spawn, play the jingle
|
||||
play_puzzle_jingle();
|
||||
}
|
||||
else if (gDisableBooDialogue)
|
||||
gBooDialogueWasSaid = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -524,7 +529,12 @@ static void big_boo_act_0(void) {
|
|||
|
||||
o->oBooTargetOpacity = 0xFF;
|
||||
o->oBooBaseScale = 3.0f;
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
o->oHealth = 5;
|
||||
}
|
||||
else {
|
||||
o->oHealth = 3;
|
||||
}
|
||||
|
||||
cur_obj_scale(3.0f);
|
||||
cur_obj_become_tangible();
|
||||
|
|
@ -540,6 +550,16 @@ static void big_boo_act_1(void) {
|
|||
s16 sp22;
|
||||
f32 sp1C;
|
||||
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
if (o->oHealth == 3) {
|
||||
sp22 = 0x300; sp1C = 0.8f;
|
||||
} else if (o->oHealth == 2) {
|
||||
sp22 = 0x360; sp1C = 1.0f;
|
||||
} else {
|
||||
sp22 = 0x420; sp1C = 1.2f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (o->oHealth == 3) {
|
||||
sp22 = 0x180; sp1C = 0.5f;
|
||||
} else if (o->oHealth == 2) {
|
||||
|
|
@ -547,6 +567,7 @@ static void big_boo_act_1(void) {
|
|||
} else {
|
||||
sp22 = 0x300; sp1C = 0.8f;
|
||||
}
|
||||
}
|
||||
|
||||
boo_chase_mario(-100.0f, sp22, sp1C);
|
||||
|
||||
|
|
|
|||
|
|
@ -1006,6 +1006,7 @@ struct SoundState D_8032F5B8[] = { { 0, 0, 0, NO_SOUND },
|
|||
{ 1, 0, -1, SOUND_OBJ2_BOWSER_ROAR } };
|
||||
s8 D_8032F690[4] = { 0, 0, 1, 0 };
|
||||
s8 D_8032F694[4] = { 1, 1, 3, 0 };
|
||||
s8 D_8032F694_hard[4] = { 3, 4, 5, 0 };
|
||||
extern u8 bowser_3_seg7_collision_07004B94[];
|
||||
extern u8 bowser_3_seg7_collision_07004C18[];
|
||||
extern u8 bowser_3_seg7_collision_07004C9C[];
|
||||
|
|
@ -1150,7 +1151,12 @@ void bhv_bowser_init(void) {
|
|||
level = 0;
|
||||
o->oBehParams2ndByte = level;
|
||||
o->oBowserUnk1B2 = D_8032F690[level];
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
o->oHealth = D_8032F694_hard[level];
|
||||
}
|
||||
else {
|
||||
o->oHealth = D_8032F694[level];
|
||||
}
|
||||
cur_obj_start_cam_event(o, CAM_EVENT_BOWSER_INIT);
|
||||
o->oAction = 5;
|
||||
o->oBowserUnk1AE = 0;
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@
|
|||
// NOTE: These first set of functions spawn a school of bub depending on objF4's
|
||||
// value. The later action functions seem to check Y distance to Mario and proceed
|
||||
// to do nothing, which indicates this behavior set is incomplete.
|
||||
#include "../settings.h"
|
||||
|
||||
// TODO: Rename these. These have nothing to do with birds.
|
||||
void bub_spawner_act_0(void) {
|
||||
s32 i;
|
||||
s32 sp18 = o->oBirdChirpChirpUnkF4;
|
||||
if (o->oDistanceToMario < 1500.0f) {
|
||||
if (o->oDistanceToMario < 1500.0f && !gDisableDrawDistance) {
|
||||
for (i = 0; i < sp18; i++)
|
||||
spawn_object(o, MODEL_BUB, bhvBub);
|
||||
o->oAction = 1;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ void bhv_camera_lakitu_init(void) {
|
|||
static void camera_lakitu_intro_act_trigger_cutscene(void) {
|
||||
//! These bounds are slightly smaller than the actual bridge bounds, allowing
|
||||
// the RTA speedrunning method of lakitu skip
|
||||
if (gMarioObject->oPosX > -544.0f && gMarioObject->oPosX < 545.0f && gMarioObject->oPosY > 800.0f
|
||||
if (!gSkipCutscenes
|
||||
&& gMarioObject->oPosX > -544.0f && gMarioObject->oPosX < 545.0f && gMarioObject->oPosY > 800.0f
|
||||
&& gMarioObject->oPosZ > -2000.0f && gMarioObject->oPosZ < -177.0f
|
||||
&& gMarioObject->oPosZ < -177.0f) // always double check your conditions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// castle_floor_trap.c.inc
|
||||
#include "../settings.h"
|
||||
|
||||
void bhv_floor_trap_in_castle_loop(void) {
|
||||
if (gMarioObject->platform == o)
|
||||
|
|
@ -25,8 +26,14 @@ void bhv_castle_floor_trap_open_detect(void) {
|
|||
}
|
||||
|
||||
void bhv_castle_floor_trap_open(void) {
|
||||
if (o->oTimer == 0)
|
||||
if (o->oTimer == 0) {
|
||||
if (gTrapdoorSound) {
|
||||
play_sound(SOUND_GENERAL_CASTLE_TRAP_OPEN, gDefaultSoundArgs);
|
||||
}
|
||||
else {
|
||||
cur_obj_play_sound_2(SOUND_GENERAL_CASTLE_TRAP_OPEN);
|
||||
}
|
||||
}
|
||||
o->oAngleVelRoll -= 0x100;
|
||||
o->oFaceAngleRoll += o->oAngleVelRoll;
|
||||
if (o->oFaceAngleRoll < -0x4000) {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
* Processing order is bhvWoodenPost, bhvChainChompGate, bhvChainChomp, bhvChainChompChainPart.
|
||||
* The chain parts are processed starting at the post and ending at the chomp.
|
||||
*/
|
||||
#include "../settings.h"
|
||||
|
||||
/**
|
||||
* Hitbox for chain chomp.
|
||||
|
|
@ -53,7 +54,7 @@ static void chain_chomp_act_uninitialized(void) {
|
|||
struct ChainSegment *segments;
|
||||
s32 i;
|
||||
|
||||
if (o->oDistanceToMario < 3000.0f) {
|
||||
if (o->oDistanceToMario < 3000.0f || gDisableDrawDistance) {
|
||||
segments = mem_pool_alloc(gObjectMemoryPool, 5 * sizeof(struct ChainSegment));
|
||||
if (segments != NULL) {
|
||||
// Each segment represents the offset of a chain part to the pivot.
|
||||
|
|
@ -359,7 +360,7 @@ static void chain_chomp_act_move(void) {
|
|||
f32 maxDistToPivot;
|
||||
|
||||
// Unload chain if mario is far enough
|
||||
if (o->oChainChompReleaseStatus == CHAIN_CHOMP_NOT_RELEASED && o->oDistanceToMario > 4000.0f) {
|
||||
if (o->oChainChompReleaseStatus == CHAIN_CHOMP_NOT_RELEASED && o->oDistanceToMario > 4000.0f && !gDisableDrawDistance) {
|
||||
o->oAction = CHAIN_CHOMP_ACT_UNLOAD_CHAIN;
|
||||
o->oForwardVel = o->oVelY = 0.0f;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
* If spawned by a lakitu, its parent will be the lakitu.
|
||||
* Processing order is lakitu -> cloud -> its cloud parts.
|
||||
*/
|
||||
#include "../settings.h"
|
||||
|
||||
/**
|
||||
* The relative heights of each cloud part.
|
||||
|
|
@ -47,7 +48,7 @@ static void cloud_act_spawn_parts(void) {
|
|||
* Wait for mario to approach, then unhide and enter the spawn parts action.
|
||||
*/
|
||||
static void cloud_act_fwoosh_hidden(void) {
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
if (o->oDistanceToMario < 2000.0f && !gDisableDrawDistance) {
|
||||
cur_obj_unhide();
|
||||
o->oAction = CLOUD_ACT_SPAWN_PARTS;
|
||||
}
|
||||
|
|
@ -58,7 +59,7 @@ static void cloud_act_fwoosh_hidden(void) {
|
|||
* long enough, blow wind at him.
|
||||
*/
|
||||
static void cloud_fwoosh_update(void) {
|
||||
if (o->oDistanceToMario > 2500.0f) {
|
||||
if (o->oDistanceToMario > 2500.0f && !gDisableDrawDistance) {
|
||||
o->oAction = CLOUD_ACT_UNLOAD;
|
||||
} else {
|
||||
if (o->oCloudBlowing) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// coin.c.inc
|
||||
#include "../settings.h"
|
||||
|
||||
struct ObjectHitbox sYellowCoinHitbox = {
|
||||
/* interactType: */ INTERACT_COIN,
|
||||
|
|
@ -184,7 +185,7 @@ void bhv_coin_formation_loop(void) {
|
|||
s32 bitIndex;
|
||||
switch (o->oAction) {
|
||||
case 0:
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
if (o->oDistanceToMario < 2000.0f || gDisableDrawDistance) {
|
||||
for (bitIndex = 0; bitIndex < 8; bitIndex++) {
|
||||
if (!(o->oCoinUnkF4 & (1 << bitIndex)))
|
||||
spawn_coin_in_formation(bitIndex, o->oBehParams2ndByte);
|
||||
|
|
@ -193,7 +194,7 @@ void bhv_coin_formation_loop(void) {
|
|||
}
|
||||
break;
|
||||
case 1:
|
||||
if (o->oDistanceToMario > 2100.0f)
|
||||
if (o->oDistanceToMario > 2100.0f && !gDisableDrawDistance)
|
||||
o->oAction++;
|
||||
break;
|
||||
case 2:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
* Lakitu comes before it spawned spinies in processing order.
|
||||
* TODO: bhvCloud processing oredr
|
||||
*/
|
||||
#include "../settings.h"
|
||||
|
||||
/**
|
||||
* Hitbox for evil lakitu.
|
||||
|
|
@ -24,7 +25,7 @@ static struct ObjectHitbox sEnemyLakituHitbox = {
|
|||
* Wait for mario to approach, then spawn the cloud and become visible.
|
||||
*/
|
||||
static void enemy_lakitu_act_uninitialized(void) {
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
if (o->oDistanceToMario < 2000.0f && !gDisableDrawDistance) {
|
||||
spawn_object_relative_with_scale(CLOUD_BP_LAKITU_CLOUD, 0, 0, 0, 2.0f, o, MODEL_MIST, bhvCloud);
|
||||
|
||||
cur_obj_unhide();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
* @file fish.inc.c
|
||||
* Implements behaviour and spawning for fish located in the Secret Aquarium and other levels.
|
||||
*/
|
||||
#include "../settings.h"
|
||||
|
||||
/**
|
||||
* Spawns fish with settings chosen by the field o->oBehParams2ndByte.
|
||||
|
|
@ -42,6 +43,8 @@ void fish_act_spawn(void) {
|
|||
* If the current level is Secret Aquarium, ignore this requirement.
|
||||
* Fish moves at random with a max-range of 700.0f.
|
||||
*/
|
||||
if(!gDisableDrawDistance)
|
||||
{
|
||||
if (o->oDistanceToMario < minDistToMario || gCurrLevelNum == LEVEL_SA) {
|
||||
for (i = 0; i < schoolQuantity; i++) {
|
||||
fishObject = spawn_object(o, model, bhvFish);
|
||||
|
|
@ -51,6 +54,7 @@ void fish_act_spawn(void) {
|
|||
}
|
||||
o->oAction = FISH_ACT_ACTIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
* Goombas can either be spawned individually, or spawned by a triplet spawner.
|
||||
* The triplet spawner comes before its spawned goombas in processing order.
|
||||
*/
|
||||
#include "../settings.h"
|
||||
|
||||
/**
|
||||
* Hitbox for goomba.
|
||||
|
|
@ -78,7 +79,7 @@ void bhv_goomba_triplet_spawner_update(void) {
|
|||
// If mario is close enough and the goombas aren't currently loaded, then
|
||||
// spawn them
|
||||
if (o->oAction == GOOMBA_TRIPLET_SPAWNER_ACT_UNLOADED) {
|
||||
if (o->oDistanceToMario < 3000.0f) {
|
||||
if (o->oDistanceToMario < 3000.0f && !gDisableDrawDistance) {
|
||||
// The spawner is capable of spawning more than 3 goombas, but this
|
||||
// is not used in the game
|
||||
dAngle =
|
||||
|
|
@ -99,7 +100,7 @@ void bhv_goomba_triplet_spawner_update(void) {
|
|||
|
||||
o->oAction += 1;
|
||||
}
|
||||
} else if (o->oDistanceToMario > 4000.0f) {
|
||||
} else if (o->oDistanceToMario > 4000.0f && !gDisableDrawDistance) {
|
||||
// If mario is too far away, enter the unloaded action. The goombas
|
||||
// will detect this and unload themselves
|
||||
o->oAction = GOOMBA_TRIPLET_SPAWNER_ACT_UNLOADED;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// heave_ho.c.inc
|
||||
#include "../settings.h"
|
||||
|
||||
s16 D_8032F460[][2] = { { 30, 0 }, { 42, 1 }, { 52, 0 }, { 64, 1 }, { 74, 0 },
|
||||
{ 86, 1 }, { 96, 0 }, { 108, 1 }, { 118, 0 }, { -1, 0 }, };
|
||||
|
|
@ -73,7 +74,7 @@ void heave_ho_act_3(void) {
|
|||
|
||||
void heave_ho_act_0(void) {
|
||||
cur_obj_set_pos_to_home();
|
||||
if (find_water_level(o->oPosX, o->oPosZ) < o->oPosY && o->oDistanceToMario < 4000.0f) {
|
||||
if (find_water_level(o->oPosX, o->oPosZ) < o->oPosY && o->oDistanceToMario < 4000.0f || gDisableDrawDistance) {
|
||||
cur_obj_become_tangible();
|
||||
cur_obj_unhide();
|
||||
o->oAction = 1;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@ void bhv_hidden_star_trigger_loop(void) {
|
|||
|
||||
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
}
|
||||
|
||||
if (gVisibleSecrets) {
|
||||
spawn_object(o, MODEL_NONE, bhvSparkleSpawn);
|
||||
}
|
||||
}
|
||||
|
||||
void bhv_bowser_course_red_coin_star_loop(void) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// king_bobomb.c.inc
|
||||
#include "../settings.h"
|
||||
|
||||
// Copy of geo_update_projectile_pos_from_parent
|
||||
Gfx *geo_update_held_mario_pos(s32 run, UNUSED struct GraphNode *node, Mat4 mtx) {
|
||||
|
|
@ -30,7 +31,12 @@ void king_bobomb_act_0(void) {
|
|||
gSecondCameraFocus = o;
|
||||
cur_obj_init_animation_with_sound(5);
|
||||
cur_obj_set_pos_to_home();
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
o->oHealth = 5;
|
||||
}
|
||||
else {
|
||||
o->oHealth = 3;
|
||||
}
|
||||
if (cur_obj_can_mario_activate_textbox_2(500.0f, 100.0f)) {
|
||||
o->oSubAction++;
|
||||
func_8031FFB4(SEQ_PLAYER_LEVEL, 60, 40);
|
||||
|
|
@ -66,8 +72,14 @@ void king_bobomb_act_2(void) {
|
|||
} else
|
||||
cur_obj_init_animation_with_sound(11);
|
||||
if (o->oKingBobombUnk108 == 0) {
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
o->oForwardVel = 10.0f;
|
||||
cur_obj_rotate_yaw_toward(o->oAngleToMario, 0x200);
|
||||
}
|
||||
else {
|
||||
o->oForwardVel = 3.0f;
|
||||
cur_obj_rotate_yaw_toward(o->oAngleToMario, 0x100);
|
||||
}
|
||||
} else {
|
||||
o->oForwardVel = 0.0f;
|
||||
o->oKingBobombUnk108--;
|
||||
|
|
@ -295,10 +307,12 @@ void king_bobomb_move(void) {
|
|||
cur_obj_move_using_fvel_and_gravity();
|
||||
cur_obj_call_action_function(sKingBobombActions);
|
||||
exec_anim_sound_state(sKingBobombSoundStates);
|
||||
if (!gDisableDrawDistance) {
|
||||
if (o->oDistanceToMario < 5000.0f)
|
||||
cur_obj_enable_rendering();
|
||||
else
|
||||
cur_obj_disable_rendering();
|
||||
}
|
||||
}
|
||||
|
||||
void bhv_king_bobomb_loop(void) {
|
||||
|
|
|
|||
|
|
@ -614,6 +614,17 @@ static void koopa_the_quick_act_race(void) {
|
|||
case KOOPA_THE_QUICK_SUB_ACT_RUN:
|
||||
koopa_the_quick_animate_footsteps();
|
||||
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
if (o->parentObj->oKoopaRaceEndpointRaceStatus != 0 && o->oDistanceToMario > 1500.0f
|
||||
&& (o->oPathedPrevWaypointFlags & WAYPOINT_MASK_00FF) < 28) {
|
||||
// Move faster if mario has already finished the race or
|
||||
// cheated by shooting from cannon
|
||||
o->oKoopaAgility = 12.0f;
|
||||
} else {
|
||||
o->oKoopaAgility = 8.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (o->parentObj->oKoopaRaceEndpointRaceStatus != 0 && o->oDistanceToMario > 1500.0f
|
||||
&& (o->oPathedPrevWaypointFlags & WAYPOINT_MASK_00FF) < 28) {
|
||||
// Move faster if mario has already finished the race or
|
||||
|
|
@ -624,6 +635,7 @@ static void koopa_the_quick_act_race(void) {
|
|||
} else {
|
||||
o->oKoopaAgility = 4.0f;
|
||||
}
|
||||
}
|
||||
|
||||
obj_forward_vel_approach(o->oKoopaAgility * 6.0f * downhillSteepness,
|
||||
o->oKoopaAgility * 0.1f);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// lll_floating_wood_piece.c.inc
|
||||
#include "../settings.h"
|
||||
|
||||
void bhv_lll_wood_piece_loop(void) {
|
||||
if (o->oTimer == 0)
|
||||
|
|
@ -14,7 +15,7 @@ void bhv_lll_floating_wood_bridge_loop(void) {
|
|||
s32 i;
|
||||
switch (o->oAction) {
|
||||
case 0:
|
||||
if (o->oDistanceToMario < 2500.0f) {
|
||||
if (o->oDistanceToMario < 2500.0f && !gDisableDrawDistance) {
|
||||
for (i = 1; i < 4; i++) {
|
||||
sp3C = spawn_object_relative(0, (i - 2) * 300, 0, 0, o, MODEL_LLL_WOOD_BRIDGE,
|
||||
bhvLllWoodPiece);
|
||||
|
|
@ -24,7 +25,7 @@ void bhv_lll_floating_wood_bridge_loop(void) {
|
|||
}
|
||||
break;
|
||||
case 1:
|
||||
if (o->oDistanceToMario > 2600.0f)
|
||||
if (o->oDistanceToMario > 2600.0f && !gDisableDrawDistance)
|
||||
o->oAction = 2;
|
||||
break;
|
||||
case 2:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,17 @@ void bhv_1up_interact(void) {
|
|||
|
||||
if (obj_check_if_collided_with_object(o, gMarioObject) == 1) {
|
||||
play_sound(SOUND_GENERAL_COLLECT_1UP, gDefaultSoundArgs);
|
||||
if (gGreenDemon != 0) {
|
||||
gMarioState->health = 0;
|
||||
}
|
||||
else if (gLifeMode || save_file_get_flags() & SAVE_FLAG_HARDCORE_MODE) {
|
||||
gMarioState->healCounter += 31.75;
|
||||
if (gMarioState->healCounter > 31.75)
|
||||
gMarioState->healCounter = 31.75;
|
||||
}
|
||||
else {
|
||||
gMarioState->numLives++;
|
||||
}
|
||||
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
* This controls Piranha Plants, which alternate between sleeping, attacking,
|
||||
* and dying, primarily depending on Mario's proximity and interaction state.
|
||||
*/
|
||||
#include "../settings.h"
|
||||
|
||||
/**
|
||||
* Reset the Piranha Plant back to a sleeping animation, no matter what state
|
||||
|
|
@ -330,7 +331,7 @@ void bhv_piranha_plant_loop(void) {
|
|||
cur_obj_call_action_function(TablePiranhaPlantActions);
|
||||
|
||||
// In WF, hide all Piranha Plants once high enough up.
|
||||
if (gCurrLevelNum == LEVEL_WF) {
|
||||
if (gCurrLevelNum == LEVEL_WF && !gDisableDrawDistance) {
|
||||
if (gMarioObject->oPosY > 3400.0f)
|
||||
cur_obj_hide();
|
||||
else
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
* Pokey comes before its body parts in processing order, and the body parts
|
||||
* are processed top to bottom.
|
||||
*/
|
||||
#include "../settings.h"
|
||||
|
||||
/**
|
||||
* Hitbox for a single pokey body part.
|
||||
|
|
@ -151,7 +152,7 @@ static void pokey_act_uninitialized(void) {
|
|||
s32 i;
|
||||
s16 partModel;
|
||||
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
if (o->oDistanceToMario < 2000.0f && !gDisableDrawDistance) {
|
||||
partModel = MODEL_POKEY_HEAD;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
|
|
@ -185,7 +186,7 @@ static void pokey_act_wander(void) {
|
|||
|
||||
if (o->oPokeyNumAliveBodyParts == 0) {
|
||||
obj_mark_for_deletion(o);
|
||||
} else if (o->oDistanceToMario > 2500.0f) {
|
||||
} else if (o->oDistanceToMario > 2500.0f && !gDisableDrawDistance) {
|
||||
o->oAction = POKEY_ACT_UNLOAD_PARTS;
|
||||
o->oForwardVel = 0.0f;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -7,10 +7,22 @@ struct RacingPenguinData {
|
|||
static struct RacingPenguinData sRacingPenguinData[] = {
|
||||
{ DIALOG_055, 200.0f, 200.0f },
|
||||
{ DIALOG_164, 350.0f, 250.0f },
|
||||
{ DIALOG_171, 0.0f, 0.0f },
|
||||
{ DIALOG_172, 0.0f, 0.0f },
|
||||
};
|
||||
|
||||
void bhv_racing_penguin_init(void) {
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
if (gMarioState->numStars == 120) {
|
||||
cur_obj_scale(0.25f);
|
||||
o->oBehParams2ndByte = 3;
|
||||
}
|
||||
else {
|
||||
cur_obj_scale(0.5f);
|
||||
o->oBehParams2ndByte = 2;
|
||||
}
|
||||
}
|
||||
else if (gMarioState->numStars == 120) {
|
||||
cur_obj_scale(8.0f);
|
||||
o->header.gfx.scale[1] = 5.0f;
|
||||
o->oBehParams2ndByte = 1;
|
||||
|
|
@ -67,7 +79,12 @@ static void racing_penguin_act_race(void) {
|
|||
o->oAction = RACING_PENGUIN_ACT_FINISH_RACE;
|
||||
} else {
|
||||
targetSpeed = o->oPosY - gMarioObject->oPosY;
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
minSpeed = 90.0f;
|
||||
}
|
||||
else {
|
||||
minSpeed = 70.0f;
|
||||
}
|
||||
|
||||
cur_obj_play_sound_1(SOUND_AIR_ROUGH_SLIDE);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#include "../settings.h"
|
||||
|
||||
struct TripletButterflyActivationData {
|
||||
s32 model;
|
||||
const BehaviorScript *behavior;
|
||||
|
|
@ -54,7 +56,7 @@ static void triplet_butterfly_act_init(void) {
|
|||
}
|
||||
|
||||
static void triplet_butterfly_act_wander(void) {
|
||||
if (o->oDistanceToMario > 1500.0f) {
|
||||
if (o->oDistanceToMario > 1500.0f && !gDisableDrawDistance) {
|
||||
obj_mark_for_deletion(o);
|
||||
} else {
|
||||
approach_f32_ptr(&o->oTripletButterflySpeed, 8.0f, 0.5f);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// water_bomb_cannon.inc.c
|
||||
#include "../settings.h"
|
||||
|
||||
void bhv_bubble_cannon_barrel_loop(void) {
|
||||
struct Object *val04;
|
||||
|
|
@ -38,7 +39,7 @@ void bhv_bubble_cannon_barrel_loop(void) {
|
|||
}
|
||||
|
||||
void water_bomb_cannon_act_0(void) {
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
if (o->oDistanceToMario < 2000.0f || gDisableDrawDistance) {
|
||||
spawn_object(o, MODEL_CANNON_BARREL, bhvCannonBarrelBubbles);
|
||||
cur_obj_unhide();
|
||||
|
||||
|
|
@ -48,7 +49,7 @@ void water_bomb_cannon_act_0(void) {
|
|||
}
|
||||
|
||||
void water_bomb_cannon_act_1(void) {
|
||||
if (o->oDistanceToMario > 2500.0f) {
|
||||
if (o->oDistanceToMario > 2500.0f && !gDisableDrawDistance) {
|
||||
o->oAction = 2;
|
||||
} else if (o->oBehParams2ndByte == 0) {
|
||||
if (o->oWaterCannonUnkF4 != 0) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// whirlpool.c.inc
|
||||
#include "../settings.h"
|
||||
|
||||
static struct ObjectHitbox sWhirlpoolHitbox = {
|
||||
/* interactType: */ INTERACT_WHIRLPOOL,
|
||||
|
|
@ -35,7 +36,7 @@ void whirpool_orient_graph(void) {
|
|||
}
|
||||
|
||||
void bhv_whirlpool_loop(void) {
|
||||
if (o->oDistanceToMario < 5000.0f) {
|
||||
if (o->oDistanceToMario < 5000.0f && !gDisableDrawDistance) {
|
||||
o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
|
||||
// not sure if actually an array
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// whomp.c.inc
|
||||
#include "../settings.h"
|
||||
|
||||
void whomp_play_sfx_from_pound_animation(void) {
|
||||
UNUSED s32 sp2C = o->header.gfx.unk38.animFrame;
|
||||
|
|
@ -26,8 +27,13 @@ void whomp_act_0(void) {
|
|||
func_8031FFB4(SEQ_PLAYER_LEVEL, 60, 40);
|
||||
} else {
|
||||
cur_obj_set_pos_to_home();
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
o->oHealth = 5;
|
||||
}
|
||||
else {
|
||||
o->oHealth = 3;
|
||||
}
|
||||
}
|
||||
} else if (cur_obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG, DIALOG_114))
|
||||
o->oAction = 2;
|
||||
} else if (o->oDistanceToMario < 500.0f)
|
||||
|
|
@ -85,7 +91,12 @@ void whomp_act_2(void) {
|
|||
sp1E = abs_angle_diff(o->oAngleToMario, o->oMoveAngleYaw);
|
||||
if (sp1E < 0x2000) {
|
||||
if (o->oDistanceToMario < 1500.0f) {
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
o->oForwardVel = 27.0f;
|
||||
}
|
||||
else {
|
||||
o->oForwardVel = 9.0f;
|
||||
}
|
||||
cur_obj_init_animation_with_accel_and_sound(0, 3.0f);
|
||||
}
|
||||
if (o->oDistanceToMario < 300.0f)
|
||||
|
|
@ -101,7 +112,12 @@ void whomp_act_2(void) {
|
|||
|
||||
void whomp_act_3(void) {
|
||||
o->oForwardVel = 0.0f;
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
cur_obj_init_animation_with_accel_and_sound(1, 3.0f);
|
||||
}
|
||||
else {
|
||||
cur_obj_init_animation_with_accel_and_sound(1, 1.0f);
|
||||
}
|
||||
if (cur_obj_check_if_near_animation_end())
|
||||
o->oAction = 4;
|
||||
}
|
||||
|
|
@ -111,7 +127,12 @@ void whomp_act_4(void) {
|
|||
o->oVelY = 40.0f;
|
||||
if (o->oTimer < 8) {
|
||||
} else {
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
o->oAngleVelPitch += 0x200;
|
||||
}
|
||||
else {
|
||||
o->oAngleVelPitch += 0x100;
|
||||
}
|
||||
o->oFaceAnglePitch += o->oAngleVelPitch;
|
||||
if (o->oFaceAnglePitch > 0x4000) {
|
||||
o->oAngleVelPitch = 0;
|
||||
|
|
@ -245,11 +266,13 @@ void bhv_whomp_loop(void) {
|
|||
cur_obj_update_floor_and_walls();
|
||||
cur_obj_call_action_function(sWhompActions);
|
||||
cur_obj_move_standard(-20);
|
||||
if (!gDisableDrawDistance) {
|
||||
if (o->oAction != 9) {
|
||||
if (o->oBehParams2ndByte != 0)
|
||||
cur_obj_hide_if_mario_far_away_y(2000.0f);
|
||||
else
|
||||
cur_obj_hide_if_mario_far_away_y(1000.0f);
|
||||
load_object_collision_model();
|
||||
}
|
||||
}
|
||||
load_object_collision_model();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,9 +316,17 @@ static void wiggler_act_jumped_on(void) {
|
|||
|
||||
if (o->oHealth == 2) {
|
||||
cur_obj_play_sound_2(SOUND_OBJ_WIGGLER_JUMP);
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
o->oForwardVel = 40.0f;
|
||||
}
|
||||
else {
|
||||
o->oForwardVel = 10.0f;
|
||||
}
|
||||
o->oVelY = 70.0f;
|
||||
}
|
||||
else if (save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
o->oForwardVel = 30.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,8 +132,11 @@ void yoshi_finish_jumping_and_despawn_loop(void) {
|
|||
void yoshi_give_present_loop(void) {
|
||||
s32 sp1C = gGlobalTimer;
|
||||
|
||||
if (gHudDisplay.lives == 100) {
|
||||
if ((!gLifeMode && gHudDisplay.lives == 100)
|
||||
|| (gLifeMode && gHudDisplay.lives == 0)) {
|
||||
if (gLifeMode) {
|
||||
play_sound(SOUND_GENERAL_COLLECT_1UP, gDefaultSoundArgs);
|
||||
}
|
||||
gSpecialTripleJump = 1;
|
||||
o->oAction = YOSHI_ACT_WALK_JUMP_OFF_ROOF;
|
||||
return;
|
||||
|
|
@ -141,8 +144,13 @@ void yoshi_give_present_loop(void) {
|
|||
|
||||
if ((sp1C & 0x03) == 0) {
|
||||
play_sound(SOUND_MENU_YOSHI_GAIN_LIVES, gDefaultSoundArgs);
|
||||
if (gLifeMode) {
|
||||
gMarioState->numLives--;
|
||||
}
|
||||
else {
|
||||
gMarioState->numLives++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bhv_yoshi_loop(void) {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include "engine/graph_node.h"
|
||||
#include "level_table.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#define CBUTTON_MASK (U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS)
|
||||
|
||||
/**
|
||||
|
|
@ -483,6 +485,10 @@ CameraTransition sModeTransitions[] = {
|
|||
extern u8 sDanceCutsceneIndexTable[][4];
|
||||
extern u8 sZoomOutAreaMasks[];
|
||||
|
||||
//Define the analog camera speed
|
||||
#define ANALOG_AMOUNT 12 * (1 - gInvertedCamera * 2)
|
||||
#define LROTATE_SPEED 0x400
|
||||
|
||||
/**
|
||||
* Starts a camera shake triggered by an interaction
|
||||
*/
|
||||
|
|
@ -906,7 +912,7 @@ s32 update_radial_camera(struct Camera *c, Vec3f focus, Vec3f pos) {
|
|||
UNUSED f32 unused2;
|
||||
UNUSED f32 unused3;
|
||||
f32 yOff = 125.f;
|
||||
f32 baseDist = 1000.f;
|
||||
f32 baseDist = 1000.f+gAdditionalCameraDistance;
|
||||
|
||||
sAreaYaw = camYaw - sModeOffsetYaw;
|
||||
calc_y_to_curr_floor(&posY, 1.f, 200.f, &focusY, 0.9f, 200.f);
|
||||
|
|
@ -930,7 +936,7 @@ s32 update_8_directions_camera(struct Camera *c, Vec3f focus, Vec3f pos) {
|
|||
UNUSED f32 unused2;
|
||||
UNUSED f32 unused3;
|
||||
f32 yOff = 125.f;
|
||||
f32 baseDist = 1000.f;
|
||||
f32 baseDist = 1000.f+gAdditionalCameraDistance;
|
||||
|
||||
sAreaYaw = camYaw;
|
||||
calc_y_to_curr_floor(&posY, 1.f, 200.f, &focusY, 0.9f, 200.f);
|
||||
|
|
@ -959,6 +965,7 @@ void radial_camera_move(struct Camera *c) {
|
|||
f32 areaDistX = sMarioCamState->pos[0] - c->areaCenX;
|
||||
f32 areaDistZ = sMarioCamState->pos[2] - c->areaCenZ;
|
||||
UNUSED s32 filler;
|
||||
s16 lCamRotation = DEGREES(180);
|
||||
|
||||
// How much the camera's yaw changed
|
||||
s16 yawOffset = calculate_yaw(sMarioCamState->pos, c->pos) - atan2s(areaDistZ, areaDistX);
|
||||
|
|
@ -1054,6 +1061,30 @@ void radial_camera_move(struct Camera *c) {
|
|||
gCameraMovementFlags &= ~(CAM_MOVE_ROTATE_LEFT | CAM_MOVE_ENTERED_ROTATE_SURFACE);
|
||||
s2ndRotateFlags &= ~CAM_MOVE_ROTATE_LEFT;
|
||||
}
|
||||
|
||||
// Analog camera code
|
||||
if (gPlayer1Controller->stick2X != 0) {
|
||||
if (gPlayer1Controller->stick2X > 0) {
|
||||
gCameraMovementFlags &= ~(CAM_MOVE_ROTATE_RIGHT | CAM_MOVE_ENTERED_ROTATE_SURFACE);
|
||||
}
|
||||
else {
|
||||
gCameraMovementFlags &= ~(CAM_MOVE_ROTATE_LEFT | CAM_MOVE_ENTERED_ROTATE_SURFACE);
|
||||
}
|
||||
sModeOffsetYaw -= ANALOG_AMOUNT * (gPlayer1Controller->stick2X / 32.0f) * gCameraSpeed;
|
||||
}
|
||||
|
||||
if (gCenterCam) {
|
||||
if (c->mode == CAMERA_MODE_OUTWARD_RADIAL) {
|
||||
lCamRotation = 0;
|
||||
}
|
||||
if (gPlayer1Controller->buttonPressed & L_TRIG) {
|
||||
sModeOffsetYaw = sMarioCamState->faceAngle[1]+lCamRotation-sAreaYaw;
|
||||
play_sound_rbutton_changed();
|
||||
}
|
||||
if (gPlayer1Controller->buttonDown & L_TRIG) {
|
||||
camera_approach_s16_symmetric_bool(&sModeOffsetYaw, sMarioCamState->faceAngle[1]+lCamRotation-sAreaYaw, LROTATE_SPEED);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(gCameraMovementFlags & CAM_MOVE_ROTATE)) {
|
||||
// If not rotating, rotate away from walls obscuring Mario from view
|
||||
|
|
@ -1070,7 +1101,7 @@ void radial_camera_move(struct Camera *c) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!gImprovedCamera) {
|
||||
// Bound sModeOffsetYaw within (-120, 120) degrees
|
||||
if (sModeOffsetYaw > 0x5554) {
|
||||
sModeOffsetYaw = 0x5554;
|
||||
|
|
@ -1078,6 +1109,7 @@ void radial_camera_move(struct Camera *c) {
|
|||
if (sModeOffsetYaw < -0x5554) {
|
||||
sModeOffsetYaw = -0x5554;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1184,6 +1216,27 @@ void mode_8_directions_camera(struct Camera *c) {
|
|||
play_sound_cbutton_side();
|
||||
}
|
||||
|
||||
// Analog camera code
|
||||
if (gPlayer1Controller->stick2X != 0) {
|
||||
if (gPlayer1Controller->stick2X > 0) {
|
||||
gCameraMovementFlags &= ~(CAM_MOVE_ROTATE_RIGHT | CAM_MOVE_ENTERED_ROTATE_SURFACE);
|
||||
}
|
||||
else {
|
||||
gCameraMovementFlags &= ~(CAM_MOVE_ROTATE_LEFT | CAM_MOVE_ENTERED_ROTATE_SURFACE);
|
||||
}
|
||||
s8DirModeYawOffset -= ANALOG_AMOUNT * (gPlayer1Controller->stick2X / 32.0f) * gCameraSpeed;
|
||||
}
|
||||
|
||||
if (gCenterCam) {
|
||||
if (gPlayer1Controller->buttonPressed & L_TRIG) {
|
||||
s8DirModeYawOffset = sMarioCamState->faceAngle[1] + DEGREES(180);
|
||||
play_sound_rbutton_changed();
|
||||
}
|
||||
if (gPlayer1Controller->buttonDown & L_TRIG) {
|
||||
camera_approach_s16_symmetric_bool(&s8DirModeYawOffset, sMarioCamState->faceAngle[1] + DEGREES(180), LROTATE_SPEED);
|
||||
}
|
||||
}
|
||||
|
||||
lakitu_zoom(400.f, 0x900);
|
||||
c->nextYaw = update_8_directions_camera(c, c->focus, pos);
|
||||
c->pos[0] = pos[0];
|
||||
|
|
@ -1201,7 +1254,7 @@ s32 update_outward_radial_camera(struct Camera *c, Vec3f focus, Vec3f pos) {
|
|||
f32 zDistFocToMario = sMarioCamState->pos[2] - c->areaCenZ;
|
||||
s16 camYaw = atan2s(zDistFocToMario, xDistFocToMario) + sModeOffsetYaw + DEGREES(180);
|
||||
s16 pitch = look_down_slopes(camYaw);
|
||||
f32 baseDist = 1000.f;
|
||||
f32 baseDist = 1000.f+gAdditionalCameraDistance;
|
||||
// A base offset of 125.f is ~= Mario's eye height
|
||||
f32 yOff = 125.f;
|
||||
f32 posY;
|
||||
|
|
@ -2092,6 +2145,8 @@ s16 update_default_camera(struct Camera *c) {
|
|||
handle_c_button_movement(c);
|
||||
vec3f_get_dist_and_angle(sMarioCamState->pos, c->pos, &dist, &pitch, &yaw);
|
||||
|
||||
gCameraZoomDist += gAdditionalCameraDistance;
|
||||
|
||||
// If C-Down is active, determine what distance the camera should be from Mario
|
||||
if (gCameraMovementFlags & CAM_MOVE_ZOOMED_OUT) {
|
||||
//! In Mario mode, the camera is zoomed out further than in Lakitu mode (1400 vs 1200)
|
||||
|
|
@ -2372,6 +2427,17 @@ s16 update_default_camera(struct Camera *c) {
|
|||
if (gCurrLevelArea == AREA_WDW_TOWN) {
|
||||
yaw = clamp_positions_and_find_yaw(c->pos, c->focus, 2254.f, -3789.f, 3790.f, -2253.f);
|
||||
}
|
||||
|
||||
if (gCenterCam) {
|
||||
if (gPlayer1Controller->buttonPressed & L_TRIG) {
|
||||
if (yaw != sMarioCamState->faceAngle[1] + DEGREES(180)) {
|
||||
yaw = sMarioCamState->faceAngle[1] + DEGREES(180);
|
||||
focus_on_mario(c->focus, c->pos, 0.0f, 0.0f, dist, pitch, yaw);
|
||||
}
|
||||
play_sound_rbutton_changed();
|
||||
}
|
||||
}
|
||||
|
||||
return yaw;
|
||||
}
|
||||
|
||||
|
|
@ -5024,6 +5090,17 @@ void handle_c_button_movement(struct Camera *c) {
|
|||
sCSideButtonYaw = cSideYaw;
|
||||
}
|
||||
}
|
||||
|
||||
// Analog camera code
|
||||
if (gPlayer1Controller->stick2X != 0) {
|
||||
if (gPlayer1Controller->stick2X > 0) {
|
||||
gCameraMovementFlags &= ~(CAM_MOVE_ROTATE_RIGHT | CAM_MOVE_ENTERED_ROTATE_SURFACE);
|
||||
}
|
||||
else {
|
||||
gCameraMovementFlags &= ~(CAM_MOVE_ROTATE_LEFT | CAM_MOVE_ENTERED_ROTATE_SURFACE);
|
||||
}
|
||||
sCSideButtonYaw = ANALOG_AMOUNT * (gPlayer1Controller->stick2X / 32.0f) * gCameraSpeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7055,8 +7132,8 @@ void player2_rotate_cam(struct Camera *c, s16 minPitch, s16 maxPitch, s16 minYaw
|
|||
s16 pitch, yaw, pitchCap;
|
||||
|
||||
// Change the camera rotation to match the 2nd player's stick
|
||||
approach_s16_asymptotic_bool(&sCreditsPlayer2Yaw, -(s16)(gPlayer2Controller->stickX * 250.f), 4);
|
||||
approach_s16_asymptotic_bool(&sCreditsPlayer2Pitch, -(s16)(gPlayer2Controller->stickY * 265.f), 4);
|
||||
approach_s16_asymptotic_bool(&sCreditsPlayer2Yaw, -(s16)(gPlayer1Controller->stick2X * 250.f), 4);
|
||||
approach_s16_asymptotic_bool(&sCreditsPlayer2Pitch, -(s16)(gPlayer1Controller->stick2Y * 265.f), 4);
|
||||
vec3f_get_dist_and_angle(c->pos, c->focus, &distCamToFocus, &pitch, &yaw);
|
||||
|
||||
pitchCap = 0x3800 - pitch; if (pitchCap < 0) {
|
||||
|
|
@ -11443,7 +11520,7 @@ Gfx *geo_camera_fov(s32 callContext, struct GraphNode *g, UNUSED void *context)
|
|||
}
|
||||
}
|
||||
|
||||
perspective->fov = sFOVState.fov;
|
||||
perspective->fov = sFOVState.fov + gAdditionalFOV;
|
||||
shake_camera_fov(perspective);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include "thread6.h"
|
||||
#include <prevent_bss_reordering.h>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
// FIXME: I'm not sure all of these variables belong in this file, but I don't
|
||||
// know of a good way to split them
|
||||
struct Controller gControllers[3];
|
||||
|
|
@ -45,6 +47,10 @@ struct MarioAnimation D_80339D10;
|
|||
struct MarioAnimation gDemo;
|
||||
UNUSED u8 filler80339D30[0x90];
|
||||
|
||||
s8 gCanMirror = 0;
|
||||
s8 gReimportTextures = 0;
|
||||
s8 gBooDialogueWasSaid = 0;
|
||||
|
||||
int unused8032C690 = 0;
|
||||
u32 gGlobalTimer = 0;
|
||||
|
||||
|
|
@ -59,6 +65,26 @@ struct DemoInput *gCurrDemoInput = NULL; // demo input sequence
|
|||
u16 gDemoInputListID = 0;
|
||||
struct DemoInput gRecordedDemoInput = { 0 }; // possibly removed in EU. TODO: Check
|
||||
|
||||
s8 get_mirror() {
|
||||
if (gEncoreMode == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gCurrCourseNum == COURSE_CAKE_END) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return gCanMirror;
|
||||
}
|
||||
|
||||
s16 get_palette() {
|
||||
if (!gEncoreMode || !gCanMirror) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return gCurrCourseNum+1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the Reality Display Processor (RDP).
|
||||
* This function initializes settings such as texture filtering mode,
|
||||
|
|
@ -76,7 +102,12 @@ void my_rdp_init(void) {
|
|||
gDPSetTextureLUT(gDisplayListHead++, G_TT_NONE);
|
||||
gDPSetTextureDetail(gDisplayListHead++, G_TD_CLAMP);
|
||||
gDPSetTexturePersp(gDisplayListHead++, G_TP_PERSP);
|
||||
if (gNearestNeighbor) {
|
||||
gDPSetTextureFilter(gDisplayListHead++, G_TF_POINT);
|
||||
}
|
||||
else {
|
||||
gDPSetTextureFilter(gDisplayListHead++, G_TF_BILERP);
|
||||
}
|
||||
gDPSetTextureConvert(gDisplayListHead++, G_TC_FILT);
|
||||
|
||||
gDPSetCombineKey(gDisplayListHead++, G_CK_NONE);
|
||||
|
|
@ -378,6 +409,8 @@ void adjust_analog_stick(struct Controller *controller) {
|
|||
// reset the controller's x and y floats.
|
||||
controller->stickX = 0;
|
||||
controller->stickY = 0;
|
||||
controller->stick2X = 0;
|
||||
controller->stick2Y = 0;
|
||||
|
||||
// modulate the rawStickX and rawStickY to be the new f32 values by adding/subtracting 6.
|
||||
if (controller->rawStickX <= -8) {
|
||||
|
|
@ -396,9 +429,28 @@ void adjust_analog_stick(struct Controller *controller) {
|
|||
controller->stickY = controller->rawStickY - 6;
|
||||
}
|
||||
|
||||
if (controller->rawStick2X <= -8) {
|
||||
controller->stick2X = controller->rawStick2X + 6;
|
||||
}
|
||||
|
||||
if (controller->rawStick2X >= 8) {
|
||||
controller->stick2X = controller->rawStick2X - 6;
|
||||
}
|
||||
|
||||
if (controller->rawStick2Y <= -8) {
|
||||
controller->stick2Y = controller->rawStick2Y + 6;
|
||||
}
|
||||
|
||||
if (controller->rawStick2Y >= 8) {
|
||||
controller->stick2Y = controller->rawStick2Y - 6;
|
||||
}
|
||||
|
||||
// calculate f32 magnitude from the center by vector length.
|
||||
controller->stickMag =
|
||||
sqrtf(controller->stickX * controller->stickX + controller->stickY * controller->stickY);
|
||||
controller->stick2Mag =
|
||||
sqrtf(controller->stick2X * controller->stick2X + controller->stick2Y * controller->stick2Y);
|
||||
|
||||
|
||||
// magnitude cannot exceed 64.0f: if it does, modify the values appropriately to
|
||||
// flatten the values down to the allowed maximum value.
|
||||
|
|
@ -407,6 +459,11 @@ void adjust_analog_stick(struct Controller *controller) {
|
|||
controller->stickY *= 64 / controller->stickMag;
|
||||
controller->stickMag = 64;
|
||||
}
|
||||
if (controller->stick2Mag > 64) {
|
||||
controller->stick2X *= 64 / controller->stick2Mag;
|
||||
controller->stick2Y *= 64 / controller->stick2Mag;
|
||||
controller->stick2Mag = 64;
|
||||
}
|
||||
}
|
||||
|
||||
// if a demo sequence exists, this will run the demo
|
||||
|
|
@ -495,8 +552,23 @@ void read_controller_inputs(void) {
|
|||
// if we're receiving inputs, update the controller struct
|
||||
// with the new button info.
|
||||
if (controller->controllerData != NULL) {
|
||||
|
||||
controller->rawStickX = controller->controllerData->stick_x;
|
||||
controller->rawStickY = controller->controllerData->stick_y;
|
||||
|
||||
if (gDpadInput) {
|
||||
controller->rawStickX += (((controller->buttonDown & R_JPAD) > 0) - ((controller->buttonDown & L_JPAD) > 0))*80;
|
||||
controller->rawStickY += (((controller->buttonDown & U_JPAD) > 0) - ((controller->buttonDown & D_JPAD) > 0))*80;
|
||||
}
|
||||
|
||||
controller->rawStick2X = controller->controllerData->stick2_x;
|
||||
controller->rawStick2Y = controller->controllerData->stick2_y;
|
||||
|
||||
if (get_mirror()) {
|
||||
controller->rawStickX *= -1;
|
||||
controller->rawStick2X *= -1;
|
||||
}
|
||||
|
||||
controller->buttonPressed = controller->controllerData->button
|
||||
& (controller->controllerData->button ^ controller->buttonDown);
|
||||
// 0.5x A presses are a good meme
|
||||
|
|
@ -506,10 +578,14 @@ void read_controller_inputs(void) {
|
|||
{
|
||||
controller->rawStickX = 0;
|
||||
controller->rawStickY = 0;
|
||||
controller->rawStick2X = 0;
|
||||
controller->rawStick2Y = 0;
|
||||
controller->buttonPressed = 0;
|
||||
controller->buttonDown = 0;
|
||||
controller->stickX = 0;
|
||||
controller->stickY = 0;
|
||||
controller->stick2X = 0;
|
||||
controller->stick2Y = 0;
|
||||
controller->stickMag = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ extern struct MarioAnimation gDemo;
|
|||
extern u8 gMarioAnims[];
|
||||
extern u8 gDemoInputs[];
|
||||
|
||||
extern s8 gCanMirror;
|
||||
extern s8 gReimportTextures;
|
||||
extern s8 gBooDialogueWasSaid;
|
||||
|
||||
extern u16 frameBufferIndex;
|
||||
extern u32 gGlobalTimer;
|
||||
|
||||
|
|
|
|||
198
src/game/hud.c
198
src/game/hud.c
|
|
@ -14,6 +14,8 @@
|
|||
#include "save_file.h"
|
||||
#include "print.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
/* @file hud.c
|
||||
* This file implements HUD rendering and power meter animations.
|
||||
* That includes stars, lives, coins, camera status, power meter, timer
|
||||
|
|
@ -53,6 +55,25 @@ static struct PowerMeterHUD sPowerMeterHUD = {
|
|||
// when the power meter is hidden.
|
||||
s32 sPowerMeterVisibleTimer = 0;
|
||||
|
||||
// Custom left and right snapping functions
|
||||
s32 get_left(s32 value) {
|
||||
if (gCenterHud || gDrawPillarbox) {
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
return GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(value);
|
||||
}
|
||||
}
|
||||
s32 get_right(s32 value) {
|
||||
if (gCenterHud || gDrawPillarbox) {
|
||||
return SCREEN_WIDTH-value;
|
||||
}
|
||||
else {
|
||||
return GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct UnusedHUDStruct sUnusedHUDValues = { 0x00, 0x0A, 0x00 };
|
||||
|
||||
static struct CameraHUD sCameraHUD = { CAM_STATUS_NONE };
|
||||
|
|
@ -116,7 +137,25 @@ void render_dl_power_meter(s16 numHealthWedges) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (gNewHud == 2) {
|
||||
if (get_mirror()) {
|
||||
guTranslate(mtx, SCREEN_WIDTH - get_right(46), (f32) sPowerMeterHUD.y, 0);
|
||||
}
|
||||
else {
|
||||
guTranslate(mtx, get_right(46), (f32) sPowerMeterHUD.y, 0);
|
||||
}
|
||||
}
|
||||
else if (gNewHud == 1) {
|
||||
guTranslate(mtx, SCREEN_WIDTH/2, (f32) sPowerMeterHUD.y, 0);
|
||||
}
|
||||
else {
|
||||
if (get_mirror()) {
|
||||
guTranslate(mtx, SCREEN_WIDTH - (f32) sPowerMeterHUD.x, (f32) sPowerMeterHUD.y, 0);
|
||||
}
|
||||
else {
|
||||
guTranslate(mtx, (f32) sPowerMeterHUD.x, (f32) sPowerMeterHUD.y, 0);
|
||||
}
|
||||
}
|
||||
|
||||
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx++),
|
||||
G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);
|
||||
|
|
@ -229,6 +268,7 @@ void handle_power_meter_actions(s16 numHealthWedges) {
|
|||
void render_hud_power_meter(void) {
|
||||
s16 shownHealthWedges = gHudDisplay.wedges;
|
||||
|
||||
if ((gNewHud < 2) && (!gAlwaysShowHealth)) {
|
||||
if (sPowerMeterHUD.animation != POWER_METER_HIDING) {
|
||||
handle_power_meter_actions(shownHealthWedges);
|
||||
}
|
||||
|
|
@ -250,10 +290,17 @@ void render_hud_power_meter(void) {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sPowerMeterHUD.y = 200;
|
||||
handle_power_meter_actions(shownHealthWedges);
|
||||
}
|
||||
|
||||
render_dl_power_meter(shownHealthWedges);
|
||||
|
||||
if ((gNewHud < 2) && (!gAlwaysShowHealth)) {
|
||||
sPowerMeterVisibleTimer += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VERSION_JP
|
||||
|
|
@ -262,22 +309,59 @@ void render_hud_power_meter(void) {
|
|||
#define HUD_TOP_Y 209
|
||||
#endif
|
||||
|
||||
#define HUD_TOP_Y_NEW 212
|
||||
#define HUD_LEFT_X 22
|
||||
|
||||
/**
|
||||
* Renders the amount of lives Mario has.
|
||||
*/
|
||||
void render_hud_mario_lives(void) {
|
||||
print_text(GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(22), HUD_TOP_Y, ","); // 'Mario Head' glyph
|
||||
print_text(GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(38), HUD_TOP_Y, "*"); // 'X' glyph
|
||||
print_text_fmt_int(GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(54), HUD_TOP_Y, "%d", gHudDisplay.lives);
|
||||
s32 x;
|
||||
s32 y;
|
||||
if (gNewHud == 2) {
|
||||
x = get_left(HUD_LEFT_X)+64;
|
||||
y = HUD_TOP_Y_NEW;
|
||||
}
|
||||
else if (gNewHud == 1) {
|
||||
x = get_left(HUD_LEFT_X);
|
||||
y = HUD_TOP_Y_NEW;
|
||||
}
|
||||
else {
|
||||
x = get_left(22);
|
||||
y = HUD_TOP_Y;
|
||||
}
|
||||
/*if (gLifeMode) {
|
||||
print_text(x, y, "Q"); // The new'Mario Head' glyph
|
||||
}
|
||||
else {*/
|
||||
print_text(x, y, ","); // 'Mario Head' glyph
|
||||
//}
|
||||
if (gNewHud > 0) {
|
||||
print_text(x+17, y, "*"); // 'X' glyph
|
||||
print_text_fmt_int(x+33, y, "%d", gHudDisplay.lives);
|
||||
}
|
||||
else {
|
||||
print_text(x+16, y, "*"); // 'X' glyph
|
||||
print_text_fmt_int(x+32, y, "%d", gHudDisplay.lives);
|
||||
}
|
||||
}
|
||||
|
||||
#define HUD_COIN_X 168
|
||||
|
||||
/**
|
||||
* Renders the amount of coins collected.
|
||||
*/
|
||||
void render_hud_coins(void) {
|
||||
print_text(168, HUD_TOP_Y, "+"); // 'Coin' glyph
|
||||
print_text(184, HUD_TOP_Y, "*"); // 'X' glyph
|
||||
print_text_fmt_int(198, HUD_TOP_Y, "%d", gHudDisplay.coins);
|
||||
if (gNewHud > 0) {
|
||||
print_text(get_left(HUD_LEFT_X), HUD_TOP_Y_NEW-18, "+"); // 'Coin' glyph
|
||||
print_text(get_left(HUD_LEFT_X)+17, HUD_TOP_Y_NEW-18, "*"); // 'X' glyph
|
||||
print_text_fmt_int(get_left(HUD_LEFT_X)+33, HUD_TOP_Y_NEW-18, "%d", gHudDisplay.coins);
|
||||
}
|
||||
else {
|
||||
print_text(HUD_COIN_X, HUD_TOP_Y, "+"); // 'Coin' glyph
|
||||
print_text(HUD_COIN_X+16, HUD_TOP_Y, "*"); // 'X' glyph
|
||||
print_text_fmt_int(HUD_COIN_X+30, HUD_TOP_Y, "%d", gHudDisplay.coins);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VERSION_JP
|
||||
|
|
@ -286,6 +370,8 @@ void render_hud_coins(void) {
|
|||
#define HUD_STARS_X 78
|
||||
#endif
|
||||
|
||||
#define HUD_STARS_X_NEW 76
|
||||
|
||||
/**
|
||||
* Renders the amount of stars collected.
|
||||
* Disables "X" glyph when Mario has 100 stars or more.
|
||||
|
|
@ -297,16 +383,50 @@ void render_hud_stars(void) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (gNewHud == 2) {
|
||||
if (gHudDisplay.stars < 10) {
|
||||
print_text(get_left(HUD_LEFT_X), HUD_TOP_Y_NEW, "-"); // 'Star' glyph
|
||||
print_text(get_left(HUD_LEFT_X) + 17, HUD_TOP_Y_NEW, "*"); // 'X' glyph
|
||||
print_text_fmt_int(get_left(HUD_LEFT_X) + 33, HUD_TOP_Y_NEW, "%d", gHudDisplay.stars);
|
||||
}
|
||||
else if (gHudDisplay.stars < 100) {
|
||||
print_text(get_left(HUD_LEFT_X), HUD_TOP_Y_NEW, "-"); // 'Star' glyph
|
||||
print_text(get_left(HUD_LEFT_X) + 15, HUD_TOP_Y_NEW, "*"); // 'X' glyph
|
||||
print_text_fmt_int(get_left(HUD_LEFT_X) + 31, HUD_TOP_Y_NEW, "%d", gHudDisplay.stars);
|
||||
}
|
||||
else {
|
||||
print_text(get_left(HUD_LEFT_X), HUD_TOP_Y_NEW, "-"); // 'Star' glyph
|
||||
print_text_fmt_int(get_left(HUD_LEFT_X) + 15, HUD_TOP_Y_NEW, "%d", gHudDisplay.stars);
|
||||
}
|
||||
}
|
||||
else if (gNewHud == 1) {
|
||||
if (gHudDisplay.stars < 10) {
|
||||
print_text(get_right(HUD_STARS_X_NEW) + 6, HUD_TOP_Y_NEW, "-"); // 'Star' glyph
|
||||
print_text(get_right(HUD_STARS_X_NEW) + 23, HUD_TOP_Y_NEW, "*"); // 'X' glyph
|
||||
print_text_fmt_int(get_right(HUD_STARS_X_NEW) + 39, HUD_TOP_Y_NEW, "%d", gHudDisplay.stars);
|
||||
}
|
||||
else if (gHudDisplay.stars < 100) {
|
||||
print_text(get_right(HUD_STARS_X_NEW) - 4, HUD_TOP_Y_NEW, "-"); // 'Star' glyph
|
||||
print_text(get_right(HUD_STARS_X_NEW) + 11, HUD_TOP_Y_NEW, "*"); // 'X' glyph
|
||||
print_text_fmt_int(get_right(HUD_STARS_X_NEW) + 27, HUD_TOP_Y_NEW, "%d", gHudDisplay.stars);
|
||||
}
|
||||
else {
|
||||
print_text(get_right(HUD_STARS_X_NEW), HUD_TOP_Y_NEW, "-"); // 'Star' glyph
|
||||
print_text_fmt_int(get_right(HUD_STARS_X_NEW) + 15, HUD_TOP_Y_NEW, "%d", gHudDisplay.stars);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (gHudDisplay.stars < 100) {
|
||||
showX = 1;
|
||||
}
|
||||
|
||||
print_text(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(HUD_STARS_X), HUD_TOP_Y, "-"); // 'Star' glyph
|
||||
print_text(get_right(HUD_STARS_X), HUD_TOP_Y, "-"); // 'Star' glyph
|
||||
if (showX == 1) {
|
||||
print_text(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(HUD_STARS_X) + 16, HUD_TOP_Y, "*"); // 'X' glyph
|
||||
print_text(get_right(HUD_STARS_X) + 16, HUD_TOP_Y, "*"); // 'X' glyph
|
||||
}
|
||||
print_text_fmt_int((showX * 14) + GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(HUD_STARS_X - 16),
|
||||
print_text_fmt_int((showX * 14) + get_right(HUD_STARS_X - 16),
|
||||
HUD_TOP_Y, "%d", gHudDisplay.stars);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -336,13 +456,13 @@ void render_hud_timer(void) {
|
|||
#ifdef VERSION_EU
|
||||
switch (eu_get_language()) {
|
||||
case LANGUAGE_ENGLISH:
|
||||
print_text(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(150), 185, "TIME");
|
||||
print_text(get_right(150), 185, "TIME");
|
||||
break;
|
||||
case LANGUAGE_FRENCH:
|
||||
print_text(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(155), 185, "TEMPS");
|
||||
print_text(get_right(155), 185, "TEMPS");
|
||||
break;
|
||||
case LANGUAGE_GERMAN:
|
||||
print_text(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(150), 185, "ZEIT");
|
||||
print_text(get_right(150), 185, "ZEIT");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -350,15 +470,32 @@ void render_hud_timer(void) {
|
|||
timerSecs = (timerValFrames - (timerMins * 1800)) / 30;
|
||||
|
||||
timerFracSecs = ((timerValFrames - (timerMins * 1800) - (timerSecs * 30)) & 0xFFFF) / 3;
|
||||
#ifndef VERSION_EU
|
||||
print_text(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(150), 185, "TIME");
|
||||
#endif
|
||||
print_text_fmt_int(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(91), 185, "%0d", timerMins);
|
||||
print_text_fmt_int(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(71), 185, "%02d", timerSecs);
|
||||
print_text_fmt_int(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(37), 185, "%d", timerFracSecs);
|
||||
|
||||
if (gNewHud != 0) {
|
||||
s32 add;
|
||||
if (gNewHud == 2)
|
||||
add = 157;
|
||||
else
|
||||
add = 0;
|
||||
print_text(get_right(151), HUD_TOP_Y_NEW-18-add, "TIME");
|
||||
print_text_fmt_int(get_right(92), HUD_TOP_Y_NEW-18-add, "%0d", timerMins);
|
||||
print_text_fmt_int(get_right(72), HUD_TOP_Y_NEW-18-add, "%02d", timerSecs);
|
||||
print_text_fmt_int(get_right(38), HUD_TOP_Y_NEW-18-add, "%d", timerFracSecs);
|
||||
gSPDisplayList(gDisplayListHead++, dl_hud_img_begin);
|
||||
render_hud_tex_lut(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(81), 32, (*hudLUT)[GLYPH_APOSTROPHE]);
|
||||
render_hud_tex_lut(GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(46), 32, (*hudLUT)[GLYPH_DOUBLE_QUOTE]);
|
||||
render_hud_tex_lut(get_right(82), 23+add, (*hudLUT)[GLYPH_APOSTROPHE]);
|
||||
render_hud_tex_lut(get_right(47), 23+add, (*hudLUT)[GLYPH_DOUBLE_QUOTE]);
|
||||
}
|
||||
else {
|
||||
#ifndef VERSION_EU
|
||||
print_text(get_right(150), 185, "TIME");
|
||||
#endif
|
||||
print_text_fmt_int(get_right(91), 185, "%0d", timerMins);
|
||||
print_text_fmt_int(get_right(71), 185, "%02d", timerSecs);
|
||||
print_text_fmt_int(get_right(37), 185, "%d", timerFracSecs);
|
||||
gSPDisplayList(gDisplayListHead++, dl_hud_img_begin);
|
||||
render_hud_tex_lut(get_right(81), 32, (*hudLUT)[GLYPH_APOSTROPHE]);
|
||||
render_hud_tex_lut(get_right(46), 32, (*hudLUT)[GLYPH_DOUBLE_QUOTE]);
|
||||
}
|
||||
gSPDisplayList(gDisplayListHead++, dl_hud_img_end);
|
||||
}
|
||||
|
||||
|
|
@ -380,8 +517,14 @@ void render_hud_camera_status(void) {
|
|||
s32 y;
|
||||
|
||||
cameraLUT = segmented_to_virtual(&main_hud_camera_lut);
|
||||
x = GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(54);
|
||||
if (gNewHud == 1) {
|
||||
x = get_right(53);
|
||||
y = 208;
|
||||
}
|
||||
else {
|
||||
x = get_right(54);
|
||||
y = 205;
|
||||
}
|
||||
|
||||
if (sCameraHUD.status == CAM_STATUS_NONE) {
|
||||
return;
|
||||
|
|
@ -414,6 +557,13 @@ void render_hud_camera_status(void) {
|
|||
gSPDisplayList(gDisplayListHead++, dl_hud_img_end);
|
||||
}
|
||||
|
||||
// The sides for the 4:3 mode
|
||||
void render_sides(void) {
|
||||
gDPSetFillColor(gDisplayListHead++, GPACK_RGBA5551(0, 0, 0, 1));
|
||||
gDPFillRectangle(gDisplayListHead++, GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(0), 0, 0, SCREEN_HEIGHT);
|
||||
gDPFillRectangle(gDisplayListHead++, SCREEN_WIDTH, 0, GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render HUD strings using hudDisplayFlags with it's render functions,
|
||||
* excluding the cannon reticle which detects a camera preset for it.
|
||||
|
|
@ -451,7 +601,7 @@ void render_hud(void) {
|
|||
render_hud_cannon_reticle();
|
||||
}
|
||||
|
||||
if (hudDisplayFlags & HUD_DISPLAY_FLAG_LIVES) {
|
||||
if (hudDisplayFlags & HUD_DISPLAY_FLAG_LIVES && !(save_file_get_flags() & SAVE_FLAG_HARDCORE_MODE)) {
|
||||
render_hud_mario_lives();
|
||||
}
|
||||
|
||||
|
|
@ -475,5 +625,9 @@ void render_hud(void) {
|
|||
if (hudDisplayFlags & HUD_DISPLAY_FLAG_TIMER) {
|
||||
render_hud_timer();
|
||||
}
|
||||
|
||||
if (gDrawPillarbox) {
|
||||
render_sides();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
#include "text_strings.h"
|
||||
#include "types.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
u16 gDialogColorFadeTimer;
|
||||
s8 gLastDialogLineNum;
|
||||
s32 gDialogVariable;
|
||||
|
|
@ -2251,8 +2253,13 @@ void render_pause_my_score_coins(void) {
|
|||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha);
|
||||
|
||||
if (courseIndex < COURSE_STAGES_COUNT && save_file_get_course_star_count(gCurrSaveFileNum - 1, courseIndex) != 0) {
|
||||
if (get_mirror()) {
|
||||
print_generic_string(280-MYSCORE_X, 121, textMyScore);
|
||||
}
|
||||
else {
|
||||
print_generic_string(MYSCORE_X, 121, textMyScore);
|
||||
}
|
||||
}
|
||||
|
||||
courseName = segmented_to_virtual(courseNameTbl[courseIndex]);
|
||||
|
||||
|
|
@ -2628,7 +2635,7 @@ s16 render_pause_courses_and_castle(void) {
|
|||
render_pause_my_score_coins();
|
||||
render_pause_red_coins();
|
||||
|
||||
if (gMarioStates[0].action & ACT_FLAG_PAUSE_EXIT) {
|
||||
if (gLeaveAnyTime || gMarioStates[0].action & ACT_FLAG_PAUSE_EXIT) {
|
||||
render_pause_course_options(99, 93, &gDialogLineNum, 15);
|
||||
}
|
||||
|
||||
|
|
@ -2767,9 +2774,11 @@ void print_hud_course_complete_coins(s16 x, s16 y) {
|
|||
|
||||
if (gCourseCompleteCoins == 50 || gCourseCompleteCoins == 100 || gCourseCompleteCoins == 150) {
|
||||
play_sound(SOUND_GENERAL_COLLECT_1UP, gDefaultSoundArgs);
|
||||
if (!gLifeMode) {
|
||||
gMarioState[0].numLives++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gHudDisplay.coins == gCourseCompleteCoins && gGotFileCoinHiScore != 0) {
|
||||
play_sound(SOUND_MENU_MARIO_CASTLE_WARP2, gDefaultSoundArgs);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include "sound_init.h"
|
||||
#include "thread6.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#define INT_GROUND_POUND_OR_TWIRL (1 << 0) // 0x01
|
||||
#define INT_PUNCH (1 << 1) // 0x02
|
||||
#define INT_KICK (1 << 2) // 0x04
|
||||
|
|
@ -769,6 +771,12 @@ u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct O
|
|||
u32 noExit = (o->oInteractionSubtype & INT_SUBTYPE_NO_EXIT) != 0;
|
||||
u32 grandStar = (o->oInteractionSubtype & INT_SUBTYPE_GRAND_STAR) != 0;
|
||||
|
||||
// Don't kick Mario if staying in levels is active
|
||||
if (gDontKick && gCurrLevelNum != LEVEL_BOWSER_1 && gCurrLevelNum != LEVEL_BOWSER_2
|
||||
&& gCurrLevelNum != LEVEL_CASTLE && gCurrLevelNum != LEVEL_CASTLE_COURTYARD && gCurrLevelNum != LEVEL_CASTLE_GROUNDS) {
|
||||
noExit = 1;
|
||||
}
|
||||
|
||||
if (m->health >= 0x100) {
|
||||
mario_stop_riding_and_holding(m);
|
||||
#ifdef VERSION_SH
|
||||
|
|
@ -1018,7 +1026,7 @@ u32 interact_door(struct MarioState *m, UNUSED u32 interactType, struct Object *
|
|||
enterDoorAction = ACT_ENTERING_STAR_DOOR;
|
||||
}
|
||||
|
||||
if (doorSaveFileFlag != 0 && !(save_file_get_flags() & doorSaveFileFlag)) {
|
||||
if (!gSkipCutscenes && doorSaveFileFlag != 0 && !(save_file_get_flags() & doorSaveFileFlag)) {
|
||||
enterDoorAction = ACT_UNLOCKING_STAR_DOOR;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include "course_table.h"
|
||||
#include "thread6.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#define PLAY_MODE_NORMAL 0
|
||||
#define PLAY_MODE_PAUSED 2
|
||||
#define PLAY_MODE_CHANGE_AREA 3
|
||||
|
|
@ -726,7 +728,11 @@ s16 level_trigger_warp(struct MarioState *m, s32 warpOp) {
|
|||
break;
|
||||
|
||||
case WARP_OP_DEATH:
|
||||
if (m->numLives == 0) {
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARDCORE_MODE) {
|
||||
sDelayedWarpOp = WARP_OP_GAME_OVER;
|
||||
save_file_erase(gCurrSaveFileNum - 1);
|
||||
}
|
||||
if (m->numLives == 0 && gLifeMode == 0) {
|
||||
sDelayedWarpOp = WARP_OP_GAME_OVER;
|
||||
}
|
||||
sDelayedWarpTimer = 48;
|
||||
|
|
@ -738,9 +744,14 @@ s16 level_trigger_warp(struct MarioState *m, s32 warpOp) {
|
|||
case WARP_OP_WARP_FLOOR:
|
||||
sSourceWarpNodeId = WARP_NODE_WARP_FLOOR;
|
||||
if (area_get_warp_node(sSourceWarpNodeId) == NULL) {
|
||||
if (m->numLives == 0) {
|
||||
if (save_file_get_flags() & SAVE_FLAG_HARDCORE_MODE) {
|
||||
sDelayedWarpOp = WARP_OP_GAME_OVER;
|
||||
} else {
|
||||
save_file_erase(gCurrSaveFileNum - 1);
|
||||
}
|
||||
else if (m->numLives == 0 && gLifeMode == 0) {
|
||||
sDelayedWarpOp = WARP_OP_GAME_OVER;
|
||||
}
|
||||
else {
|
||||
sSourceWarpNodeId = WARP_NODE_DEATH;
|
||||
}
|
||||
}
|
||||
|
|
@ -865,9 +876,26 @@ void initiate_delayed_warp(void) {
|
|||
destWarpNode, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
case WARP_OP_STAR_EXIT:
|
||||
warpNode = area_get_warp_node(sSourceWarpNodeId);
|
||||
|
||||
initiate_warp(warpNode->node.destLevel & 0x7F, warpNode->node.destArea,
|
||||
warpNode->node.destNode, sDelayedWarpArg);
|
||||
|
||||
check_if_should_set_warp_checkpoint(&warpNode->node);
|
||||
if (sWarpDest.type != WARP_TYPE_CHANGE_LEVEL) {
|
||||
level_set_transition(2, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (gRemoveAnnoyingWarps && (sDelayedWarpOp & WARP_OP_TRIGGERS_LEVEL_SELECT)) {
|
||||
warpNode = area_get_warp_node(WARP_NODE_DEATH);
|
||||
}
|
||||
else {
|
||||
warpNode = area_get_warp_node(sSourceWarpNodeId);
|
||||
}
|
||||
|
||||
initiate_warp(warpNode->node.destLevel & 0x7F, warpNode->node.destArea,
|
||||
warpNode->node.destNode, sDelayedWarpArg);
|
||||
|
||||
|
|
@ -1193,6 +1221,23 @@ s32 init_level(void) {
|
|||
} else {
|
||||
set_mario_action(gMarioState, ACT_INTRO_CUTSCENE, 0);
|
||||
val4 = 1;
|
||||
if (gPlayer1Controller->buttonDown & U_CBUTTONS && gPlayer1Controller->buttonDown & R_TRIG) {
|
||||
level_trigger_warp(gMarioState, WARP_OP_CREDITS_START);
|
||||
}
|
||||
else if (gSkipCutscenes) {
|
||||
set_mario_action(gMarioState, ACT_IDLE, 0);
|
||||
} else {
|
||||
set_mario_action(gMarioState, ACT_INTRO_CUTSCENE, 0);
|
||||
val4 = 1;
|
||||
}
|
||||
}
|
||||
if (gHardSave) {
|
||||
gMarioState->flags &= ~(MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD);
|
||||
save_file_set_flags(SAVE_FLAG_HARD_MODE);
|
||||
}
|
||||
if (gHardcoreSave) {
|
||||
gMarioState->flags &= ~(MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD);
|
||||
save_file_set_flags(SAVE_FLAG_HARDCORE_MODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1318,3 +1363,10 @@ s32 lvl_play_the_end_screen_sound(UNUSED s16 arg0, UNUSED s32 arg1) {
|
|||
play_sound(SOUND_MENU_THANK_YOU_PLAYING_MY_GAME, gDefaultSoundArgs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
s32 credits_wait_for_reset() {
|
||||
if (gPlayer1Controller->buttonPressed & START_BUTTON || gPlayer1Controller->buttonPressed & A_BUTTON) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -127,6 +127,7 @@ s32 lvl_init_or_update(s16 initOrUpdate, UNUSED s32 unused);
|
|||
s32 lvl_init_from_save_file(UNUSED s16 arg0, s32 levelNum);
|
||||
s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum);
|
||||
s32 lvl_play_the_end_screen_sound(UNUSED s16 arg0, UNUSED s32 arg1);
|
||||
s32 credits_wait_for_reset();
|
||||
void basic_update(UNUSED s16 *arg);
|
||||
|
||||
#endif // LEVEL_UPDATE_H
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@
|
|||
#include "sound_init.h"
|
||||
#include "thread6.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
u32 unused80339F10;
|
||||
s8 filler80339F1C[20];
|
||||
|
||||
|
|
@ -810,8 +812,13 @@ static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actio
|
|||
case ACT_WATER_JUMP:
|
||||
case ACT_HOLD_WATER_JUMP:
|
||||
if (actionArg == 0) {
|
||||
if (gBetterControls) {
|
||||
set_mario_y_vel_based_on_fspeed(m, 48.0f, 0.0f);
|
||||
}
|
||||
else {
|
||||
set_mario_y_vel_based_on_fspeed(m, 42.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ACT_BURNING_JUMP:
|
||||
|
|
@ -831,6 +838,19 @@ static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actio
|
|||
break;
|
||||
|
||||
case ACT_WALL_KICK_AIR:
|
||||
set_mario_y_vel_based_on_fspeed(m, 62.0f, 0.0f);
|
||||
if (gBetterControls) {
|
||||
if (m->forwardVel < 28.0f) {
|
||||
m->forwardVel = 28.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (m->forwardVel < 24.0f) {
|
||||
m->forwardVel = 24.0f;
|
||||
}
|
||||
}
|
||||
m->wallKickTimer = 0;
|
||||
break;
|
||||
case ACT_TOP_OF_POLE_JUMP:
|
||||
set_mario_y_vel_based_on_fspeed(m, 62.0f, 0.0f);
|
||||
if (m->forwardVel < 24.0f) {
|
||||
|
|
@ -878,15 +898,28 @@ static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actio
|
|||
break;
|
||||
|
||||
case ACT_SLIDE_KICK:
|
||||
if (gBetterControls) {
|
||||
m->vel[1] = 14.0f;
|
||||
if (m->forwardVel < 36.0f) {
|
||||
m->forwardVel = 36.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m->vel[1] = 12.0f;
|
||||
if (m->forwardVel < 32.0f) {
|
||||
m->forwardVel = 32.0f;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ACT_JUMP_KICK:
|
||||
m->vel[1] = 20.0f;
|
||||
break;
|
||||
|
||||
case ACT_WALL_SLIDE:
|
||||
m->vel[1] = 4.0f;
|
||||
mario_set_forward_vel(m, 8.0f);
|
||||
break;
|
||||
}
|
||||
|
||||
m->peakHeight = m->pos[1];
|
||||
|
|
@ -1473,7 +1506,9 @@ void update_mario_health(struct MarioState *m) {
|
|||
// when in snow terrains lose 3 health.
|
||||
// If using the debug level select, do not lose any HP to water.
|
||||
if ((m->pos[1] >= (m->waterLevel - 140)) && !terrainIsSnow) {
|
||||
if (!save_file_get_flags() & SAVE_FLAG_HARD_MODE) {
|
||||
m->health += 0x1A;
|
||||
}
|
||||
} else if (gDebugLevelSelect == 0) {
|
||||
m->health -= (terrainIsSnow ? 3 : 1);
|
||||
}
|
||||
|
|
@ -1808,7 +1843,7 @@ void init_mario(void) {
|
|||
|
||||
if (save_file_get_flags()
|
||||
& (SAVE_FLAG_CAP_ON_GROUND | SAVE_FLAG_CAP_ON_KLEPTO | SAVE_FLAG_CAP_ON_UKIKI
|
||||
| SAVE_FLAG_CAP_ON_MR_BLIZZARD)) {
|
||||
| SAVE_FLAG_CAP_ON_MR_BLIZZARD | SAVE_FLAG_HARD_MODE)) {
|
||||
gMarioState->flags = 0;
|
||||
} else {
|
||||
gMarioState->flags = (MARIO_CAP_ON_HEAD | MARIO_NORMAL_CAP);
|
||||
|
|
@ -1892,7 +1927,12 @@ void init_mario_from_save_file(void) {
|
|||
save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1);
|
||||
gMarioState->numKeys = 0;
|
||||
|
||||
if (gLifeMode) {
|
||||
gMarioState->numLives = 0;
|
||||
}
|
||||
else {
|
||||
gMarioState->numLives = 4;
|
||||
}
|
||||
gMarioState->health = 0x880;
|
||||
|
||||
gMarioState->prevNumStarsForDialog = gMarioState->numStars;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
#include "save_file.h"
|
||||
#include "thread6.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
void play_flip_sounds(struct MarioState *m, s16 frame1, s16 frame2, s16 frame3) {
|
||||
s32 animFrame = m->marioObj->header.gfx.unk38.animFrame;
|
||||
if (animFrame == frame1 || animFrame == frame2 || animFrame == frame3) {
|
||||
|
|
@ -80,7 +82,9 @@ s32 check_fall_damage(struct MarioState *m, u32 hardFallAction) {
|
|||
if (m->action != ACT_TWIRLING && m->floor->type != SURFACE_BURNING) {
|
||||
if (m->vel[1] < -55.0f) {
|
||||
if (fallHeight > 3000.0f) {
|
||||
if (!gDisableFallDamage) {
|
||||
m->hurtCounter += (m->flags & MARIO_CAP_ON_HEAD) ? 16 : 24;
|
||||
}
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 80);
|
||||
#endif
|
||||
|
|
@ -88,7 +92,9 @@ s32 check_fall_damage(struct MarioState *m, u32 hardFallAction) {
|
|||
play_sound(SOUND_MARIO_ATTACKED, m->marioObj->header.gfx.cameraToObject);
|
||||
return drop_and_set_mario_action(m, hardFallAction, 4);
|
||||
} else if (fallHeight > damageHeight && !mario_floor_is_slippery(m)) {
|
||||
if (!gDisableFallDamage) {
|
||||
m->hurtCounter += (m->flags & MARIO_CAP_ON_HEAD) ? 8 : 12;
|
||||
}
|
||||
m->squishTimer = 30;
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 80);
|
||||
|
|
@ -104,8 +110,16 @@ s32 check_fall_damage(struct MarioState *m, u32 hardFallAction) {
|
|||
|
||||
s32 check_kick_or_dive_in_air(struct MarioState *m) {
|
||||
if (m->input & INPUT_B_PRESSED) {
|
||||
if (gBetterControls) {
|
||||
if (m->forwardVel >= 28.0f && m->controller->stickMag > 48.0f) {
|
||||
return set_mario_action(m, ACT_DIVE, 1);
|
||||
}
|
||||
return set_mario_action(m, ACT_JUMP_KICK, 0);
|
||||
}
|
||||
else {
|
||||
return set_mario_action(m, m->forwardVel > 28.0f ? ACT_DIVE : ACT_JUMP_KICK, 0);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -193,9 +207,21 @@ void update_air_with_turn(struct MarioState *m) {
|
|||
intendedDYaw = m->intendedYaw - m->faceAngle[1];
|
||||
intendedMag = m->intendedMag / 32.0f;
|
||||
|
||||
if (gBetterControls) {
|
||||
if ((m->forwardVel > 0 && intendedMag * coss(intendedDYaw) > 0) || (m->forwardVel < 0 && intendedMag * coss(intendedDYaw) < 0)) {
|
||||
if (m->action != ACT_WALL_KICK_AIR)
|
||||
m->forwardVel += intendedMag * coss(intendedDYaw) * 1.5f;
|
||||
}
|
||||
else {
|
||||
m->forwardVel += intendedMag * coss(intendedDYaw) * 3.5f;
|
||||
}
|
||||
m->faceAngle[1] += 1024.0f * sins(intendedDYaw) * intendedMag;
|
||||
}
|
||||
else {
|
||||
m->forwardVel += 1.5f * coss(intendedDYaw) * intendedMag;
|
||||
m->faceAngle[1] += 512.0f * sins(intendedDYaw) * intendedMag;
|
||||
}
|
||||
}
|
||||
|
||||
//! Uncapped air speed. Net positive when moving forward.
|
||||
if (m->forwardVel > dragThreshold) {
|
||||
|
|
@ -210,7 +236,7 @@ void update_air_with_turn(struct MarioState *m) {
|
|||
}
|
||||
}
|
||||
|
||||
void update_air_without_turn(struct MarioState *m) {
|
||||
void update_air_without_turn(struct MarioState *m, u32 canTurn) {
|
||||
f32 sidewaysSpeed = 0.0f;
|
||||
f32 dragThreshold;
|
||||
s16 intendedDYaw;
|
||||
|
|
@ -224,9 +250,39 @@ void update_air_without_turn(struct MarioState *m) {
|
|||
intendedDYaw = m->intendedYaw - m->faceAngle[1];
|
||||
intendedMag = m->intendedMag / 32.0f;
|
||||
|
||||
if (gBetterControls) {
|
||||
if ((m->forwardVel > 0 && intendedMag * coss(intendedDYaw) > 0) || (m->forwardVel < 0 && intendedMag * coss(intendedDYaw) < 0)) {
|
||||
if (m->action != ACT_WALL_KICK_AIR)
|
||||
m->forwardVel += intendedMag * coss(intendedDYaw) * 1.5f;
|
||||
}
|
||||
else {
|
||||
m->forwardVel += intendedMag * coss(intendedDYaw) * 3.5f;
|
||||
}
|
||||
if (gAirTurn && canTurn) {
|
||||
sidewaysSpeed = intendedMag * sins(intendedDYaw) * 7.5f;
|
||||
m->faceAngle[1] += 768.0f * sins(intendedDYaw) * intendedMag;
|
||||
}
|
||||
else if (canTurn) {
|
||||
sidewaysSpeed = intendedMag * sins(intendedDYaw) * 15.0f;
|
||||
m->faceAngle[1] += 320.0f * sins(intendedDYaw) * intendedMag;
|
||||
}
|
||||
else {
|
||||
sidewaysSpeed = intendedMag * sins(intendedDYaw) * 15.0f;
|
||||
m->faceAngle[1] += 64.0f * sins(intendedDYaw) * intendedMag;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
m->forwardVel += intendedMag * coss(intendedDYaw) * 1.5f;
|
||||
if (gAirTurn && canTurn) {
|
||||
sidewaysSpeed = intendedMag * sins(intendedDYaw) * 5.0f;
|
||||
m->faceAngle[1] += 768.0f * sins(intendedDYaw) * intendedMag;
|
||||
}
|
||||
else {
|
||||
sidewaysSpeed = intendedMag * sins(intendedDYaw) * 10.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Uncapped air speed. Net positive when moving forward.
|
||||
if (m->forwardVel > dragThreshold) {
|
||||
|
|
@ -368,7 +424,7 @@ void update_flying(struct MarioState *m) {
|
|||
u32 common_air_action_step(struct MarioState *m, u32 landAction, s32 animation, u32 stepArg) {
|
||||
u32 stepResult;
|
||||
|
||||
update_air_without_turn(m);
|
||||
update_air_without_turn(m, 1);
|
||||
|
||||
stepResult = perform_air_step(m, stepArg);
|
||||
switch (stepResult) {
|
||||
|
|
@ -441,6 +497,9 @@ u32 common_air_action_step(struct MarioState *m, u32 landAction, s32 animation,
|
|||
}
|
||||
|
||||
s32 act_jump(struct MarioState *m) {
|
||||
if (gDebugMovementMode) {
|
||||
set_mario_action(m, ACT_DEBUG_FREE_MOVE, 0);
|
||||
}
|
||||
if (check_kick_or_dive_in_air(m)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -654,7 +713,7 @@ s32 act_riding_shell_air(struct MarioState *m) {
|
|||
play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, 0);
|
||||
set_mario_animation(m, MARIO_ANIM_JUMP_RIDING_SHELL);
|
||||
|
||||
update_air_without_turn(m);
|
||||
update_air_without_turn(m, 1);
|
||||
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_LANDED:
|
||||
|
|
@ -732,7 +791,7 @@ s32 act_dive(struct MarioState *m) {
|
|||
}
|
||||
}
|
||||
|
||||
update_air_without_turn(m);
|
||||
update_air_without_turn(m, 0);
|
||||
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_NONE:
|
||||
|
|
@ -794,7 +853,7 @@ s32 act_air_throw(struct MarioState *m) {
|
|||
|
||||
play_sound_if_no_flag(m, SOUND_MARIO_WAH2, MARIO_MARIO_SOUND_PLAYED);
|
||||
set_mario_animation(m, MARIO_ANIM_THROW_LIGHT_OBJECT);
|
||||
update_air_without_turn(m);
|
||||
update_air_without_turn(m, 1);
|
||||
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_LANDED:
|
||||
|
|
@ -816,9 +875,16 @@ s32 act_air_throw(struct MarioState *m) {
|
|||
}
|
||||
|
||||
s32 act_water_jump(struct MarioState *m) {
|
||||
if (gBetterControls) {
|
||||
if (m->forwardVel < 20.0f) {
|
||||
mario_set_forward_vel(m, 20.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (m->forwardVel < 15.0f) {
|
||||
mario_set_forward_vel(m, 15.0f);
|
||||
}
|
||||
}
|
||||
|
||||
play_mario_sound(m, SOUND_ACTION_UNKNOWN432, 0);
|
||||
set_mario_animation(m, MARIO_ANIM_SINGLE_JUMP);
|
||||
|
|
@ -830,7 +896,12 @@ s32 act_water_jump(struct MarioState *m) {
|
|||
break;
|
||||
|
||||
case AIR_STEP_HIT_WALL:
|
||||
if (gBetterControls) {
|
||||
mario_set_forward_vel(m, 20.0f);
|
||||
}
|
||||
else {
|
||||
mario_set_forward_vel(m, 15.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
case AIR_STEP_GRABBED_LEDGE:
|
||||
|
|
@ -854,9 +925,16 @@ s32 act_hold_water_jump(struct MarioState *m) {
|
|||
return drop_and_set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (gBetterControls) {
|
||||
if (m->forwardVel < 20.0f) {
|
||||
mario_set_forward_vel(m, 20.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (m->forwardVel < 15.0f) {
|
||||
mario_set_forward_vel(m, 15.0f);
|
||||
}
|
||||
}
|
||||
|
||||
play_mario_sound(m, SOUND_ACTION_UNKNOWN432, 0);
|
||||
set_mario_animation(m, MARIO_ANIM_JUMP_WITH_LIGHT_OBJ);
|
||||
|
|
@ -868,7 +946,12 @@ s32 act_hold_water_jump(struct MarioState *m) {
|
|||
break;
|
||||
|
||||
case AIR_STEP_HIT_WALL:
|
||||
if (gBetterControls) {
|
||||
mario_set_forward_vel(m, 20.0f);
|
||||
}
|
||||
else {
|
||||
mario_set_forward_vel(m, 15.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
case AIR_STEP_HIT_LAVA_WALL:
|
||||
|
|
@ -912,6 +995,7 @@ s32 act_steep_jump(struct MarioState *m) {
|
|||
s32 act_ground_pound(struct MarioState *m) {
|
||||
u32 stepResult;
|
||||
f32 yOffset;
|
||||
u8 lagTime;
|
||||
|
||||
play_sound_if_no_flag(m, SOUND_ACTION_THROW, MARIO_ACTION_SOUND_PLAYED);
|
||||
|
||||
|
|
@ -925,7 +1009,13 @@ s32 act_ground_pound(struct MarioState *m) {
|
|||
}
|
||||
}
|
||||
|
||||
else if (gBetterControls) {
|
||||
m->vel[1] = -54.0f;
|
||||
}
|
||||
else {
|
||||
m->vel[1] = -50.0f;
|
||||
}
|
||||
|
||||
mario_set_forward_vel(m, 0.0f);
|
||||
|
||||
set_mario_animation(m, m->actionArg == 0 ? MARIO_ANIM_START_GROUND_POUND
|
||||
|
|
@ -935,10 +1025,22 @@ s32 act_ground_pound(struct MarioState *m) {
|
|||
}
|
||||
|
||||
m->actionTimer++;
|
||||
if (m->actionTimer >= m->marioObj->header.gfx.unk38.curAnim->unk08 + 4) {
|
||||
if (gBetterControls) {
|
||||
lagTime = 2;
|
||||
}
|
||||
else {
|
||||
lagTime = 4;
|
||||
}
|
||||
if (m->actionTimer >= m->marioObj->header.gfx.unk38.curAnim->unk08 + lagTime) {
|
||||
play_sound(SOUND_MARIO_GROUND_POUND_WAH, m->marioObj->header.gfx.cameraToObject);
|
||||
m->actionState = 1;
|
||||
}
|
||||
|
||||
if (gOdysseyDive && m->input & INPUT_B_PRESSED) {
|
||||
set_mario_action(m, ACT_DIVE, 0);
|
||||
mario_set_forward_vel(m, 24.0f);
|
||||
m->vel[1] = 28;
|
||||
}
|
||||
} else {
|
||||
set_mario_animation(m, MARIO_ANIM_GROUND_POUND);
|
||||
|
||||
|
|
@ -1058,7 +1160,7 @@ s32 act_crazy_box_bounce(struct MarioState *m) {
|
|||
play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, 0);
|
||||
set_mario_animation(m, MARIO_ANIM_DIVE);
|
||||
|
||||
update_air_without_turn(m);
|
||||
update_air_without_turn(m, 0);
|
||||
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_LANDED:
|
||||
|
|
@ -1141,12 +1243,45 @@ u32 common_air_knockback_step(struct MarioState *m, u32 landAction, u32 hardFall
|
|||
s32 check_wall_kick(struct MarioState *m) {
|
||||
if ((m->input & INPUT_A_PRESSED) && m->wallKickTimer != 0 && m->prevAction == ACT_AIR_HIT_WALL) {
|
||||
m->faceAngle[1] += 0x8000;
|
||||
if (gBetterControls) {
|
||||
m->particleFlags |= PARTICLE_VERTICAL_STAR;
|
||||
}
|
||||
return set_mario_action(m, ACT_WALL_KICK_AIR, 0);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_wall_slide(struct MarioState *m) {
|
||||
m->marioObj->header.gfx.angle[1] = m->faceAngle[1];
|
||||
if (m->input & INPUT_A_PRESSED) {
|
||||
m->faceAngle[1] += 0x8000;
|
||||
m->particleFlags |= PARTICLE_VERTICAL_STAR;
|
||||
return set_mario_action(m, ACT_WALL_KICK_AIR, 0);
|
||||
}
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_NONE:
|
||||
set_mario_action(m, ACT_FREEFALL, 0);
|
||||
break;
|
||||
|
||||
case AIR_STEP_LANDED:
|
||||
set_mario_action(m, ACT_JUMP_LAND_STOP, 0);
|
||||
break;
|
||||
|
||||
case AIR_STEP_HIT_LAVA_WALL:
|
||||
lava_boost_on_wall(m);
|
||||
break;
|
||||
}
|
||||
if (m->vel[1] < -20.0f) {
|
||||
m->vel[1] = -20.0f;
|
||||
}
|
||||
mario_set_forward_vel(m, 1.0f);
|
||||
play_sound(SOUND_MOVING_TERRAIN_SLIDE + m->terrainSoundAddend, m->marioObj->header.gfx.cameraToObject);
|
||||
m->particleFlags |= PARTICLE_DUST;
|
||||
m->marioObj->header.gfx.angle[1] = m->faceAngle[1]+0x8000;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_backward_air_kb(struct MarioState *m) {
|
||||
if (check_wall_kick(m)) {
|
||||
return 1;
|
||||
|
|
@ -1304,7 +1439,24 @@ s32 act_air_hit_wall(struct MarioState *m) {
|
|||
if (m->heldObj != NULL) {
|
||||
mario_drop_held_object(m);
|
||||
}
|
||||
|
||||
if (gModernWallJump) {
|
||||
if (++(m->actionTimer) <= 2) {
|
||||
if (m->input & INPUT_A_PRESSED) {
|
||||
m->vel[1] = 52.0f;
|
||||
m->faceAngle[1] += 0x8000;
|
||||
m->particleFlags |= PARTICLE_VERTICAL_STAR;
|
||||
return set_mario_action(m, ACT_WALL_KICK_AIR, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
m->wallKickTimer = 5;
|
||||
if (m->vel[1] > 0.0f) {
|
||||
m->vel[1] = 0.0f;
|
||||
}
|
||||
return set_mario_action(m, ACT_WALL_SLIDE, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (++(m->actionTimer) <= 2) {
|
||||
if (m->input & INPUT_A_PRESSED) {
|
||||
m->vel[1] = 52.0f;
|
||||
|
|
@ -1330,6 +1482,7 @@ s32 act_air_hit_wall(struct MarioState *m) {
|
|||
}
|
||||
return set_mario_action(m, ACT_SOFT_BONK, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef AVOID_UB
|
||||
return
|
||||
|
|
@ -1353,7 +1506,7 @@ s32 act_forward_rollout(struct MarioState *m) {
|
|||
|
||||
play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, 0);
|
||||
|
||||
update_air_without_turn(m);
|
||||
update_air_without_turn(m, 0);
|
||||
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_NONE:
|
||||
|
|
@ -1394,7 +1547,7 @@ s32 act_backward_rollout(struct MarioState *m) {
|
|||
|
||||
play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, 0);
|
||||
|
||||
update_air_without_turn(m);
|
||||
update_air_without_turn(m, 0);
|
||||
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_NONE:
|
||||
|
|
@ -1582,7 +1735,7 @@ s32 act_slide_kick(struct MarioState *m) {
|
|||
return set_mario_action(m, ACT_FREEFALL, 2);
|
||||
}
|
||||
|
||||
update_air_without_turn(m);
|
||||
update_air_without_turn(m, 0);
|
||||
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_NONE:
|
||||
|
|
@ -1641,7 +1794,7 @@ s32 act_jump_kick(struct MarioState *m) {
|
|||
m->flags |= MARIO_KICKING;
|
||||
}
|
||||
|
||||
update_air_without_turn(m);
|
||||
update_air_without_turn(m, 1);
|
||||
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_LANDED:
|
||||
|
|
@ -1933,7 +2086,7 @@ s32 act_flying_triple_jump(struct MarioState *m) {
|
|||
set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1);
|
||||
}
|
||||
|
||||
update_air_without_turn(m);
|
||||
update_air_without_turn(m, 1);
|
||||
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_LANDED:
|
||||
|
|
@ -1981,7 +2134,7 @@ s32 act_vertical_wind(struct MarioState *m) {
|
|||
set_mario_animation(m, MARIO_ANIM_AIRBORNE_ON_STOMACH);
|
||||
}
|
||||
|
||||
update_air_without_turn(m);
|
||||
update_air_without_turn(m, 1);
|
||||
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_LANDED:
|
||||
|
|
@ -2009,7 +2162,7 @@ s32 act_special_triple_jump(struct MarioState *m) {
|
|||
|
||||
play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, SOUND_MARIO_YAHOO);
|
||||
|
||||
update_air_without_turn(m);
|
||||
update_air_without_turn(m, 1);
|
||||
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_LANDED:
|
||||
|
|
@ -2111,6 +2264,7 @@ s32 mario_execute_airborne_action(struct MarioState *m) {
|
|||
case ACT_RIDING_HOOT: cancel = act_riding_hoot(m); break;
|
||||
case ACT_TOP_OF_POLE_JUMP: cancel = act_top_of_pole_jump(m); break;
|
||||
case ACT_VERTICAL_WIND: cancel = act_vertical_wind(m); break;
|
||||
case ACT_WALL_SLIDE: cancel = act_wall_slide(m); break;
|
||||
}
|
||||
/* clang-format on */
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
#include "level_table.h"
|
||||
#include "thread6.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#define POLE_NONE 0
|
||||
#define POLE_TOUCHED_FLOOR 1
|
||||
#define POLE_FELL_OFF 2
|
||||
|
|
@ -711,8 +713,14 @@ s32 act_in_cannon(struct MarioState *m) {
|
|||
break;
|
||||
|
||||
case 2:
|
||||
if (gBetterControls) {
|
||||
m->faceAngle[0] -= (s16)(m->controller->stickY * 6.0f);
|
||||
marioObj->oMarioCannonInputYaw -= (s16)(m->controller->stickX * 6.0f);
|
||||
}
|
||||
else {
|
||||
m->faceAngle[0] -= (s16)(m->controller->stickY * 10.0f);
|
||||
marioObj->oMarioCannonInputYaw -= (s16)(m->controller->stickX * 10.0f);
|
||||
}
|
||||
|
||||
if (m->faceAngle[0] > 0x38E3) {
|
||||
m->faceAngle[0] = 0x38E3;
|
||||
|
|
@ -721,12 +729,22 @@ s32 act_in_cannon(struct MarioState *m) {
|
|||
m->faceAngle[0] = 0;
|
||||
}
|
||||
|
||||
if (gFlexibleCannons) {
|
||||
if (marioObj->oMarioCannonInputYaw > 0x8000) {
|
||||
marioObj->oMarioCannonInputYaw = 0x8000;
|
||||
}
|
||||
if (marioObj->oMarioCannonInputYaw < -0x8000) {
|
||||
marioObj->oMarioCannonInputYaw = -0x8000;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (marioObj->oMarioCannonInputYaw > 0x4000) {
|
||||
marioObj->oMarioCannonInputYaw = 0x4000;
|
||||
}
|
||||
if (marioObj->oMarioCannonInputYaw < -0x4000) {
|
||||
marioObj->oMarioCannonInputYaw = -0x4000;
|
||||
}
|
||||
}
|
||||
|
||||
m->faceAngle[1] = marioObj->oMarioCannonObjectYaw + marioObj->oMarioCannonInputYaw;
|
||||
if (m->input & INPUT_A_PRESSED) {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include "sound_init.h"
|
||||
#include "thread6.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
// TODO: put this elsewhere
|
||||
enum SaveOption { SAVE_OPT_SAVE_AND_CONTINUE = 1, SAVE_OPT_SAVE_AND_QUIT, SAVE_OPT_CONTINUE_DONT_SAVE };
|
||||
|
||||
|
|
@ -618,16 +620,30 @@ void general_star_dance_handler(struct MarioState *m, s32 isInWater) {
|
|||
if ((m->actionArg & 1) == 0) {
|
||||
level_trigger_warp(m, WARP_OP_STAR_EXIT);
|
||||
} else {
|
||||
if (gDontKick == 2) {
|
||||
save_file_do_save(gCurrSaveFileNum - 1);
|
||||
m->actionState = 2;
|
||||
}
|
||||
else {
|
||||
enable_time_stop();
|
||||
if (gDontKick) {
|
||||
create_dialog_box_with_response(DIALOG_170);
|
||||
}
|
||||
else {
|
||||
create_dialog_box_with_response(gLastCompletedStarNum == 7 ? DIALOG_013 : DIALOG_014);
|
||||
}
|
||||
m->actionState = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (m->actionState == 1 && gDialogResponse) {
|
||||
if (gDialogResponse == 1) {
|
||||
save_file_do_save(gCurrSaveFileNum - 1);
|
||||
}
|
||||
else if (gDontKick && gLastCompletedStarNum < 7) {
|
||||
level_trigger_warp(m, WARP_OP_STAR_EXIT);
|
||||
}
|
||||
m->actionState = 2;
|
||||
} else if (m->actionState == 2 && is_anim_at_end(m)) {
|
||||
disable_time_stop();
|
||||
|
|
@ -966,7 +982,7 @@ s32 act_warp_door_spawn(struct MarioState *m) {
|
|||
m->usedObj->oInteractStatus = 0x00080000;
|
||||
}
|
||||
} else if (m->usedObj->oAction == 0) {
|
||||
if (gShouldNotPlayCastleMusic == TRUE && gCurrLevelNum == LEVEL_CASTLE) {
|
||||
if (!gSkipCutscenes && gShouldNotPlayCastleMusic == TRUE && gCurrLevelNum == LEVEL_CASTLE) {
|
||||
set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, DIALOG_021);
|
||||
} else {
|
||||
set_mario_action(m, ACT_IDLE, 0);
|
||||
|
|
@ -1173,7 +1189,12 @@ s32 act_death_exit(struct MarioState *m) {
|
|||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 80);
|
||||
#endif
|
||||
if (gLifeMode) {
|
||||
m->numLives++;
|
||||
}
|
||||
else if (m->numLives > 0) {
|
||||
m->numLives--;
|
||||
}
|
||||
// restore 7.75 units of health
|
||||
m->healCounter = 31;
|
||||
}
|
||||
|
|
@ -1189,7 +1210,12 @@ s32 act_unused_death_exit(struct MarioState *m) {
|
|||
#else
|
||||
play_sound(SOUND_MARIO_OOOF2, m->marioObj->header.gfx.cameraToObject);
|
||||
#endif
|
||||
if (gLifeMode) {
|
||||
m->numLives++;
|
||||
}
|
||||
else if (m->numLives > 0) {
|
||||
m->numLives--;
|
||||
}
|
||||
// restore 7.75 units of health
|
||||
m->healCounter = 31;
|
||||
}
|
||||
|
|
@ -1208,7 +1234,12 @@ s32 act_falling_death_exit(struct MarioState *m) {
|
|||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 80);
|
||||
#endif
|
||||
if (gLifeMode) {
|
||||
m->numLives++;
|
||||
}
|
||||
else if (m->numLives > 0) {
|
||||
m->numLives--;
|
||||
}
|
||||
// restore 7.75 units of health
|
||||
m->healCounter = 31;
|
||||
}
|
||||
|
|
@ -1255,7 +1286,12 @@ s32 act_special_death_exit(struct MarioState *m) {
|
|||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 80);
|
||||
#endif
|
||||
if (gLifeMode) {
|
||||
m->numLives++;
|
||||
}
|
||||
else if (m->numLives > 0) {
|
||||
m->numLives--;
|
||||
}
|
||||
m->healCounter = 31;
|
||||
}
|
||||
// show Mario
|
||||
|
|
@ -2524,7 +2560,7 @@ static s32 act_end_peach_cutscene(struct MarioState *m) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef VERSION_EU
|
||||
/*#ifdef VERSION_EU
|
||||
#define TIMER_CREDITS_SHOW 51
|
||||
#define TIMER_CREDITS_PROGRESS 80
|
||||
#define TIMER_CREDITS_WARP 160
|
||||
|
|
@ -2532,6 +2568,16 @@ static s32 act_end_peach_cutscene(struct MarioState *m) {
|
|||
#define TIMER_CREDITS_SHOW 61
|
||||
#define TIMER_CREDITS_PROGRESS 90
|
||||
#define TIMER_CREDITS_WARP 200
|
||||
#endif*/
|
||||
|
||||
#ifdef VERSION_EU
|
||||
#define TIMER_CREDITS_SHOW 64
|
||||
#define TIMER_CREDITS_PROGRESS 93
|
||||
#define TIMER_CREDITS_WARP 173
|
||||
#else
|
||||
#define TIMER_CREDITS_SHOW 74
|
||||
#define TIMER_CREDITS_PROGRESS 103
|
||||
#define TIMER_CREDITS_WARP 213
|
||||
#endif
|
||||
|
||||
static s32 act_credits_cutscene(struct MarioState *m) {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
#include "behavior_data.h"
|
||||
#include "thread6.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
struct LandingAction {
|
||||
s16 numFrames;
|
||||
s16 unk02;
|
||||
|
|
@ -461,8 +463,12 @@ void update_walking_speed(struct MarioState *m) {
|
|||
m->forwardVel = 48.0f;
|
||||
}
|
||||
|
||||
m->faceAngle[1] =
|
||||
m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x800, 0x800);
|
||||
if (gBetterControls) {
|
||||
m->faceAngle[1] = m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x1000, 0x1000);
|
||||
}
|
||||
else {
|
||||
m->faceAngle[1] = m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x800, 0x800);
|
||||
}
|
||||
apply_slope_accel(m);
|
||||
}
|
||||
|
||||
|
|
@ -806,9 +812,21 @@ s32 act_walking(struct MarioState *m) {
|
|||
return begin_braking_action(m);
|
||||
}
|
||||
|
||||
if (gBetterControls) {
|
||||
if (analog_stick_held_back(m)) {
|
||||
if (m->forwardVel >= 12.0f){
|
||||
return set_mario_action(m, ACT_TURNING_AROUND, 0);
|
||||
} else if ((m->forwardVel) < 10.0f && (m->forwardVel > 0.0f)){
|
||||
m->faceAngle[1] = m->intendedYaw;
|
||||
return set_mario_action(m, ACT_TURNING_AROUND, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (analog_stick_held_back(m) && m->forwardVel >= 16.0f) {
|
||||
return set_mario_action(m, ACT_TURNING_AROUND, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (m->input & INPUT_Z_PRESSED) {
|
||||
return set_mario_action(m, ACT_CROUCH_SLIDE, 0);
|
||||
|
|
@ -1047,9 +1065,16 @@ s32 act_braking(struct MarioState *m) {
|
|||
return check_common_action_exits(m);
|
||||
}
|
||||
|
||||
if (gBetterControls) {
|
||||
if (apply_slope_decel(m, 2.5f)) {
|
||||
return set_mario_action(m, ACT_BRAKING_STOP, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (apply_slope_decel(m, 2.0f)) {
|
||||
return set_mario_action(m, ACT_BRAKING_STOP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (m->input & INPUT_B_PRESSED) {
|
||||
return set_mario_action(m, ACT_MOVE_PUNCHING, 0);
|
||||
|
|
@ -1328,8 +1353,12 @@ s32 act_burning_ground(struct MarioState *m) {
|
|||
m->forwardVel = approach_f32(m->forwardVel, 32.0f, 4.0f, 1.0f);
|
||||
|
||||
if (m->input & INPUT_NONZERO_ANALOG) {
|
||||
m->faceAngle[1] =
|
||||
m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x600, 0x600);
|
||||
if (gBetterControls) {
|
||||
m->faceAngle[1] = m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x800, 0x800);
|
||||
}
|
||||
else {
|
||||
m->faceAngle[1] = m->intendedYaw - approach_s32((s16)(m->intendedYaw - m->faceAngle[1]), 0, 0x600, 0x600);
|
||||
}
|
||||
}
|
||||
|
||||
apply_slope_accel(m);
|
||||
|
|
@ -1565,9 +1594,16 @@ s32 act_dive_slide(struct MarioState *m) {
|
|||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 80);
|
||||
#endif
|
||||
if (gSunshineDive && m->input & INPUT_B_PRESSED) {
|
||||
mario_set_forward_vel(m, 20.0f);
|
||||
m->vel[1] = 21.0f;
|
||||
return set_mario_action(m, ACT_DIVE, 0);
|
||||
}
|
||||
else {
|
||||
return set_mario_action(m, m->forwardVel > 0.0f ? ACT_FORWARD_ROLLOUT : ACT_BACKWARD_ROLLOUT,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
play_mario_landing_sound_once(m, SOUND_ACTION_TERRAIN_BODY_HIT_GROUND);
|
||||
|
||||
|
|
@ -1856,6 +1892,11 @@ s32 act_long_jump_land(struct MarioState *m) {
|
|||
}
|
||||
#endif
|
||||
|
||||
// Sorry daddy...
|
||||
if (gDisableBLJ && m->forwardVel < 0.0f) {
|
||||
m->forwardVel = 0.0f;
|
||||
}
|
||||
|
||||
if (!(m->input & INPUT_Z_DOWN)) {
|
||||
m->input &= ~INPUT_A_PRESSED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
#include "sound_init.h"
|
||||
#include "surface_terrains.h"
|
||||
#include "thread6.h"
|
||||
#include "game_init.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
s32 check_common_idle_cancels(struct MarioState *m) {
|
||||
mario_drop_held_object(m);
|
||||
|
|
@ -1046,6 +1049,34 @@ s32 act_twirl_land(struct MarioState *m) {
|
|||
|
||||
s32 act_ground_pound_land(struct MarioState *m) {
|
||||
m->actionState = 1;
|
||||
|
||||
if (gFlashbackPound) {
|
||||
if (m->input & INPUT_OFF_FLOOR) {
|
||||
return set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
else if (m->input & INPUT_ABOVE_SLIDE) {
|
||||
return set_mario_action(m, ACT_BUTT_SLIDE, 0);
|
||||
}
|
||||
if (m->input & INPUT_Z_DOWN) {
|
||||
if (gPlayer1Controller->stickX != 0 || gPlayer1Controller->stickY != 0) {
|
||||
m->vel[1] = 2.0f;
|
||||
mario_set_forward_vel(m, 56.0f);
|
||||
m->faceAngle[1] = m->intendedYaw;
|
||||
return set_mario_action(m, ACT_SLIDE_KICK, 0);
|
||||
}
|
||||
else {
|
||||
return set_mario_action(m, ACT_CROUCHING, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
set_mario_action(m, ACT_BACKWARD_ROLLOUT, 0);
|
||||
m->actionState = 1;
|
||||
m->vel[1] = 40.0f;
|
||||
mario_set_forward_vel(m, 0.0f);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (m->input & INPUT_UNKNOWN_10) {
|
||||
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
|
||||
}
|
||||
|
|
@ -1057,6 +1088,7 @@ s32 act_ground_pound_land(struct MarioState *m) {
|
|||
if (m->input & INPUT_ABOVE_SLIDE) {
|
||||
return set_mario_action(m, ACT_BUTT_SLIDE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
landing_step(m, MARIO_ANIM_GROUND_POUND_LANDING, ACT_BUTT_SLIDE_STOP);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
#include "level_table.h"
|
||||
#include "thread6.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#define MIN_SWIM_STRENGTH 160
|
||||
#define MIN_SWIM_SPEED 16.0f
|
||||
|
||||
|
|
@ -59,10 +61,20 @@ static f32 get_buoyancy(struct MarioState *m) {
|
|||
buoyancy = -18.0f;
|
||||
}
|
||||
} else if (swimming_near_surface(m)) {
|
||||
if (gBetterControls) {
|
||||
buoyancy = 2.0f;
|
||||
}
|
||||
else {
|
||||
buoyancy = 1.25f;
|
||||
}
|
||||
} else if (!(m->action & ACT_FLAG_MOVING)) {
|
||||
if (gBetterControls) {
|
||||
buoyancy = -0.5f;
|
||||
}
|
||||
else {
|
||||
buoyancy = -2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return buoyancy;
|
||||
}
|
||||
|
|
@ -493,7 +505,12 @@ static s32 check_water_jump(struct MarioState *m) {
|
|||
if (probe >= m->waterLevel - 80 && m->faceAngle[0] >= 0 && m->controller->stickY < -60.0f) {
|
||||
vec3s_set(m->angleVel, 0, 0, 0);
|
||||
|
||||
if (gBetterControls) {
|
||||
m->vel[1] = 64.0f;
|
||||
}
|
||||
else {
|
||||
m->vel[1] = 62.0f;
|
||||
}
|
||||
|
||||
if (m->heldObj == NULL) {
|
||||
return set_mario_action(m, ACT_WATER_JUMP, 0);
|
||||
|
|
@ -528,12 +545,22 @@ static s32 act_breaststroke(struct MarioState *m) {
|
|||
}
|
||||
|
||||
if (m->actionTimer < 6) {
|
||||
if (gBetterControls) {
|
||||
m->forwardVel += 1.0f;
|
||||
}
|
||||
else {
|
||||
m->forwardVel += 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
if (m->actionTimer >= 9) {
|
||||
if (gBetterControls) {
|
||||
m->forwardVel += 3.0f;
|
||||
}
|
||||
else {
|
||||
m->forwardVel += 1.5f;
|
||||
}
|
||||
}
|
||||
|
||||
if (m->actionTimer >= 2) {
|
||||
if (m->actionTimer < 6 && (m->input & INPUT_A_PRESSED)) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@
|
|||
#include "interaction.h"
|
||||
#include "mario_step.h"
|
||||
|
||||
#include "object_list_processor.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
static s16 sMovingSandSpeeds[] = { 12, 8, 4, 0 };
|
||||
|
||||
struct Surface gWaterSurfacePseudoFloor = {
|
||||
|
|
@ -402,7 +406,12 @@ s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepAr
|
|||
lowerWall = resolve_and_return_wall_collisions(nextPos, 30.0f, 50.0f);
|
||||
|
||||
floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor);
|
||||
if (gCollisionFixes) {
|
||||
ceilHeight = vec3f_find_ceil(nextPos, nextPos[1], &ceil);
|
||||
}
|
||||
else {
|
||||
ceilHeight = vec3f_find_ceil(nextPos, floorHeight, &ceil);
|
||||
}
|
||||
|
||||
waterLevel = find_water_level(nextPos[0], nextPos[2]);
|
||||
|
||||
|
|
@ -429,6 +438,7 @@ s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepAr
|
|||
|
||||
//! This check uses f32, but findFloor uses short (overflow jumps)
|
||||
if (nextPos[1] <= floorHeight) {
|
||||
if (!gCollisionFixes || gMarioObject->platform == NULL | (m->vel[1]<=0)) {
|
||||
if (ceilHeight - floorHeight > 160.0f) {
|
||||
m->pos[0] = nextPos[0];
|
||||
m->pos[2] = nextPos[2];
|
||||
|
|
@ -442,6 +452,7 @@ s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepAr
|
|||
m->pos[1] = floorHeight;
|
||||
return AIR_STEP_LANDED;
|
||||
}
|
||||
}
|
||||
|
||||
if (nextPos[1] + 160.0f > ceilHeight) {
|
||||
if (m->vel[1] >= 0.0f) {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
#include "spawn_object.h"
|
||||
#include "spawn_sound.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
/**
|
||||
* @file obj_behaviors.c
|
||||
* This file contains a portion of the obj behaviors and many helper functions for those
|
||||
|
|
@ -529,7 +531,7 @@ void set_object_visibility(struct Object *obj, s32 dist) {
|
|||
f32 objY = obj->oPosY;
|
||||
f32 objZ = obj->oPosZ;
|
||||
|
||||
if (is_point_within_radius_of_mario(objX, objY, objZ, dist) == TRUE) {
|
||||
if (gDisableDrawDistance || is_point_within_radius_of_mario(objX, objY, objZ, dist) == TRUE) {
|
||||
obj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
} else {
|
||||
obj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
#include "shadow.h"
|
||||
#include "sm64.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
/**
|
||||
* This file contains the code that processes the scene graph for rendering.
|
||||
* The scene graph is responsible for drawing everything except the HUD / text boxes.
|
||||
|
|
@ -272,6 +274,14 @@ static void geo_process_level_of_detail(struct GraphNodeLevelOfDetail *node) {
|
|||
s16 *mtx = (s16 *) gMatStackFixed[gMatStackIndex];
|
||||
s16 distanceFromCam = -mtx[14]; // z-component of the translation column
|
||||
|
||||
// You know what they say, if it works, it works.
|
||||
if (gNoLowPoly) {
|
||||
distanceFromCam = 0;
|
||||
}
|
||||
if (gForceLowPoly) {
|
||||
distanceFromCam = 10000;
|
||||
}
|
||||
|
||||
if (node->minDistance <= distanceFromCam && distanceFromCam < node->maxDistance) {
|
||||
if (node->node.children != 0) {
|
||||
geo_process_node_and_siblings(node->node.children);
|
||||
|
|
|
|||
|
|
@ -481,6 +481,13 @@ u32 save_file_get_flags(void) {
|
|||
return gSaveBuffer.files[gCurrSaveFileNum - 1][0].flags;
|
||||
}
|
||||
|
||||
s8 is_save_hard(s16 slot) {
|
||||
return ((gSaveBuffer.files[slot][0].flags & SAVE_FLAG_HARD_MODE) != 0);
|
||||
}
|
||||
s8 is_save_hardcore(s16 slot) {
|
||||
return ((gSaveBuffer.files[slot][0].flags & SAVE_FLAG_HARDCORE_MODE) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bitset of obtained stars in the specified course.
|
||||
* If course is -1, return the bitset of obtained castle secret stars.
|
||||
|
|
|
|||
|
|
@ -104,6 +104,8 @@ extern s8 gLevelToCourseNumTable[];
|
|||
#define SAVE_FLAG_CAP_ON_UKIKI /* 0x040000 */ (1 << 18)
|
||||
#define SAVE_FLAG_CAP_ON_MR_BLIZZARD /* 0x080000 */ (1 << 19)
|
||||
#define SAVE_FLAG_UNLOCKED_50_STAR_DOOR /* 0x100000 */ (1 << 20)
|
||||
#define SAVE_FLAG_HARD_MODE /* 0x200000 */ (1 << 21)
|
||||
#define SAVE_FLAG_HARDCORE_MODE /* 0x800000 */ (1 << 23)
|
||||
|
||||
// Variable for setting a warp checkpoint.
|
||||
|
||||
|
|
@ -134,6 +136,8 @@ s32 save_file_get_total_star_count(s32 fileIndex, s32 minCourse, s32 maxCourse);
|
|||
void save_file_set_flags(u32 flags);
|
||||
void save_file_clear_flags(u32 flags);
|
||||
u32 save_file_get_flags(void);
|
||||
s8 is_save_hard(s16 slot);
|
||||
s8 is_save_hardcore(s16 slot);
|
||||
u32 save_file_get_star_flags(s32 fileIndex, s32 courseIndex);
|
||||
void save_file_set_star_flags(s32 fileIndex, s32 courseIndex, u32 starFlags);
|
||||
s32 save_file_get_course_coin_score(s32 fileIndex, s32 courseIndex);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
#include <ultra64.h>
|
||||
|
||||
s8 gBetterControls = 1;
|
||||
s8 gDpadInput = 1;
|
||||
s8 gAirTurn = 0;
|
||||
s8 gDisableBLJ = 0;
|
||||
s8 gDisableFallDamage = 0;
|
||||
int gControllerDeadzone = 500;
|
||||
|
||||
s8 gCollisionFixes = 1;
|
||||
s8 gRemoveAnnoyingWarps = 1;
|
||||
s8 gDisableBooDialogue = 1;
|
||||
s8 gSkipCutscenes = 0;
|
||||
s8 gLeaveAnyTime = 0;
|
||||
s8 gVisibleSecrets = 0;
|
||||
s8 gFlexibleCannons = 0;
|
||||
int gDontKick = 0;
|
||||
|
||||
s8 gModernWallJump = 1;
|
||||
s8 gSunshineDive = 0;
|
||||
s8 gOdysseyDive = 0;
|
||||
s8 gFlashbackPound = 0;
|
||||
|
||||
s8 configFullscreen = 1;
|
||||
int gCustomFullscreenResolution = 0;
|
||||
int gFullscreenWidth = 1920;
|
||||
int gFullscreenHeight = 1080;
|
||||
int gFullscreenRefreshRate = 60;
|
||||
int gWindowWidth = 1280;
|
||||
int gWindowHeight = 720;
|
||||
s8 gCustomInternalResolution = 1;
|
||||
int gInternalResolutionWidth = 3840;
|
||||
int gInternalResolutionHeight = 2160;
|
||||
s8 gDrawPillarbox = 0;
|
||||
|
||||
s8 gDisableDrawDistance = 1;
|
||||
s8 gNoLowPoly = 1;
|
||||
int gNoiseType = 0;
|
||||
s8 gDisableFog = 0;
|
||||
s8 gForceLowPoly = 0;
|
||||
s8 gNearestNeighbor = 0;
|
||||
s8 gFXMode = 0;
|
||||
|
||||
s8 gImprovedCamera = 1;
|
||||
s8 gCenterCam = 1;
|
||||
s8 gInvertedCamera = 0;
|
||||
int gCameraSpeed = 32;
|
||||
int gAdditionalCameraDistance = 0;
|
||||
int gAdditionalFOV = 0;
|
||||
|
||||
int gNewHud = 2;
|
||||
s8 gCenterHud = 0;
|
||||
s8 gHUDFiltering = 0;
|
||||
int gHUDUpscaling = 0;
|
||||
s8 gAlwaysShowHealth = 0;
|
||||
s8 gHideHud = 0;
|
||||
|
||||
s8 gTrapdoorSound = 1;
|
||||
|
||||
s8 gLifeMode = 0;
|
||||
s8 gHardSave = 0;
|
||||
s8 gHardcoreSave = 0;
|
||||
s8 gGreenDemon = 0;
|
||||
s8 gEncoreMode = 0;
|
||||
|
||||
s8 gDebugMovementMode = 0;
|
||||
|
||||
s8 gShow100CoinStar = 0;
|
||||
int gTextureUpscaling = 0;
|
||||
|
||||
unsigned int configKeyA = 0x26;
|
||||
unsigned int configKeyB = 0x33;
|
||||
unsigned int configKeyStart = 0x39;
|
||||
unsigned int configKeyR = 0x36;
|
||||
unsigned int configKeyZ = 0x25;
|
||||
unsigned int configKeyCUp = 0x148;
|
||||
unsigned int configKeyCDown = 0x150;
|
||||
unsigned int configKeyCLeft = 0x14B;
|
||||
unsigned int configKeyCRight = 0x14D;
|
||||
unsigned int configKeyStickUp = 0x11;
|
||||
unsigned int configKeyStickDown = 0x1F;
|
||||
unsigned int configKeyStickLeft = 0x1E;
|
||||
unsigned int configKeyStickRight = 0x20;
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
#include <ultra64.h>
|
||||
|
||||
extern s8 gBetterControls;
|
||||
extern s8 gDpadInput;
|
||||
extern s8 gAirTurn;
|
||||
extern s8 gDisableBLJ;
|
||||
extern s8 gDisableFallDamage;
|
||||
extern int gControllerDeadzone;
|
||||
|
||||
extern s8 gCollisionFixes;
|
||||
extern s8 gRemoveAnnoyingWarps;
|
||||
extern s8 gDisableBooDialogue;
|
||||
extern s8 gSkipCutscenes;
|
||||
extern s8 gLeaveAnyTime;
|
||||
extern s8 gVisibleSecrets;
|
||||
extern s8 gFlexibleCannons;
|
||||
extern int gDontKick;
|
||||
|
||||
extern s8 gModernWallJump;
|
||||
extern s8 gSunshineDive;
|
||||
extern s8 gOdysseyDive;
|
||||
extern s8 gFlashbackPound;
|
||||
|
||||
extern s8 configFullscreen;
|
||||
extern s8 gCustomFullscreenResolution;
|
||||
extern int gFullscreenWidth;
|
||||
extern int gFullscreenHeight;
|
||||
extern int gFullscreenRefreshRate;
|
||||
extern int gWindowWidth;
|
||||
extern int gWindowHeight;
|
||||
extern s8 gCustomInternalResolution;
|
||||
extern int gInternalResolutionWidth;
|
||||
extern int gInternalResolutionHeight;
|
||||
extern s8 gDrawPillarbox;
|
||||
|
||||
extern s8 gDisableDrawDistance;
|
||||
extern s8 gNoLowPoly;
|
||||
extern int gNoiseType;
|
||||
extern s8 gDisableFog;
|
||||
extern s8 gForceLowPoly;
|
||||
extern s8 gNearestNeighbor;
|
||||
extern s8 gFXMode;
|
||||
|
||||
extern s8 gImprovedCamera;
|
||||
extern s8 gCenterCam;
|
||||
extern s8 gInvertedCamera;
|
||||
extern int gCameraSpeed;
|
||||
extern int gAdditionalCameraDistance;
|
||||
extern int gAdditionalFOV;
|
||||
|
||||
extern int gNewHud;
|
||||
extern s8 gCenterHud;
|
||||
extern s8 gHUDFiltering;
|
||||
extern int gHUDUpscaling;
|
||||
extern s8 gAlwaysShowHealth;
|
||||
extern s8 gHideHud;
|
||||
|
||||
extern s8 gTrapdoorSound;
|
||||
|
||||
extern s8 gLifeMode;
|
||||
extern s8 gHardSave;
|
||||
extern s8 gHardcoreSave;
|
||||
extern s8 gGreenDemon;
|
||||
extern s8 gEncoreMode;
|
||||
|
||||
extern s8 gDebugMovementMode;
|
||||
|
||||
extern s8 gShow100CoinStar;
|
||||
extern int gTextureUpscaling;
|
||||
|
||||
extern unsigned int configKeyA;
|
||||
extern unsigned int configKeyB;
|
||||
extern unsigned int configKeyStart;
|
||||
extern unsigned int configKeyR;
|
||||
extern unsigned int configKeyZ;
|
||||
extern unsigned int configKeyCUp;
|
||||
extern unsigned int configKeyCDown;
|
||||
extern unsigned int configKeyCLeft;
|
||||
extern unsigned int configKeyCRight;
|
||||
extern unsigned int configKeyStickUp;
|
||||
extern unsigned int configKeyStickDown;
|
||||
extern unsigned int configKeyStickLeft;
|
||||
extern unsigned int configKeyStickRight;
|
||||
|
|
@ -13,6 +13,11 @@
|
|||
#include "shadow.h"
|
||||
#include "sm64.h"
|
||||
|
||||
#ifndef TARGET_N64
|
||||
// Avoid Z-fighting
|
||||
#define find_floor_height_and_data 0.4 + find_floor_height_and_data
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file shadow.c
|
||||
* This file implements a self-contained subsystem used to draw shadows.
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include "sm64.h"
|
||||
#include "text_strings.h"
|
||||
|
||||
#include "game/settings.h"
|
||||
|
||||
#include "eu_translation.h"
|
||||
#ifdef VERSION_EU
|
||||
#undef LANGUAGE_FUNCTION
|
||||
|
|
@ -177,6 +179,16 @@ static unsigned char textMarioB[] = { TEXT_FILE_MARIO_B };
|
|||
static unsigned char textMarioC[] = { TEXT_FILE_MARIO_C };
|
||||
static unsigned char textMarioD[] = { TEXT_FILE_MARIO_D };
|
||||
|
||||
static unsigned char textHardA[] = { TEXT_FILE_HARD_A };
|
||||
static unsigned char textHardB[] = { TEXT_FILE_HARD_B };
|
||||
static unsigned char textHardC[] = { TEXT_FILE_HARD_C };
|
||||
static unsigned char textHardD[] = { TEXT_FILE_HARD_D };
|
||||
|
||||
static unsigned char textHardcoreA[] = { TEXT_FILE_HARDCORE_A };
|
||||
static unsigned char textHardcoreB[] = { TEXT_FILE_HARDCORE_B };
|
||||
static unsigned char textHardcoreC[] = { TEXT_FILE_HARDCORE_C };
|
||||
static unsigned char textHardcoreD[] = { TEXT_FILE_HARDCORE_D };
|
||||
|
||||
#ifndef VERSION_EU
|
||||
static unsigned char textNew[] = { TEXT_NEW };
|
||||
static unsigned char starIcon[] = { GLYPH_STAR, GLYPH_SPACE };
|
||||
|
|
@ -1794,10 +1806,45 @@ void print_main_menu_strings(void) {
|
|||
// Print file names
|
||||
gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_begin);
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha);
|
||||
if (is_save_hardcore(0)) {
|
||||
print_menu_generic_string(MARIOTEXT_X1, 65, textHardcoreA);
|
||||
}
|
||||
else if (is_save_hard(0)) {
|
||||
print_menu_generic_string(MARIOTEXT_X1, 65, textHardA);
|
||||
}
|
||||
else {
|
||||
print_menu_generic_string(MARIOTEXT_X1, 65, textMarioA);
|
||||
}
|
||||
|
||||
if (is_save_hardcore(1)) {
|
||||
print_menu_generic_string(MARIOTEXT_X2, 65, textHardcoreB);
|
||||
}
|
||||
else if (is_save_hard(1)) {
|
||||
print_menu_generic_string(MARIOTEXT_X2, 65, textHardB);
|
||||
}
|
||||
else {
|
||||
print_menu_generic_string(MARIOTEXT_X2, 65, textMarioB);
|
||||
}
|
||||
|
||||
if (is_save_hardcore(2)) {
|
||||
print_menu_generic_string(MARIOTEXT_X1, 105, textHardcoreC);
|
||||
}
|
||||
else if (is_save_hard(2)) {
|
||||
print_menu_generic_string(MARIOTEXT_X1, 105, textHardC);
|
||||
}
|
||||
else {
|
||||
print_menu_generic_string(MARIOTEXT_X1, 105, textMarioC);
|
||||
}
|
||||
|
||||
if (is_save_hardcore(3)) {
|
||||
print_menu_generic_string(MARIOTEXT_X2, 105, textHardcoreD);
|
||||
}
|
||||
else if (is_save_hard(3)) {
|
||||
print_menu_generic_string(MARIOTEXT_X2, 105, textHardD);
|
||||
}
|
||||
else {
|
||||
print_menu_generic_string(MARIOTEXT_X2, 105, textMarioD);
|
||||
}
|
||||
gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_end);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
#include "text_strings.h"
|
||||
#include "prevent_bss_reordering.h"
|
||||
|
||||
#include "game/settings.h"
|
||||
|
||||
/**
|
||||
* @file star_select.c
|
||||
* This file implements how the star select screen (act selector) function.
|
||||
|
|
@ -96,6 +98,13 @@ void render_100_coin_star(u8 stars) {
|
|||
sStarSelectorModels[6]->oStarSelectorSize = 0.8;
|
||||
sStarSelectorModels[6]->oStarSelectorType = STAR_SELECTOR_100_COINS;
|
||||
}
|
||||
else if (gShow100CoinStar) {
|
||||
sStarSelectorModels[6] = spawn_object_abs_with_rot(gCurrentObject, 0, MODEL_TRANSPARENT_STAR,
|
||||
bhvActSelectorStarType, 300, 30, -300, 0, 0, 0);
|
||||
sStarSelectorModels[6]->oStarSelectorSize = 0.8;
|
||||
sStarSelectorModels[6]->oStarSelectorType = STAR_SELECTOR_100_COINS;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "../game/settings.h"
|
||||
#include "../game/main.h"
|
||||
|
||||
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
|
|
@ -26,28 +28,78 @@ struct ConfigOption {
|
|||
};
|
||||
};
|
||||
|
||||
/*
|
||||
*Config options and default values
|
||||
*/
|
||||
bool configFullscreen = false;
|
||||
// Keyboard mappings (scancode values)
|
||||
unsigned int configKeyA = 0x26;
|
||||
unsigned int configKeyB = 0x33;
|
||||
unsigned int configKeyStart = 0x39;
|
||||
unsigned int configKeyR = 0x36;
|
||||
unsigned int configKeyZ = 0x25;
|
||||
unsigned int configKeyCUp = 0x148;
|
||||
unsigned int configKeyCDown = 0x150;
|
||||
unsigned int configKeyCLeft = 0x14B;
|
||||
unsigned int configKeyCRight = 0x14D;
|
||||
unsigned int configKeyStickUp = 0x11;
|
||||
unsigned int configKeyStickDown = 0x1F;
|
||||
unsigned int configKeyStickLeft = 0x1E;
|
||||
unsigned int configKeyStickRight = 0x20;
|
||||
|
||||
|
||||
static const struct ConfigOption options[] = {
|
||||
{.name = "improved_controls",.type = CONFIG_TYPE_BOOL, .boolValue = &gBetterControls},
|
||||
{.name = "dpad_controls", .type = CONFIG_TYPE_BOOL, .boolValue = &gDpadInput},
|
||||
{.name = "full_air_control", .type = CONFIG_TYPE_BOOL, .boolValue = &gAirTurn},
|
||||
{.name = "disable_blj", .type = CONFIG_TYPE_BOOL, .boolValue = &gDisableBLJ},
|
||||
{.name = "disable_fall_damage",.type = CONFIG_TYPE_BOOL, .boolValue = &gDisableFallDamage},
|
||||
{.name = "analog_stick_deadzone",.type = CONFIG_TYPE_UINT, .uintValue = &gControllerDeadzone},
|
||||
|
||||
{.name = "fix_collision_errors",.type = CONFIG_TYPE_BOOL, .boolValue = &gCollisionFixes},
|
||||
{.name = "remove_annoying_warps",.type = CONFIG_TYPE_BOOL, .boolValue = &gRemoveAnnoyingWarps},
|
||||
{.name = "disable_all_boo_messages_except_the_first",.type = CONFIG_TYPE_BOOL, .boolValue = &gDisableBooDialogue},
|
||||
{.name = "skip_cutscenes", .type = CONFIG_TYPE_BOOL, .boolValue = &gSkipCutscenes},
|
||||
{.name = "allow_leaving_the_level_at_any_time", .type = CONFIG_TYPE_BOOL, .boolValue = &gLeaveAnyTime},
|
||||
{.name = "make_secrets_visible",.type = CONFIG_TYPE_BOOL, .boolValue = &gVisibleSecrets},
|
||||
{.name = "allow_the_cannons_to_rotate_more",.type = CONFIG_TYPE_BOOL, .boolValue = &gFlexibleCannons},
|
||||
{.name = "stay_in_level_after_getting_a_star", .type = CONFIG_TYPE_UINT, .uintValue = &gDontKick},
|
||||
|
||||
{.name = "wall_sliding",.type = CONFIG_TYPE_BOOL, .boolValue = &gModernWallJump},
|
||||
{.name = "sunshine_dive_hop", .type = CONFIG_TYPE_BOOL, .boolValue = &gSunshineDive},
|
||||
{.name = "odyssey_ground_pound_dive", .type = CONFIG_TYPE_BOOL, .boolValue = &gOdysseyDive},
|
||||
{.name = "flashback_ground_pound", .type = CONFIG_TYPE_BOOL, .boolValue = &gFlashbackPound},
|
||||
|
||||
{.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configFullscreen},
|
||||
{.name = "custom_fullscreen_resolution",.type = CONFIG_TYPE_BOOL, .boolValue = &gCustomFullscreenResolution},
|
||||
{.name = "fullscreen_width",.type = CONFIG_TYPE_UINT, .uintValue = &gFullscreenWidth},
|
||||
{.name = "fullscreen_height",.type = CONFIG_TYPE_UINT, .uintValue = &gFullscreenHeight},
|
||||
{.name = "fullscreen_refresh_rate",.type = CONFIG_TYPE_UINT, .uintValue = &gFullscreenRefreshRate},
|
||||
{.name = "window_width", .type = CONFIG_TYPE_UINT, .uintValue = &gWindowWidth},
|
||||
{.name = "window_height", .type = CONFIG_TYPE_UINT, .uintValue = &gWindowHeight},
|
||||
{.name = "custom_internal_resolution",.type = CONFIG_TYPE_BOOL, .boolValue = &gCustomInternalResolution},
|
||||
{.name = "internal_resolution_width",.type = CONFIG_TYPE_UINT, .uintValue = &gInternalResolutionWidth},
|
||||
{.name = "internal_resolution_height",.type = CONFIG_TYPE_UINT, .uintValue = &gInternalResolutionHeight},
|
||||
{.name = "force_4by3", .type = CONFIG_TYPE_BOOL, .boolValue = &gDrawPillarbox},
|
||||
|
||||
{.name = "disable_draw_distance",.type = CONFIG_TYPE_BOOL, .boolValue = &gDisableDrawDistance},
|
||||
{.name = "disable_low_poly_mario",.type = CONFIG_TYPE_BOOL, .boolValue = &gNoLowPoly},
|
||||
{.name = "noise_type", .type = CONFIG_TYPE_UINT, .uintValue = &gNoiseType},
|
||||
{.name = "disable_fog", .type = CONFIG_TYPE_BOOL, .boolValue = &gDisableFog},
|
||||
{.name = "force_low_poly_mario", .type = CONFIG_TYPE_BOOL, .boolValue = &gForceLowPoly},
|
||||
{.name = "nearest_neighbor_filtering",.type = CONFIG_TYPE_BOOL, .boolValue = &gNearestNeighbor},
|
||||
{.name = "fx_mode", .type = CONFIG_TYPE_BOOL, .boolValue = &gFXMode},
|
||||
|
||||
{.name = "improved_camera", .type = CONFIG_TYPE_BOOL, .boolValue = &gImprovedCamera},
|
||||
{.name = "center_camera_button",.type = CONFIG_TYPE_BOOL, .boolValue = &gCenterCam},
|
||||
{.name = "invert_camera_controls",.type = CONFIG_TYPE_BOOL, .boolValue = &gInvertedCamera},
|
||||
{.name = "analog_camera_speed", .type = CONFIG_TYPE_UINT, .uintValue = &gCameraSpeed},
|
||||
{.name = "additional_camera_distance",.type = CONFIG_TYPE_UINT, .uintValue = &gAdditionalCameraDistance},
|
||||
{.name = "additional_fov", .type = CONFIG_TYPE_UINT, .uintValue = &gAdditionalFOV},
|
||||
|
||||
{.name = "hud_style", .type = CONFIG_TYPE_UINT, .uintValue = &gNewHud},
|
||||
{.name = "4by3_hud", .type = CONFIG_TYPE_BOOL, .boolValue = &gCenterHud},
|
||||
{.name = "hud_filtering",.type = CONFIG_TYPE_BOOL, .boolValue = &gHUDFiltering},
|
||||
{.name = "hud_upscaling", .type = CONFIG_TYPE_UINT, .uintValue = &gHUDUpscaling},
|
||||
{.name = "always_show_the_health_meter", .type = CONFIG_TYPE_BOOL, .boolValue = &gAlwaysShowHealth},
|
||||
{.name = "hide_hud", .type = CONFIG_TYPE_BOOL, .boolValue = &gHideHud},
|
||||
|
||||
{.name = "enable_the_trapdoor_sound", .type = CONFIG_TYPE_BOOL, .boolValue = &gTrapdoorSound},
|
||||
|
||||
{.name = "infinite_lives_mode", .type = CONFIG_TYPE_BOOL, .boolValue = &gLifeMode},
|
||||
{.name = "hard_mode", .type = CONFIG_TYPE_BOOL, .boolValue = &gHardSave},
|
||||
{.name = "permadeath_mode", .type = CONFIG_TYPE_BOOL, .boolValue = &gHardcoreSave},
|
||||
{.name = "green_demon_mode",.type = CONFIG_TYPE_BOOL, .boolValue = &gGreenDemon},
|
||||
{.name = "encore_mode", .type = CONFIG_TYPE_BOOL, .boolValue = &gEncoreMode},
|
||||
|
||||
{.name = "level_select", .type = CONFIG_TYPE_BOOL, .boolValue = &gDebugLevelSelect},
|
||||
{.name = "show_debug_profiler",.type = CONFIG_TYPE_BOOL, .boolValue = &gShowProfiler},
|
||||
{.name = "show_debug_display",.type = CONFIG_TYPE_BOOL, .boolValue = &gShowDebugText},
|
||||
{.name = "debug_movement_mode",.type = CONFIG_TYPE_BOOL, .boolValue = &gDebugMovementMode},
|
||||
|
||||
{.name = "show_100_coin_star",.type = CONFIG_TYPE_BOOL, .boolValue = &gShow100CoinStar},
|
||||
{.name = "texture_upscaling",.type = CONFIG_TYPE_UINT, .uintValue = &gTextureUpscaling},
|
||||
|
||||
{.name = "key_a", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyA},
|
||||
{.name = "key_b", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyB},
|
||||
{.name = "key_start", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStart},
|
||||
|
|
@ -60,7 +112,7 @@ static const struct ConfigOption options[] = {
|
|||
{.name = "key_stickup", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickUp},
|
||||
{.name = "key_stickdown", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickDown},
|
||||
{.name = "key_stickleft", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickLeft},
|
||||
{.name = "key_stickright", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickRight},
|
||||
{.name = "key_stickright", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickRight}
|
||||
};
|
||||
|
||||
// Reads an entire line from a file (excluding the newline character) and returns an allocated string
|
||||
|
|
|
|||
|
|
@ -1,21 +1,6 @@
|
|||
#ifndef CONFIGFILE_H
|
||||
#define CONFIGFILE_H
|
||||
|
||||
extern bool configFullscreen;
|
||||
extern unsigned int configKeyA;
|
||||
extern unsigned int configKeyB;
|
||||
extern unsigned int configKeyStart;
|
||||
extern unsigned int configKeyR;
|
||||
extern unsigned int configKeyZ;
|
||||
extern unsigned int configKeyCUp;
|
||||
extern unsigned int configKeyCDown;
|
||||
extern unsigned int configKeyCLeft;
|
||||
extern unsigned int configKeyCRight;
|
||||
extern unsigned int configKeyStickUp;
|
||||
extern unsigned int configKeyStickDown;
|
||||
extern unsigned int configKeyStickLeft;
|
||||
extern unsigned int configKeyStickRight;
|
||||
|
||||
void configfile_load(const char *filename);
|
||||
void configfile_save(const char *filename);
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ void osContGetReadData(OSContPad *pad) {
|
|||
pad->button = 0;
|
||||
pad->stick_x = 0;
|
||||
pad->stick_y = 0;
|
||||
pad->stick2_x = 0;
|
||||
pad->stick2_y = 0;
|
||||
pad->errnum = 0;
|
||||
|
||||
for (size_t i = 0; i < sizeof(controller_implementations) / sizeof(struct ControllerAPI *); i++) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include "controller_emscripten_keyboard.h"
|
||||
#endif
|
||||
|
||||
#include "../configfile.h"
|
||||
#include "game/settings.h"
|
||||
|
||||
static int keyboard_buttons_down;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ static void controller_sdl_read(OSContPad *pad) {
|
|||
if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)) pad->button |= R_TRIG;
|
||||
if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_A)) pad->button |= A_BUTTON;
|
||||
if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_X)) pad->button |= B_BUTTON;
|
||||
if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_RIGHTSTICK)) pad->button |= L_TRIG;
|
||||
|
||||
int16_t leftx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTX);
|
||||
int16_t lefty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTY);
|
||||
|
|
@ -78,8 +79,19 @@ static void controller_sdl_read(OSContPad *pad) {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (gImprovedCamera) {
|
||||
uint32_t magnitude_sq2 = (uint32_t)(rightx * rightx) + (uint32_t)(righty * righty);
|
||||
if (magnitude_sq > (uint32_t)(DEADZONE * DEADZONE)) {
|
||||
pad->stick2_x = rightx / 0x100;
|
||||
//int stick_y = -righty / 0x100;
|
||||
//pad->stick2_y = stick_y == 128 ? 127 : stick_y;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (rightx < -0x4000) pad->button |= L_CBUTTONS;
|
||||
if (rightx > 0x4000) pad->button |= R_CBUTTONS;
|
||||
}
|
||||
|
||||
if (righty < -0x4000) pad->button |= U_CBUTTONS;
|
||||
if (righty > 0x4000) pad->button |= D_CBUTTONS;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,16 @@ static void controller_wup_read(OSContPad *pad) {
|
|||
if (buttons & 0x0100) pad->button |= A_BUTTON;
|
||||
if (buttons & 0x0200) pad->button |= B_BUTTON;
|
||||
if (buttons & 0x1000) pad->button |= L_TRIG;
|
||||
if (gImprovedCamera) {
|
||||
if (stick2_x != 0 || stick2_y != 0) {
|
||||
pad->stick2_x = saturate(axis[2] - 128 - 0);
|
||||
//pad->stick2_y = saturate(axis[3] - 128 - 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (axis[2] < 0x40) pad->button |= L_CBUTTONS;
|
||||
if (axis[2] > 0xC0) pad->button |= R_CBUTTONS;
|
||||
}
|
||||
if (axis[3] < 0x40) pad->button |= D_CBUTTONS;
|
||||
if (axis[3] > 0xC0) pad->button |= U_CBUTTONS;
|
||||
int8_t stick_x = saturate(axis[0] - 128 - 0);
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@
|
|||
#include <ultra64.h>
|
||||
|
||||
#include "controller_api.h"
|
||||
#include "game/settings.h"
|
||||
|
||||
#define DEADZONE 4960
|
||||
#define DEADZONE gControllerDeadzone*10
|
||||
|
||||
static void xinput_init(void) {
|
||||
}
|
||||
|
|
@ -25,9 +26,17 @@ static void xinput_read(OSContPad *pad) {
|
|||
if (gp->bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) pad->button |= R_TRIG;
|
||||
if (gp->wButtons & XINPUT_GAMEPAD_A) pad->button |= A_BUTTON;
|
||||
if (gp->wButtons & XINPUT_GAMEPAD_X) pad->button |= B_BUTTON;
|
||||
if (gp->wButtons & XINPUT_GAMEPAD_DPAD_LEFT) pad->button |= L_TRIG;
|
||||
if (gp->wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) pad->button |= L_TRIG;
|
||||
|
||||
if (gp->wButtons & XINPUT_GAMEPAD_DPAD_LEFT) pad->button |= L_JPAD;
|
||||
if (gp->wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) pad->button |= R_JPAD;
|
||||
if (gp->wButtons & XINPUT_GAMEPAD_DPAD_UP) pad->button |= U_JPAD;
|
||||
if (gp->wButtons & XINPUT_GAMEPAD_DPAD_DOWN) pad->button |= D_JPAD;
|
||||
|
||||
if (!gImprovedCamera) {
|
||||
if (gp->sThumbRX < -0x4000) pad->button |= L_CBUTTONS;
|
||||
if (gp->sThumbRX > 0x4000) pad->button |= R_CBUTTONS;
|
||||
}
|
||||
if (gp->sThumbRY < -0x4000) pad->button |= D_CBUTTONS;
|
||||
if (gp->sThumbRY > 0x4000) pad->button |= U_CBUTTONS;
|
||||
|
||||
|
|
@ -36,6 +45,13 @@ static void xinput_read(OSContPad *pad) {
|
|||
pad->stick_x = gp->sThumbLX / 0x100;
|
||||
pad->stick_y = gp->sThumbLY / 0x100;
|
||||
}
|
||||
if (gImprovedCamera) {
|
||||
uint32_t magnitude_sq2 = (uint32_t)(gp->sThumbRX * gp->sThumbRX) + (uint32_t)(gp->sThumbRY * gp->sThumbRY);
|
||||
if (magnitude_sq2 > (uint32_t)(DEADZONE * DEADZONE)) {
|
||||
pad->stick2_x = gp->sThumbRX / 0x100;
|
||||
// pad->stick2_y = gp->sThumbRY / 0x100;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* XBR filter: from the FFmpeg project
|
||||
*
|
||||
* Copyright (c) 2011, 2012 Hyllian/Jararaca <sergiogdb@gmail.com>
|
||||
* Copyright (c) 2014 Arwa Arif <arwaarif1994@gmail.com>
|
||||
* Copyright (c) 2015 Treeki <treeki@gmail.com>
|
||||
*
|
||||
*
|
||||
* hqx filter: from the hqx project
|
||||
* Copyright (C) 2003 Maxim Stepin ( maxst@hiend3d.com )
|
||||
* Copyright (C) 2010 Cameron Zemek ( grom@zeminvaders.net)
|
||||
* Copyright (c) 2015 Treeki <treeki@gmail.com>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __LIBXBR_FILTERS_H_INCLUDED
|
||||
#define __LIBXBR_FILTERS_H_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define XBR_INLINE __inline
|
||||
|
||||
#ifdef XBR_INTERNAL
|
||||
#define XBR_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define XBR_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define XBR_INLINE inline
|
||||
#define XBR_EXPORT
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t rgbtoyuv[1<<24];
|
||||
} xbr_data;
|
||||
|
||||
typedef struct {
|
||||
const uint8_t *input;
|
||||
uint8_t *output;
|
||||
int inWidth, inHeight;
|
||||
int inPitch, outPitch;
|
||||
const xbr_data *data;
|
||||
} xbr_params;
|
||||
|
||||
XBR_EXPORT void xbr_filter_xbr2x(const xbr_params *ctx);
|
||||
XBR_EXPORT void xbr_filter_xbr3x(const xbr_params *ctx);
|
||||
XBR_EXPORT void xbr_filter_xbr4x(const xbr_params *ctx);
|
||||
|
||||
XBR_EXPORT void xbr_filter_hq2x(const xbr_params *ctx);
|
||||
XBR_EXPORT void xbr_filter_hq3x(const xbr_params *ctx);
|
||||
XBR_EXPORT void xbr_filter_hq4x(const xbr_params *ctx);
|
||||
|
||||
XBR_EXPORT void xbr_init_data(xbr_data *data);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include "gfx_screen_config.h"
|
||||
|
||||
#include "./game/settings.h"
|
||||
|
||||
#define THREE_POINT_FILTERING 0
|
||||
#define DEBUG_D3D 0
|
||||
|
||||
|
|
@ -143,9 +145,15 @@ static void create_render_target_views(bool is_resize) {
|
|||
// Resize swap chain buffers
|
||||
|
||||
ThrowIfFailed(d3d.swap_chain->GetDesc1(&desc1));
|
||||
if (gCustomInternalResolution) {
|
||||
ThrowIfFailed(d3d.swap_chain->ResizeBuffers(0, gInternalResolutionWidth, gInternalResolutionHeight, DXGI_FORMAT_UNKNOWN, desc1.Flags),
|
||||
gfx_dxgi_get_h_wnd(), "Failed to resize IDXGISwapChain buffers.");
|
||||
}
|
||||
else {
|
||||
ThrowIfFailed(d3d.swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, desc1.Flags),
|
||||
gfx_dxgi_get_h_wnd(), "Failed to resize IDXGISwapChain buffers.");
|
||||
}
|
||||
}
|
||||
|
||||
// Get new size
|
||||
|
||||
|
|
@ -247,6 +255,20 @@ static void gfx_d3d11_init(void) {
|
|||
// Create the swap chain
|
||||
d3d.swap_chain = gfx_dxgi_create_swap_chain(d3d.device.Get());
|
||||
|
||||
// Enable MSAA
|
||||
// I fucking TRIED but couldn't get it working I'm STUPID if anyone reading this that knows what they are doing let me know lol
|
||||
/*
|
||||
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc;
|
||||
ThrowIfFailed(d3d.swap_chain->GetDesc1(&swap_chain_desc));
|
||||
|
||||
u_int num_levels = 0;
|
||||
HRESULT hr = d3d.device->CheckMultisampleQualityLevels(swap_chain_desc.Format, D3D10_MAX_MULTISAMPLE_SAMPLE_COUNT, &num_levels);
|
||||
if (hr == S_OK) {
|
||||
swap_chain_desc.SampleDesc.Count = D3D10_MAX_MULTISAMPLE_SAMPLE_COUNT;
|
||||
swap_chain_desc.SampleDesc.Quality = num_levels-1;
|
||||
}
|
||||
*/
|
||||
|
||||
// Create D3D Debug device if in debug mode
|
||||
|
||||
#if DEBUG_D3D
|
||||
|
|
@ -441,8 +463,14 @@ static void gfx_d3d11_upload_texture(const uint8_t *rgba32_buf, int width, int h
|
|||
D3D11_TEXTURE2D_DESC texture_desc;
|
||||
ZeroMemory(&texture_desc, sizeof(D3D11_TEXTURE2D_DESC));
|
||||
|
||||
if (gFXMode) {
|
||||
texture_desc.Width = 1;
|
||||
texture_desc.Height = 1;
|
||||
}
|
||||
else {
|
||||
texture_desc.Width = width;
|
||||
texture_desc.Height = height;
|
||||
}
|
||||
texture_desc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
|
|
@ -682,8 +710,14 @@ static void gfx_d3d11_start_frame(void) {
|
|||
d3d.per_frame_cb_data.noise_frame = 0;
|
||||
}
|
||||
float aspect_ratio = (float) d3d.current_width / (float) d3d.current_height;
|
||||
if (gNoiseType) {
|
||||
d3d.per_frame_cb_data.noise_scale_x = d3d.current_width;
|
||||
d3d.per_frame_cb_data.noise_scale_y = d3d.current_height;
|
||||
}
|
||||
else {
|
||||
d3d.per_frame_cb_data.noise_scale_x = 120 * aspect_ratio; // 120 = N64 height resolution (240) / 2
|
||||
d3d.per_frame_cb_data.noise_scale_y = 120;
|
||||
}
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE ms;
|
||||
ZeroMemory(&ms, sizeof(D3D11_MAPPED_SUBRESOURCE));
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@
|
|||
|
||||
#include "gfx_screen_config.h"
|
||||
|
||||
#include "./game/settings.h"
|
||||
|
||||
#define DEBUG_D3D 0
|
||||
|
||||
using namespace Microsoft::WRL; // For ComPtr
|
||||
|
|
@ -302,8 +304,14 @@ static void gfx_direct3d12_upload_texture(const uint8_t *rgba32_buf, int width,
|
|||
D3D12_RESOURCE_DESC texture_desc = {};
|
||||
texture_desc.MipLevels = 1;
|
||||
texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
if (gFXMode) {
|
||||
texture_desc.Width = 1;
|
||||
texture_desc.Height = 1;
|
||||
}
|
||||
else {
|
||||
texture_desc.Width = width;
|
||||
texture_desc.Height = height;
|
||||
}
|
||||
texture_desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
texture_desc.DepthOrArraySize = 1;
|
||||
texture_desc.SampleDesc.Count = 1;
|
||||
|
|
@ -609,8 +617,14 @@ static void gfx_direct3d12_start_frame(void) {
|
|||
d3d.noise_cb_data.noise_frame = 0;
|
||||
}
|
||||
float aspect_ratio = (float) d3d.current_width / (float) d3d.current_height;
|
||||
if (gNoiseType) {
|
||||
d3d.noise_cb_data.noise_scale_x = d3d.current_width;
|
||||
d3d.noise_cb_data.noise_scale_y = d3d.current_height;
|
||||
}
|
||||
else {
|
||||
d3d.noise_cb_data.noise_scale_x = 120 * aspect_ratio; // 120 = N64 height resolution (240) / 2
|
||||
d3d.noise_cb_data.noise_scale_y = 120;
|
||||
}
|
||||
memcpy(d3d.mapped_noise_cb_address, &d3d.noise_cb_data, sizeof(struct NoiseCB));
|
||||
|
||||
d3d.vbuf_pos = 0;
|
||||
|
|
@ -671,7 +685,13 @@ static void gfx_direct3d12_on_resize(void) {
|
|||
if (d3d.render_targets[0].Get() != nullptr) {
|
||||
d3d.render_targets[0].Reset();
|
||||
d3d.render_targets[1].Reset();
|
||||
if (gCustomInternalResolution) {
|
||||
ThrowIfFailed(d3d.swap_chain->ResizeBuffers(0, gInternalResolutionWidth, gInternalResolutionHeight, DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT));
|
||||
}
|
||||
else {
|
||||
ThrowIfFailed(d3d.swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT));
|
||||
}
|
||||
|
||||
d3d.frame_index = d3d.swap_chain->GetCurrentBackBufferIndex();
|
||||
create_render_target_views();
|
||||
create_depth_buffer();
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <shellscalingapi.h>
|
||||
|
||||
#include "./game/settings.h"
|
||||
|
||||
#ifndef _LANGUAGE_C
|
||||
#define _LANGUAGE_C
|
||||
|
|
@ -143,9 +144,43 @@ static void toggle_borderless_window_full_screen(bool enable, bool call_callback
|
|||
return;
|
||||
}
|
||||
|
||||
// Get the primary monitor
|
||||
POINT zero = { 0, 0 };
|
||||
HMONITOR h_monitor = MonitorFromPoint(zero, MONITOR_DEFAULTTOPRIMARY);
|
||||
|
||||
// Get info from that monitor
|
||||
MONITORINFOEX monitor_info;
|
||||
monitor_info.cbSize = sizeof(MONITORINFOEX);
|
||||
GetMonitorInfo(h_monitor, &monitor_info);
|
||||
RECT primary = monitor_info.rcMonitor;
|
||||
|
||||
if (!enable) {
|
||||
|
||||
if (gCustomFullscreenResolution) {
|
||||
ChangeDisplaySettings(NULL, CDS_RESET);
|
||||
}
|
||||
RECT r = dxgi.last_window_rect;
|
||||
|
||||
// Prevent the window from going outside the primary display
|
||||
if (r.left > primary.right) {
|
||||
r.left -= primary.right;
|
||||
r.right -= primary.right;
|
||||
}
|
||||
if (r.top > primary.bottom) {
|
||||
r.top -= primary.bottom;
|
||||
r.bottom -= primary.bottom;
|
||||
}
|
||||
|
||||
if (r.right < primary.left) {
|
||||
r.left += primary.left;
|
||||
r.right += primary.left;
|
||||
}
|
||||
|
||||
if (r.bottom < primary.top) {
|
||||
r.top += primary.top;
|
||||
r.bottom += primary.top;
|
||||
}
|
||||
|
||||
// Set in window mode with the last saved position and size
|
||||
SetWindowLongPtr(dxgi.h_wnd, GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW);
|
||||
|
||||
|
|
@ -161,6 +196,25 @@ static void toggle_borderless_window_full_screen(bool enable, bool call_callback
|
|||
|
||||
dxgi.is_full_screen = false;
|
||||
} else {
|
||||
|
||||
if (gCustomFullscreenResolution) {
|
||||
|
||||
DEVMODE fullscreenSettings;
|
||||
|
||||
memset (&fullscreenSettings, 0, sizeof (fullscreenSettings));
|
||||
fullscreenSettings.dmSize = sizeof (fullscreenSettings);
|
||||
fullscreenSettings.dmPelsWidth = gFullscreenWidth;
|
||||
fullscreenSettings.dmPelsHeight = gFullscreenHeight;
|
||||
fullscreenSettings.dmBitsPerPel = 32;
|
||||
fullscreenSettings.dmDisplayFrequency = gFullscreenRefreshRate;
|
||||
fullscreenSettings.dmFields = DM_PELSWIDTH |
|
||||
DM_PELSHEIGHT |
|
||||
DM_BITSPERPEL |
|
||||
DM_DISPLAYFREQUENCY;
|
||||
|
||||
ChangeDisplaySettings(&fullscreenSettings, CDS_FULLSCREEN);
|
||||
}
|
||||
|
||||
// Save if window is maximized or not
|
||||
WINDOWPLACEMENT window_placement;
|
||||
window_placement.length = sizeof(WINDOWPLACEMENT);
|
||||
|
|
@ -170,18 +224,9 @@ static void toggle_borderless_window_full_screen(bool enable, bool call_callback
|
|||
// Save window position and size if the window is not maximized
|
||||
GetWindowRect(dxgi.h_wnd, &dxgi.last_window_rect);
|
||||
|
||||
// Get in which monitor the window is
|
||||
HMONITOR h_monitor = MonitorFromWindow(dxgi.h_wnd, MONITOR_DEFAULTTONEAREST);
|
||||
|
||||
// Get info from that monitor
|
||||
MONITORINFOEX monitor_info;
|
||||
monitor_info.cbSize = sizeof(MONITORINFOEX);
|
||||
GetMonitorInfo(h_monitor, &monitor_info);
|
||||
RECT r = monitor_info.rcMonitor;
|
||||
|
||||
// Set borderless full screen to that monitor
|
||||
// Set borderless full screen to the primary monitor
|
||||
SetWindowLongPtr(dxgi.h_wnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
|
||||
SetWindowPos(dxgi.h_wnd, HWND_TOP, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_FRAMECHANGED);
|
||||
SetWindowPos(dxgi.h_wnd, HWND_TOP, primary.left, primary.top, primary.right - primary.left, primary.bottom - primary.top, SWP_FRAMECHANGED);
|
||||
|
||||
ShowCursor(FALSE);
|
||||
|
||||
|
|
@ -536,13 +581,19 @@ void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*crea
|
|||
}
|
||||
|
||||
ComPtr<IDXGISwapChain1> gfx_dxgi_create_swap_chain(IUnknown *device) {
|
||||
bool win8 = IsWindows8OrGreater(); // DXGI_SCALING_NONE is only supported on Win8 and beyond
|
||||
bool win8 = IsWindows8OrGreater() && !gCustomInternalResolution; // DXGI_SCALING_NONE is only supported on Win8 and beyond
|
||||
bool dxgi_13 = dxgi.CreateDXGIFactory2 != nullptr; // DXGI 1.3 introduced waitable object
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
|
||||
swap_chain_desc.BufferCount = 2;
|
||||
if (gCustomInternalResolution) {
|
||||
swap_chain_desc.Width = gInternalResolutionWidth;
|
||||
swap_chain_desc.Height = gInternalResolutionHeight;
|
||||
}
|
||||
else {
|
||||
swap_chain_desc.Width = 0;
|
||||
swap_chain_desc.Height = 0;
|
||||
}
|
||||
swap_chain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swap_chain_desc.Scaling = win8 ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH;
|
||||
|
|
@ -550,6 +601,7 @@ ComPtr<IDXGISwapChain1> gfx_dxgi_create_swap_chain(IUnknown *device) {
|
|||
swap_chain_desc.Flags = dxgi_13 ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT : 0;
|
||||
swap_chain_desc.SampleDesc.Count = 1;
|
||||
|
||||
|
||||
run_as_dpi_aware([&] () {
|
||||
// When setting size for the buffers, the values that DXGI puts into the desc (that can later be retrieved by GetDesc1)
|
||||
// have been divided by the current scaling factor. By making this call dpi aware, no division will be performed.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
#include "gfx_window_manager_api.h"
|
||||
#include "gfx_screen_config.h"
|
||||
|
||||
#include "./game/game_init.h"
|
||||
|
||||
#define GFX_API_NAME "GLX - OpenGL"
|
||||
|
||||
#ifdef VERSION_EU
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "gfx_cc.h"
|
||||
#include "gfx_rendering_api.h"
|
||||
|
||||
#include "./game/settings.h"
|
||||
|
||||
struct ShaderProgram {
|
||||
uint32_t shader_id;
|
||||
GLuint opengl_program_id;
|
||||
|
|
@ -408,7 +410,12 @@ static void gfx_opengl_select_texture(int tile, GLuint texture_id) {
|
|||
}
|
||||
|
||||
static void gfx_opengl_upload_texture(const uint8_t *rgba32_buf, int width, int height) {
|
||||
if (gFXMode) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba32_buf);
|
||||
}
|
||||
else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba32_buf);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t gfx_cm_to_opengl(uint32_t val) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@
|
|||
#include "gfx_rendering_api.h"
|
||||
#include "gfx_screen_config.h"
|
||||
|
||||
#include "filters.h"
|
||||
|
||||
#include "../../game/game_init.h"
|
||||
#include "../../game/settings.h"
|
||||
#include "../../engine/math_util.h"
|
||||
|
||||
#define SUPPORT_CHECK(x) assert(x)
|
||||
|
||||
// SCALE_M_N: upscale/downscale M-bit integer to N-bit
|
||||
|
|
@ -255,15 +261,18 @@ static bool gfx_texture_cache_lookup(int tile, struct TextureHashmapNode **n, co
|
|||
while (*node != NULL && *node - gfx_texture_cache.pool < (int)gfx_texture_cache.pool_pos) {
|
||||
if ((*node)->texture_addr == orig_addr && (*node)->fmt == fmt && (*node)->siz == siz) {
|
||||
gfx_rapi->select_texture(tile, (*node)->texture_id);
|
||||
if (gEncoreMode)
|
||||
(*node)->linear_filter = (get_palette() == 12);
|
||||
*n = *node;
|
||||
return true;
|
||||
}
|
||||
node = &(*node)->next;
|
||||
}
|
||||
if (gfx_texture_cache.pool_pos == sizeof(gfx_texture_cache.pool) / sizeof(struct TextureHashmapNode)) {
|
||||
if (gfx_texture_cache.pool_pos == sizeof(gfx_texture_cache.pool) / sizeof(struct TextureHashmapNode) || gReimportTextures) {
|
||||
// Pool is full. We just invalidate everything and start over.
|
||||
gfx_texture_cache.pool_pos = 0;
|
||||
node = &gfx_texture_cache.hashmap[hash];
|
||||
gReimportTextures = 0;
|
||||
//puts("Clearing texture cache");
|
||||
}
|
||||
*node = &gfx_texture_cache.pool[gfx_texture_cache.pool_pos++];
|
||||
|
|
@ -274,7 +283,7 @@ static bool gfx_texture_cache_lookup(int tile, struct TextureHashmapNode **n, co
|
|||
gfx_rapi->set_sampler_parameters(tile, false, 0, 0);
|
||||
(*node)->cms = 0;
|
||||
(*node)->cmt = 0;
|
||||
(*node)->linear_filter = false;
|
||||
(*node)->linear_filter = (get_palette() == 12); // Use nearest neighbor on Wet Dry World
|
||||
(*node)->next = NULL;
|
||||
(*node)->texture_addr = orig_addr;
|
||||
(*node)->fmt = fmt;
|
||||
|
|
@ -285,6 +294,9 @@ static bool gfx_texture_cache_lookup(int tile, struct TextureHashmapNode **n, co
|
|||
|
||||
static void import_texture_rgba16(int tile) {
|
||||
uint8_t rgba32_buf[8192];
|
||||
uint8_t rgba32_buf_out[8192*4*4];
|
||||
xbr_data *xbrData;
|
||||
xbr_params xbrParams;
|
||||
|
||||
for (uint32_t i = 0; i < rdp.loaded_texture[tile].size_bytes / 2; i++) {
|
||||
uint16_t col16 = (rdp.loaded_texture[tile].addr[2 * i] << 8) | rdp.loaded_texture[tile].addr[2 * i + 1];
|
||||
|
|
@ -292,16 +304,183 @@ static void import_texture_rgba16(int tile) {
|
|||
uint8_t r = col16 >> 11;
|
||||
uint8_t g = (col16 >> 6) & 0x1f;
|
||||
uint8_t b = (col16 >> 1) & 0x1f;
|
||||
if ((rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) != G_TF_POINT) {
|
||||
// Return different palettes
|
||||
switch (get_palette()) {
|
||||
default:
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(r);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(g);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(b);
|
||||
break;
|
||||
case 1: // Castle grounds
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(r);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(g);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(min(b+r*0.125+g*0.25f,31));
|
||||
break;
|
||||
case 2: //Bob Omb Battlefield
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(max(min(r*1.125+g*0.625-b*0.625,31),0));
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(g);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(max(min(b*1.0625-(r+g)*0.03125,31), 0));
|
||||
break;
|
||||
case 3: // Whomp's Fortress
|
||||
case 21: // Metal Cave
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(min(r+g*0.625f+b*0.0625f,31));
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(min(g+r*0.25f+b*0.03125,31));
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(b);
|
||||
break;
|
||||
case 4: // Jolly Roger Bay
|
||||
case 15: // Tick Tock Clock
|
||||
case 22: // Wing Mario Over the Rainbows
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(min(r*0.75, 31)*0.75);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(min(g*0.5+r*0.0625+b*0.0625, 31)*0.75);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(min(b+r*0.5+g*0.5,31)*0.75);
|
||||
break;
|
||||
case 5: // Cool Cool Mountain
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(r);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(g);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(min(b*0.96875+r*0.5f+g*0.5f,31));
|
||||
break;
|
||||
case 6: // Big Boo's Haunt
|
||||
case 19: // Sky
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8((r+g+b)/3);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8((r+g+b)/3);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8((r+g+b)/3);
|
||||
break;
|
||||
case 7: // Hazy Maze Cave
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(max(min(r-g*0.5+b*0.5,31),0));
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(max(min((g-r*0.5+b*0.5)*1.5-(r-g*0.5+b*0.5+b*0.75+g*0.25)*0.25, 31),0));
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(min(b*0.75+g*0.25,31));
|
||||
break;
|
||||
case 8: // Lethal Lava Land
|
||||
case 23: // Vanish Cap area
|
||||
case 10: // Dire Dire Docks
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(min(r+g*0.5+b*0.5, 31));
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(min(g+r*0.0625+b*0.0625, 31));
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(b*0.875);
|
||||
break;
|
||||
case 9: // Shitting Sand Land
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(r);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(g);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(min(b*0.5+r*0.25+g*0.25, 31));
|
||||
break;
|
||||
case 11: // Snowman
|
||||
case 24: // Shit level
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(min(r+b*0.25, 31));
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(g);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(b);
|
||||
break;
|
||||
case 12: // Wet Dry World
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(min(round(sqrt(r/31.0f)*8)*4,31));
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(min(round(sqrt(g/31.0f)*8)*4,31));
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(min(round(sqrt(b/31.0f)*8)*4,31));
|
||||
break;
|
||||
case 13: // Donkey Slide
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(max(min(r+g*1.25-b*1.5,31), 0));
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(g);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(b);
|
||||
break;
|
||||
case 14: // Tiny Huge Island
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(min(r*0.75, 31));
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(min(g*0.5+r*0.0625+b*0.0625, 31));
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(min(b+r*0.5+g*0.5,31));
|
||||
break;
|
||||
case 16: // Rainbow Ride
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(r);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(g);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(max(min(b+g*1.25-r*0.5,31),0));
|
||||
break;
|
||||
case 17: // Dank world
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(r);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(b);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(g);
|
||||
break;
|
||||
case 18: // Bowser in the Fire Sea
|
||||
if (r > (g+b)*2) {
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(r);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(min(g*0.875+r*0.0625+b*0.0625, 31)*0.3125+g*0.5);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(min(b+r*0.75+g*0.75,31)*0.625);
|
||||
}
|
||||
else
|
||||
{
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(r);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(min(g*0.875+r*0.0625+b*0.0625, 31)*0.875);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(min(b+r*0.75+g*0.75,31)*0.875);
|
||||
}
|
||||
break;
|
||||
case 20: // Secret Slide
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(r);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8((r+g+b)/3);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8((r+g+b)/3);
|
||||
break;
|
||||
case 25: // Secret Aquarium
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(r*0.875);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(min(g*0.875+r*0.0625+b*0.0625, 31));
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(min(b+r*0.75+g*0.75,31));
|
||||
break;
|
||||
case 26: // Ending
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(min((r+g+b)/2,31));
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(min((r+g+b)/2.5,31));
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(min((r+g+b)/3,31));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
rgba32_buf[4*i + 0] = SCALE_5_8(r);
|
||||
rgba32_buf[4*i + 1] = SCALE_5_8(g);
|
||||
rgba32_buf[4*i + 2] = SCALE_5_8(b);
|
||||
}
|
||||
|
||||
rgba32_buf[4*i + 3] = a ? 255 : 0;
|
||||
}
|
||||
|
||||
uint32_t width = rdp.texture_tile.line_size_bytes / 2;
|
||||
uint32_t height = rdp.loaded_texture[tile].size_bytes / rdp.texture_tile.line_size_bytes;
|
||||
|
||||
if (gTextureUpscaling && (rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) != G_TF_POINT) {
|
||||
xbrData = malloc(sizeof(xbr_data));
|
||||
xbr_init_data(xbrData);
|
||||
|
||||
xbrParams.data = xbrData;
|
||||
xbrParams.input = rgba32_buf;
|
||||
xbrParams.output = rgba32_buf_out;
|
||||
xbrParams.inWidth = width;
|
||||
xbrParams.inHeight = height;
|
||||
xbrParams.inPitch = width * 4;
|
||||
xbrParams.outPitch = width * 4 * 4;
|
||||
|
||||
switch (gTextureUpscaling) {
|
||||
case 1: xbr_filter_hq4x(&xbrParams); break;
|
||||
case 2: xbr_filter_xbr4x(&xbrParams); break;
|
||||
}
|
||||
|
||||
free(xbrData);
|
||||
gfx_rapi->upload_texture(rgba32_buf_out, width*4, height*4);
|
||||
}
|
||||
|
||||
else if (gHUDUpscaling && (rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) == G_TF_POINT) {
|
||||
xbrData = malloc(sizeof(xbr_data));
|
||||
xbr_init_data(xbrData);
|
||||
|
||||
xbrParams.data = xbrData;
|
||||
xbrParams.input = rgba32_buf;
|
||||
xbrParams.output = rgba32_buf_out;
|
||||
xbrParams.inWidth = width;
|
||||
xbrParams.inHeight = height;
|
||||
xbrParams.inPitch = width * 4;
|
||||
xbrParams.outPitch = width * 4 * 4;
|
||||
|
||||
switch (gHUDUpscaling) {
|
||||
case 1: xbr_filter_hq4x(&xbrParams); break;
|
||||
case 2: xbr_filter_xbr4x(&xbrParams); break;
|
||||
}
|
||||
|
||||
free(xbrData);
|
||||
gfx_rapi->upload_texture(rgba32_buf_out, width*4, height*4);
|
||||
}
|
||||
else {
|
||||
gfx_rapi->upload_texture(rgba32_buf, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
static void import_texture_rgba32(int tile) {
|
||||
|
|
@ -568,6 +747,9 @@ static void gfx_sp_matrix(uint8_t parameters, const int32_t *addr) {
|
|||
|
||||
if (parameters & G_MTX_PROJECTION) {
|
||||
if (parameters & G_MTX_LOAD) {
|
||||
if(get_mirror()) {
|
||||
matrix[0][0] *= -1;
|
||||
}
|
||||
memcpy(rsp.P_matrix, matrix, sizeof(matrix));
|
||||
} else {
|
||||
gfx_matrix_mul(rsp.P_matrix, matrix, rsp.P_matrix);
|
||||
|
|
@ -735,10 +917,20 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx) {
|
|||
|
||||
switch (rsp.geometry_mode & G_CULL_BOTH) {
|
||||
case G_CULL_FRONT:
|
||||
if (get_mirror()) {
|
||||
if (cross >= 0) return;
|
||||
}
|
||||
else {
|
||||
if (cross <= 0) return;
|
||||
}
|
||||
break;
|
||||
case G_CULL_BACK:
|
||||
if (get_mirror()) {
|
||||
if (cross <= 0) return;
|
||||
}
|
||||
else {
|
||||
if (cross >= 0) return;
|
||||
}
|
||||
break;
|
||||
case G_CULL_BOTH:
|
||||
// Why is this even an option?
|
||||
|
|
@ -784,9 +976,9 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx) {
|
|||
uint32_t cc_id = rdp.combine_mode;
|
||||
|
||||
bool use_alpha = (rdp.other_mode_l & (G_BL_A_MEM << 18)) == 0;
|
||||
bool use_fog = (rdp.other_mode_l >> 30) == G_BL_CLR_FOG;
|
||||
bool use_fog = (rdp.other_mode_l >> 30) == G_BL_CLR_FOG && !gDisableFog;
|
||||
bool texture_edge = (rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA;
|
||||
bool use_noise = (rdp.other_mode_l & G_AC_DITHER) == G_AC_DITHER;
|
||||
bool use_noise = (rdp.other_mode_l & G_AC_DITHER) == G_AC_DITHER && gNoiseType != 2;
|
||||
|
||||
if (texture_edge) {
|
||||
use_alpha = true;
|
||||
|
|
@ -825,7 +1017,7 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx) {
|
|||
import_texture(i);
|
||||
rdp.textures_changed[i] = false;
|
||||
}
|
||||
bool linear_filter = (rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) != G_TF_POINT;
|
||||
bool linear_filter = (rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) != G_TF_POINT || gHUDFiltering;
|
||||
if (linear_filter != rendering_state.textures[i]->linear_filter || rdp.texture_tile.cms != rendering_state.textures[i]->cms || rdp.texture_tile.cmt != rendering_state.textures[i]->cmt) {
|
||||
gfx_flush();
|
||||
gfx_rapi->set_sampler_parameters(i, linear_filter, rdp.texture_tile.cms, rdp.texture_tile.cmt);
|
||||
|
|
@ -880,7 +1072,16 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx) {
|
|||
color = &rdp.prim_color;
|
||||
break;
|
||||
case CC_SHADE:
|
||||
if (get_palette() == 19) {
|
||||
tmp.r = (v_arr[i]->color.r+v_arr[i]->color.g+v_arr[i]->color.b)/3;
|
||||
tmp.g = (v_arr[i]->color.r+v_arr[i]->color.g+v_arr[i]->color.b)/3;
|
||||
tmp.b = (v_arr[i]->color.r+v_arr[i]->color.g+v_arr[i]->color.b)/3;
|
||||
tmp.a = v_arr[i]->color.a;
|
||||
color = &tmp;
|
||||
}
|
||||
else {
|
||||
color = &v_arr[i]->color;
|
||||
}
|
||||
break;
|
||||
case CC_ENV:
|
||||
color = &rdp.env_color;
|
||||
|
|
@ -1171,9 +1372,25 @@ static void gfx_dp_set_prim_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
|||
}
|
||||
|
||||
static void gfx_dp_set_fog_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
|
||||
switch (get_palette()) {
|
||||
default:
|
||||
rdp.fog_color.r = r;
|
||||
rdp.fog_color.g = g;
|
||||
rdp.fog_color.b = b;
|
||||
break;
|
||||
case 2: // bobomb
|
||||
rdp.fog_color.r = 255;
|
||||
rdp.fog_color.g = 255;
|
||||
rdp.fog_color.b = 247;
|
||||
break;
|
||||
case 4: // jollyy
|
||||
case 15: // clock
|
||||
rdp.fog_color.r = 11;
|
||||
rdp.fog_color.g = 3;
|
||||
rdp.fog_color.b = 63;
|
||||
break;
|
||||
}
|
||||
rdp.fog_color.a = a;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef GFX_SCREEN_CONFIG_H
|
||||
#define GFX_SCREEN_CONFIG_H
|
||||
|
||||
#define DESIRED_SCREEN_WIDTH 640
|
||||
#define DESIRED_SCREEN_HEIGHT 480
|
||||
#define DESIRED_SCREEN_WIDTH gWindowWidth
|
||||
#define DESIRED_SCREEN_HEIGHT gWindowHeight
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,19 +20,22 @@
|
|||
#include "gfx_window_manager_api.h"
|
||||
#include "gfx_screen_config.h"
|
||||
|
||||
#include "game/settings.h"
|
||||
|
||||
#define GFX_API_NAME "SDL2 - OpenGL"
|
||||
|
||||
static SDL_Window *wnd;
|
||||
static int inverted_scancode_table[512];
|
||||
static int vsync_enabled = 0;
|
||||
static unsigned int window_width = DESIRED_SCREEN_WIDTH;
|
||||
static unsigned int window_height = DESIRED_SCREEN_HEIGHT;
|
||||
|
||||
static bool fullscreen_state;
|
||||
static void (*on_fullscreen_changed_callback)(bool is_now_fullscreen);
|
||||
static bool (*on_key_down_callback)(int scancode);
|
||||
static bool (*on_key_up_callback)(int scancode);
|
||||
static void (*on_all_keys_up_callback)(void);
|
||||
|
||||
static Uint32 last_time;
|
||||
|
||||
const SDL_Scancode windows_scancode_table[] =
|
||||
{
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
|
|
@ -85,6 +88,9 @@ const SDL_Scancode scancode_rmapping_nonextended[][2] = {
|
|||
};
|
||||
|
||||
static void set_fullscreen(bool on, bool call_callback) {
|
||||
unsigned int window_width;
|
||||
unsigned int window_height;
|
||||
|
||||
if (fullscreen_state == on) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -92,15 +98,39 @@ static void set_fullscreen(bool on, bool call_callback) {
|
|||
|
||||
if (on) {
|
||||
SDL_DisplayMode mode;
|
||||
if (gCustomFullscreenResolution) {
|
||||
mode.format = SDL_PIXELFORMAT_ARGB8888;
|
||||
mode.w = gFullscreenWidth;
|
||||
mode.h = gFullscreenHeight;
|
||||
mode.refresh_rate = gFullscreenRefreshRate;
|
||||
mode.driverdata = 0;
|
||||
SDL_SetWindowDisplayMode(wnd, &mode);
|
||||
}
|
||||
else {
|
||||
SDL_GetDesktopDisplayMode(0, &mode);
|
||||
}
|
||||
window_width = mode.w;
|
||||
window_height = mode.h;
|
||||
|
||||
SDL_ShowCursor(false);
|
||||
} else {
|
||||
if (gCustomFullscreenResolution) {
|
||||
SDL_DisplayMode mode;
|
||||
SDL_GetDesktopDisplayMode(0, &mode);
|
||||
SDL_SetWindowDisplayMode(wnd, &mode);
|
||||
}
|
||||
window_width = DESIRED_SCREEN_WIDTH;
|
||||
window_height = DESIRED_SCREEN_HEIGHT;
|
||||
|
||||
SDL_ShowCursor(true);
|
||||
}
|
||||
SDL_SetWindowSize(wnd, window_width, window_height);
|
||||
if (gCustomFullscreenResolution) {
|
||||
SDL_SetWindowFullscreen(wnd, on ? SDL_WINDOW_FULLSCREEN : 0);
|
||||
}
|
||||
else {
|
||||
SDL_SetWindowFullscreen(wnd, on ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
||||
}
|
||||
|
||||
if (on_fullscreen_changed_callback != NULL && call_callback) {
|
||||
on_fullscreen_changed_callback(on);
|
||||
|
|
@ -160,10 +190,10 @@ static void gfx_sdl_init(const char *game_name, bool start_in_fullscreen) {
|
|||
//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
|
||||
|
||||
char title[512];
|
||||
int len = sprintf(title, "%s (%s)", game_name, GFX_API_NAME);
|
||||
sprintf(title, "%s (%s)", game_name, GFX_API_NAME);
|
||||
|
||||
wnd = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
window_width, window_height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
||||
DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
||||
|
||||
if (start_in_fullscreen) {
|
||||
set_fullscreen(true, false);
|
||||
|
|
@ -211,8 +241,10 @@ static void gfx_sdl_main_loop(void (*run_one_game_iter)(void)) {
|
|||
}
|
||||
|
||||
static void gfx_sdl_get_dimensions(uint32_t *width, uint32_t *height) {
|
||||
*width = window_width;
|
||||
*height = window_height;
|
||||
int w, h;
|
||||
SDL_GetWindowSize(wnd, &w, &h);
|
||||
*width = w;
|
||||
*height = h;
|
||||
}
|
||||
|
||||
static int translate_scancode(int scancode) {
|
||||
|
|
@ -239,27 +271,23 @@ static void gfx_sdl_onkeyup(int scancode) {
|
|||
|
||||
static void gfx_sdl_handle_events(void) {
|
||||
SDL_Event event;
|
||||
Uint8 *state = SDL_GetKeyboardState(NULL);
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
#ifndef TARGET_WEB
|
||||
// Scancodes are broken in Emscripten SDL2: https://bugzilla.libsdl.org/show_bug.cgi?id=3259
|
||||
case SDL_KEYDOWN:
|
||||
if (event.key.keysym.sym == SDLK_F10) {
|
||||
if (state[SDL_SCANCODE_RETURN] && state[SDL_SCANCODE_LALT]) {
|
||||
set_fullscreen(!fullscreen_state, true);
|
||||
break;
|
||||
}
|
||||
|
||||
gfx_sdl_onkeydown(event.key.keysym.scancode);
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
gfx_sdl_onkeyup(event.key.keysym.scancode);
|
||||
break;
|
||||
#endif
|
||||
case SDL_WINDOWEVENT:
|
||||
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||
window_width = event.window.data1;
|
||||
window_height = event.window.data2;
|
||||
}
|
||||
break;
|
||||
case SDL_QUIT:
|
||||
exit(0);
|
||||
}
|
||||
|
|
@ -267,18 +295,17 @@ static void gfx_sdl_handle_events(void) {
|
|||
}
|
||||
|
||||
static bool gfx_sdl_start_frame(void) {
|
||||
last_time = SDL_GetTicks();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void sync_framerate_with_timer(void) {
|
||||
// Number of milliseconds a frame should take (30 fps)
|
||||
const Uint32 FRAME_TIME = 1000 / 30;
|
||||
static Uint32 last_time;
|
||||
Uint32 elapsed = SDL_GetTicks() - last_time;
|
||||
|
||||
if (elapsed < FRAME_TIME)
|
||||
SDL_Delay(FRAME_TIME - elapsed);
|
||||
last_time += FRAME_TIME;
|
||||
}
|
||||
|
||||
static void gfx_sdl_swap_buffers_begin(void) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright (C) 2003 Maxim Stepin ( maxst@hiend3d.com )
|
||||
*
|
||||
* Copyright (C) 2010 Cameron Zemek ( grom@zeminvaders.net)
|
||||
* Copyright (C) 2011 Francois Gannaz <mytskine@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __INTERNAL_HQX_COMMON_H_
|
||||
#define __INTERNAL_HQX_COMMON_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define XBR_INTERNAL
|
||||
#include "filters.h"
|
||||
|
||||
#define MASK_2 0x0000FF00
|
||||
#define MASK_13 0x00FF00FF
|
||||
#define MASK_RGB 0x00FFFFFF
|
||||
#define MASK_ALPHA 0xFF000000
|
||||
|
||||
#define Ymask 0x00FF0000
|
||||
#define Umask 0x0000FF00
|
||||
#define Vmask 0x000000FF
|
||||
#define trY 0x00300000
|
||||
#define trU 0x00000700
|
||||
#define trV 0x00000006
|
||||
|
||||
/* RGB to YUV lookup table */
|
||||
static XBR_INLINE uint32_t rgb_to_yuv(const xbr_data *data, uint32_t c)
|
||||
{
|
||||
// Mask against MASK_RGB to discard the alpha channel
|
||||
return data->rgbtoyuv[MASK_RGB & c];
|
||||
}
|
||||
|
||||
/* Test if there is difference in color */
|
||||
static XBR_INLINE int yuv_diff(uint32_t yuv1, uint32_t yuv2) {
|
||||
return (( abs((yuv1 & Ymask) - (yuv2 & Ymask)) > trY ) ||
|
||||
( abs((yuv1 & Umask) - (yuv2 & Umask)) > trU ) ||
|
||||
( abs((yuv1 & Vmask) - (yuv2 & Vmask)) > trV ) );
|
||||
}
|
||||
|
||||
static XBR_INLINE int Diff(const xbr_data *data, uint32_t c1, uint32_t c2)
|
||||
{
|
||||
return yuv_diff(rgb_to_yuv(data, c1), rgb_to_yuv(data, c2));
|
||||
}
|
||||
|
||||
/* Interpolate functions */
|
||||
static XBR_INLINE uint32_t Interpolate_2(uint32_t c1, int w1, uint32_t c2, int w2, int s)
|
||||
{
|
||||
if (c1 == c2) {
|
||||
return c1;
|
||||
}
|
||||
return
|
||||
(((((c1 & MASK_ALPHA) >> 24) * w1 + ((c2 & MASK_ALPHA) >> 24) * w2) << (24-s)) & MASK_ALPHA) +
|
||||
((((c1 & MASK_2) * w1 + (c2 & MASK_2) * w2) >> s) & MASK_2) +
|
||||
((((c1 & MASK_13) * w1 + (c2 & MASK_13) * w2) >> s) & MASK_13);
|
||||
}
|
||||
|
||||
static XBR_INLINE uint32_t Interpolate_3(uint32_t c1, int w1, uint32_t c2, int w2, uint32_t c3, int w3, int s)
|
||||
{
|
||||
return
|
||||
(((((c1 & MASK_ALPHA) >> 24) * w1 + ((c2 & MASK_ALPHA) >> 24) * w2 + ((c3 & MASK_ALPHA) >> 24) * w3) << (24-s)) & MASK_ALPHA) +
|
||||
((((c1 & MASK_2) * w1 + (c2 & MASK_2) * w2 + (c3 & MASK_2) * w3) >> s) & MASK_2) +
|
||||
((((c1 & MASK_13) * w1 + (c2 & MASK_13) * w2 + (c3 & MASK_13) * w3) >> s) & MASK_13);
|
||||
}
|
||||
|
||||
static XBR_INLINE void Interp1(uint32_t * pc, uint32_t c1, uint32_t c2)
|
||||
{
|
||||
//*pc = (c1*3+c2) >> 2;
|
||||
*pc = Interpolate_2(c1, 3, c2, 1, 2);
|
||||
}
|
||||
|
||||
static XBR_INLINE void Interp2(uint32_t * pc, uint32_t c1, uint32_t c2, uint32_t c3)
|
||||
{
|
||||
//*pc = (c1*2+c2+c3) >> 2;
|
||||
*pc = Interpolate_3(c1, 2, c2, 1, c3, 1, 2);
|
||||
}
|
||||
|
||||
static XBR_INLINE void Interp3(uint32_t * pc, uint32_t c1, uint32_t c2)
|
||||
{
|
||||
//*pc = (c1*7+c2)/8;
|
||||
*pc = Interpolate_2(c1, 7, c2, 1, 3);
|
||||
}
|
||||
|
||||
static XBR_INLINE void Interp4(uint32_t * pc, uint32_t c1, uint32_t c2, uint32_t c3)
|
||||
{
|
||||
//*pc = (c1*2+(c2+c3)*7)/16;
|
||||
*pc = Interpolate_3(c1, 2, c2, 7, c3, 7, 4);
|
||||
}
|
||||
|
||||
static XBR_INLINE void Interp5(uint32_t * pc, uint32_t c1, uint32_t c2)
|
||||
{
|
||||
//*pc = (c1+c2) >> 1;
|
||||
*pc = Interpolate_2(c1, 1, c2, 1, 1);
|
||||
}
|
||||
|
||||
static XBR_INLINE void Interp6(uint32_t * pc, uint32_t c1, uint32_t c2, uint32_t c3)
|
||||
{
|
||||
//*pc = (c1*5+c2*2+c3)/8;
|
||||
*pc = Interpolate_3(c1, 5, c2, 2, c3, 1, 3);
|
||||
}
|
||||
|
||||
static XBR_INLINE void Interp7(uint32_t * pc, uint32_t c1, uint32_t c2, uint32_t c3)
|
||||
{
|
||||
//*pc = (c1*6+c2+c3)/8;
|
||||
*pc = Interpolate_3(c1, 6, c2, 1, c3, 1, 3);
|
||||
}
|
||||
|
||||
static XBR_INLINE void Interp8(uint32_t * pc, uint32_t c1, uint32_t c2)
|
||||
{
|
||||
//*pc = (c1*5+c2*3)/8;
|
||||
*pc = Interpolate_2(c1, 5, c2, 3, 3);
|
||||
}
|
||||
|
||||
static XBR_INLINE void Interp9(uint32_t * pc, uint32_t c1, uint32_t c2, uint32_t c3)
|
||||
{
|
||||
//*pc = (c1*2+(c2+c3)*3)/8;
|
||||
*pc = Interpolate_3(c1, 2, c2, 3, c3, 3, 3);
|
||||
}
|
||||
|
||||
static XBR_INLINE void Interp10(uint32_t * pc, uint32_t c1, uint32_t c2, uint32_t c3)
|
||||
{
|
||||
//*pc = (c1*14+c2+c3)/16;
|
||||
*pc = Interpolate_3(c1, 14, c2, 1, c3, 1, 4);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,337 @@
|
|||
/*
|
||||
* XBR filter extracted from FFmpeg into a separate library.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2011, 2012 Hyllian/Jararaca <sergiogdb@gmail.com>
|
||||
* Copyright (c) 2014 Arwa Arif <arwaarif1994@gmail.com>
|
||||
* Copyright (c) 2015 Treeki <treeki@gmail.com>
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* XBR Filter is used for depixelization of image.
|
||||
* This is based on Hyllian's xBR shader.
|
||||
*
|
||||
* @see http://www.libretro.com/forums/viewtopic.php?f=6&t=134
|
||||
* @see https://github.com/yoyofr/iFBA/blob/master/fba_src/src/intf/video/scalers/xbr.cpp
|
||||
*/
|
||||
|
||||
#define XBR_INTERNAL
|
||||
#include "filters.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define LB_MASK 0x00FEFEFE
|
||||
#define RED_BLUE_MASK 0x00FF00FF
|
||||
#define GREEN_MASK 0x0000FF00
|
||||
#define PART_MASK 0x00FF00FF
|
||||
|
||||
static uint32_t pixel_diff(uint32_t x, uint32_t y, const uint32_t *r2y)
|
||||
{
|
||||
#define YMASK 0xff0000
|
||||
#define UMASK 0x00ff00
|
||||
#define VMASK 0x0000ff
|
||||
|
||||
uint32_t yuv1 = r2y[x & 0xffffff];
|
||||
uint32_t yuv2 = r2y[y & 0xffffff];
|
||||
|
||||
return (abs((x >> 24) - (y >> 24))) +
|
||||
(abs((yuv1 & YMASK) - (yuv2 & YMASK)) >> 16) +
|
||||
(abs((yuv1 & UMASK) - (yuv2 & UMASK)) >> 8) +
|
||||
abs((yuv1 & VMASK) - (yuv2 & VMASK));
|
||||
}
|
||||
|
||||
#define ALPHA_BLEND_BASE(a, b, m, s) ( (PART_MASK & (((a) & PART_MASK) + (((((b) & PART_MASK) - ((a) & PART_MASK)) * (m)) >> (s)))) \
|
||||
| ((PART_MASK & ((((a) >> 8) & PART_MASK) + ((((((b) >> 8) & PART_MASK) - (((a) >> 8) & PART_MASK)) * (m)) >> (s)))) << 8))
|
||||
|
||||
#define ALPHA_BLEND_32_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 3)
|
||||
#define ALPHA_BLEND_64_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 2)
|
||||
#define ALPHA_BLEND_128_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 1)
|
||||
#define ALPHA_BLEND_192_W(a, b) ALPHA_BLEND_BASE(a, b, 3, 2)
|
||||
#define ALPHA_BLEND_224_W(a, b) ALPHA_BLEND_BASE(a, b, 7, 3)
|
||||
|
||||
|
||||
|
||||
#define df(A, B) pixel_diff(A, B, r2y)
|
||||
#define eq(A, B) (df(A, B) < 155)
|
||||
|
||||
#define FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
|
||||
N0, N1, N2, N3) do { \
|
||||
if (PE != PH && PE != PF) { \
|
||||
const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
|
||||
const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
|
||||
if (e <= i) { \
|
||||
const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
|
||||
if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI) \
|
||||
&& (!eq(PF,I4) && !eq(PH,I5)) \
|
||||
|| eq(PE,PG) || eq(PE,PC))) { \
|
||||
const unsigned ke = df(PF,PG); \
|
||||
const unsigned ki = df(PH,PC); \
|
||||
const int left = ke<<1 <= ki && PE != PG && PD != PG; \
|
||||
const int up = ke >= ki<<1 && PE != PC && PB != PC; \
|
||||
if (left && up) { \
|
||||
E[N3] = ALPHA_BLEND_224_W(E[N3], px); \
|
||||
E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
|
||||
E[N1] = E[N2]; \
|
||||
} else if (left) { \
|
||||
E[N3] = ALPHA_BLEND_192_W(E[N3], px); \
|
||||
E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
|
||||
} else if (up) { \
|
||||
E[N3] = ALPHA_BLEND_192_W(E[N3], px); \
|
||||
E[N1] = ALPHA_BLEND_64_W( E[N1], px); \
|
||||
} else { /* diagonal */ \
|
||||
E[N3] = ALPHA_BLEND_128_W(E[N3], px); \
|
||||
} \
|
||||
} else { \
|
||||
E[N3] = ALPHA_BLEND_128_W(E[N3], px); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FILT3(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
|
||||
N0, N1, N2, N3, N4, N5, N6, N7, N8) do { \
|
||||
if (PE != PH && PE != PF) { \
|
||||
const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
|
||||
const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
|
||||
if (e <= i) { \
|
||||
const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
|
||||
if (e < i && (!eq(PF,PB) && !eq(PF,PC) || !eq(PH,PD) && !eq(PH,PG) || eq(PE,PI) \
|
||||
&& (!eq(PF,F4) && !eq(PF,I4) || !eq(PH,H5) && !eq(PH,I5)) \
|
||||
|| eq(PE,PG) || eq(PE,PC))) { \
|
||||
const unsigned ke = df(PF,PG); \
|
||||
const unsigned ki = df(PH,PC); \
|
||||
const int left = ke<<1 <= ki && PE != PG && PD != PG; \
|
||||
const int up = ke >= ki<<1 && PE != PC && PB != PC; \
|
||||
if (left && up) { \
|
||||
E[N7] = ALPHA_BLEND_192_W(E[N7], px); \
|
||||
E[N6] = ALPHA_BLEND_64_W( E[N6], px); \
|
||||
E[N5] = E[N7]; \
|
||||
E[N2] = E[N6]; \
|
||||
E[N8] = px; \
|
||||
} else if (left) { \
|
||||
E[N7] = ALPHA_BLEND_192_W(E[N7], px); \
|
||||
E[N5] = ALPHA_BLEND_64_W( E[N5], px); \
|
||||
E[N6] = ALPHA_BLEND_64_W( E[N6], px); \
|
||||
E[N8] = px; \
|
||||
} else if (up) { \
|
||||
E[N5] = ALPHA_BLEND_192_W(E[N5], px); \
|
||||
E[N7] = ALPHA_BLEND_64_W( E[N7], px); \
|
||||
E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
|
||||
E[N8] = px; \
|
||||
} else { /* diagonal */ \
|
||||
E[N8] = ALPHA_BLEND_224_W(E[N8], px); \
|
||||
E[N5] = ALPHA_BLEND_32_W( E[N5], px); \
|
||||
E[N7] = ALPHA_BLEND_32_W( E[N7], px); \
|
||||
} \
|
||||
} else { \
|
||||
E[N8] = ALPHA_BLEND_128_W(E[N8], px); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FILT4(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
|
||||
N15, N14, N11, N3, N7, N10, N13, N12, N9, N6, N2, N1, N5, N8, N4, N0) do { \
|
||||
if (PE != PH && PE != PF) { \
|
||||
const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
|
||||
const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
|
||||
if (e <= i) { \
|
||||
const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
|
||||
if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI) \
|
||||
&& (!eq(PF,I4) && !eq(PH,I5)) \
|
||||
|| eq(PE,PG) || eq(PE,PC))) { \
|
||||
const unsigned ke = df(PF,PG); \
|
||||
const unsigned ki = df(PH,PC); \
|
||||
const int left = ke<<1 <= ki && PE != PG && PD != PG; \
|
||||
const int up = ke >= ki<<1 && PE != PC && PB != PC; \
|
||||
if (left && up) { \
|
||||
E[N13] = ALPHA_BLEND_192_W(E[N13], px); \
|
||||
E[N12] = ALPHA_BLEND_64_W( E[N12], px); \
|
||||
E[N15] = E[N14] = E[N11] = px; \
|
||||
E[N10] = E[N3] = E[N12]; \
|
||||
E[N7] = E[N13]; \
|
||||
} else if (left) { \
|
||||
E[N11] = ALPHA_BLEND_192_W(E[N11], px); \
|
||||
E[N13] = ALPHA_BLEND_192_W(E[N13], px); \
|
||||
E[N10] = ALPHA_BLEND_64_W( E[N10], px); \
|
||||
E[N12] = ALPHA_BLEND_64_W( E[N12], px); \
|
||||
E[N14] = px; \
|
||||
E[N15] = px; \
|
||||
} else if (up) { \
|
||||
E[N14] = ALPHA_BLEND_192_W(E[N14], px); \
|
||||
E[N7 ] = ALPHA_BLEND_192_W(E[N7 ], px); \
|
||||
E[N10] = ALPHA_BLEND_64_W( E[N10], px); \
|
||||
E[N3 ] = ALPHA_BLEND_64_W( E[N3 ], px); \
|
||||
E[N11] = px; \
|
||||
E[N15] = px; \
|
||||
} else { /* diagonal */ \
|
||||
E[N11] = ALPHA_BLEND_128_W(E[N11], px); \
|
||||
E[N14] = ALPHA_BLEND_128_W(E[N14], px); \
|
||||
E[N15] = px; \
|
||||
} \
|
||||
} else { \
|
||||
E[N15] = ALPHA_BLEND_128_W(E[N15], px); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static XBR_INLINE void xbr_filter(const xbr_params *params, int n)
|
||||
{
|
||||
int x, y;
|
||||
const uint32_t *r2y = params->data->rgbtoyuv;
|
||||
const int nl = params->outPitch >> 2;
|
||||
const int nl1 = nl + nl;
|
||||
const int nl2 = nl1 + nl;
|
||||
|
||||
for (y = 0; y < params->inHeight; y++) {
|
||||
|
||||
uint32_t *E = (uint32_t *)(params->output + y * params->outPitch * n);
|
||||
const uint32_t *sa2 = (uint32_t *)(params->input + y * params->inPitch - 8); /* center */
|
||||
const uint32_t *sa1 = sa2 - (params->inPitch>>2); /* up x1 */
|
||||
const uint32_t *sa0 = sa1 - (params->inPitch>>2); /* up x2 */
|
||||
const uint32_t *sa3 = sa2 + (params->inPitch>>2); /* down x1 */
|
||||
const uint32_t *sa4 = sa3 + (params->inPitch>>2); /* down x2 */
|
||||
|
||||
if (y <= 1) {
|
||||
sa0 = sa1;
|
||||
if (y == 0) {
|
||||
sa0 = sa1 = sa2;
|
||||
}
|
||||
}
|
||||
|
||||
if (y >= params->inHeight - 2) {
|
||||
sa4 = sa3;
|
||||
if (y == params->inHeight - 1) {
|
||||
sa4 = sa3 = sa2;
|
||||
}
|
||||
}
|
||||
|
||||
for (x = 0; x < params->inWidth; x++) {
|
||||
const uint32_t B1 = sa0[2];
|
||||
const uint32_t PB = sa1[2];
|
||||
const uint32_t PE = sa2[2];
|
||||
const uint32_t PH = sa3[2];
|
||||
const uint32_t H5 = sa4[2];
|
||||
|
||||
const int pprev = 2 - (x > 0);
|
||||
const uint32_t A1 = sa0[pprev];
|
||||
const uint32_t PA = sa1[pprev];
|
||||
const uint32_t PD = sa2[pprev];
|
||||
const uint32_t PG = sa3[pprev];
|
||||
const uint32_t G5 = sa4[pprev];
|
||||
|
||||
const int pprev2 = pprev - (x > 1);
|
||||
const uint32_t A0 = sa1[pprev2];
|
||||
const uint32_t D0 = sa2[pprev2];
|
||||
const uint32_t G0 = sa3[pprev2];
|
||||
|
||||
const int pnext = 3 - (x == params->inWidth - 1);
|
||||
const uint32_t C1 = sa0[pnext];
|
||||
const uint32_t PC = sa1[pnext];
|
||||
const uint32_t PF = sa2[pnext];
|
||||
const uint32_t PI = sa3[pnext];
|
||||
const uint32_t I5 = sa4[pnext];
|
||||
|
||||
const int pnext2 = pnext + 1 - (x >= params->inWidth - 2);
|
||||
const uint32_t C4 = sa1[pnext2];
|
||||
const uint32_t F4 = sa2[pnext2];
|
||||
const uint32_t I4 = sa3[pnext2];
|
||||
|
||||
if (n == 2) {
|
||||
E[0] = E[1] = // 0, 1
|
||||
E[nl] = E[nl + 1] = PE; // 2, 3
|
||||
|
||||
FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, 0, 1, nl, nl+1);
|
||||
FILT2(PE, PC, PF, PB, PI, PA, PH, PD, PG, I4, A1, I5, H5, A0, D0, B1, C1, F4, C4, G5, G0, nl, 0, nl+1, 1);
|
||||
FILT2(PE, PA, PB, PD, PC, PG, PF, PH, PI, C1, G0, C4, F4, G5, H5, D0, A0, B1, A1, I4, I5, nl+1, nl, 1, 0);
|
||||
FILT2(PE, PG, PD, PH, PA, PI, PB, PF, PC, A0, I5, A1, B1, I4, F4, H5, G5, D0, G0, C1, C4, 1, nl+1, 0, nl);
|
||||
} else if (n == 3) {
|
||||
E[0] = E[1] = E[2] = // 0, 1, 2
|
||||
E[nl] = E[nl+1] = E[nl+2] = // 3, 4, 5
|
||||
E[nl1] = E[nl1+1] = E[nl1+2] = PE; // 6, 7, 8
|
||||
|
||||
FILT3(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, 0, 1, 2, nl, nl+1, nl+2, nl1, nl1+1, nl1+2);
|
||||
FILT3(PE, PC, PF, PB, PI, PA, PH, PD, PG, I4, A1, I5, H5, A0, D0, B1, C1, F4, C4, G5, G0, nl1, nl, 0, nl1+1, nl+1, 1, nl1+2, nl+2, 2);
|
||||
FILT3(PE, PA, PB, PD, PC, PG, PF, PH, PI, C1, G0, C4, F4, G5, H5, D0, A0, B1, A1, I4, I5, nl1+2, nl1+1, nl1, nl+2, nl+1, nl, 2, 1, 0);
|
||||
FILT3(PE, PG, PD, PH, PA, PI, PB, PF, PC, A0, I5, A1, B1, I4, F4, H5, G5, D0, G0, C1, C4, 2, nl+2, nl1+2, 1, nl+1, nl1+1, 0, nl, nl1);
|
||||
} else if (n == 4) {
|
||||
E[0] = E[1] = E[2] = E[3] = // 0, 1, 2, 3
|
||||
E[nl] = E[nl+1] = E[nl+2] = E[nl+3] = // 4, 5, 6, 7
|
||||
E[nl1] = E[nl1+1] = E[nl1+2] = E[nl1+3] = // 8, 9, 10, 11
|
||||
E[nl2] = E[nl2+1] = E[nl2+2] = E[nl2+3] = PE; // 12, 13, 14, 15
|
||||
|
||||
FILT4(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, nl2+3, nl2+2, nl1+3, 3, nl+3, nl1+2, nl2+1, nl2, nl1+1, nl+2, 2, 1, nl+1, nl1, nl, 0);
|
||||
FILT4(PE, PC, PF, PB, PI, PA, PH, PD, PG, I4, A1, I5, H5, A0, D0, B1, C1, F4, C4, G5, G0, 3, nl+3, 2, 0, 1, nl+2, nl1+3, nl2+3, nl1+2, nl+1, nl, nl1, nl1+1, nl2+2, nl2+1, nl2);
|
||||
FILT4(PE, PA, PB, PD, PC, PG, PF, PH, PI, C1, G0, C4, F4, G5, H5, D0, A0, B1, A1, I4, I5, 0, 1, nl, nl2, nl1, nl+1, 2, 3, nl+2, nl1+1, nl2+1, nl2+2, nl1+2, nl+3, nl1+3, nl2+3);
|
||||
FILT4(PE, PG, PD, PH, PA, PI, PB, PF, PC, A0, I5, A1, B1, I4, F4, H5, G5, D0, G0, C1, C4, nl2, nl1, nl2+1, nl2+3, nl2+2, nl1+1, nl, 0, nl+1, nl1+2, nl1+3, nl+3, nl+2, 1, 2, 3);
|
||||
}
|
||||
|
||||
sa0 += 1;
|
||||
sa1 += 1;
|
||||
sa2 += 1;
|
||||
sa3 += 1;
|
||||
sa4 += 1;
|
||||
|
||||
E += n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define XBR_FUNC(size) \
|
||||
void xbr_filter_xbr##size##x(const xbr_params *params) \
|
||||
{ \
|
||||
xbr_filter(params, size); \
|
||||
}
|
||||
|
||||
XBR_FUNC(2)
|
||||
XBR_FUNC(3)
|
||||
XBR_FUNC(4)
|
||||
|
||||
|
||||
static XBR_INLINE int _max(int a, int b)
|
||||
{
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
static XBR_INLINE int _min(int a, int b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
|
||||
void xbr_init_data(xbr_data *data)
|
||||
{
|
||||
uint32_t c;
|
||||
int bg, rg, g;
|
||||
|
||||
for (bg = -255; bg < 256; bg++) {
|
||||
for (rg = -255; rg < 256; rg++) {
|
||||
const uint32_t u = (uint32_t)((-169*rg + 500*bg)/1000) + 128;
|
||||
const uint32_t v = (uint32_t)(( 500*rg - 81*bg)/1000) + 128;
|
||||
int startg = _max(-bg, _max(-rg, 0));
|
||||
int endg = _min(255-bg, _min(255-rg, 255));
|
||||
uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000);
|
||||
c = bg + (rg<<16) + 0x010101 * startg;
|
||||
for (g = startg; g <= endg; g++) {
|
||||
data->rgbtoyuv[c] = ((y++) << 16) + (u << 8) + v;
|
||||
c+= 0x010101;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include "controller/controller_keyboard.h"
|
||||
|
||||
#include "configfile.h"
|
||||
#include "game/settings.h"
|
||||
|
||||
#define CONFIG_FILE "sm64config.txt"
|
||||
|
||||
|
|
|
|||
|
|
@ -2100,3 +2100,29 @@ Arrgghh!\n\
|
|||
Anyone entering this cave\n\
|
||||
without permission will\n\
|
||||
meet certain disaster."))
|
||||
|
||||
DEFINE_DIALOG(DIALOG_170, 1, 5, 30, 200, _("\
|
||||
Wow! Another Power Star!\n\
|
||||
Do you want to keep\n\
|
||||
playing this level?\n\
|
||||
\n\
|
||||
//You Bet//Not Now"))
|
||||
|
||||
DEFINE_DIALOG(DIALOG_171, 1, 4, 30, 200, _("\
|
||||
Hey-ey, Mario, buddy,\n\
|
||||
howzit goin'?\n\
|
||||
Ok, so, basically, I am\n\
|
||||
very smol.\n\
|
||||
How about a race?\n\
|
||||
Ready...\n\
|
||||
\n\
|
||||
//Go//// Don't Go"))
|
||||
|
||||
DEFINE_DIALOG(DIALOG_172, 1, 4, 30, 200, _("\
|
||||
Mario! What's up, pal?\n\
|
||||
Ok, so, basically, I am\n\
|
||||
even smoller.\n\
|
||||
How about a race?\n\
|
||||
Ready...set...\n\
|
||||
\n\
|
||||
//Go//// Don't Go"))
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
# SM64 Crash Handler
|
||||
# See Readme below.
|
||||
|
||||
.include "macros.inc"
|
||||
|
||||
/* ---------------------------------------------------------------
|
||||
* IMPORTANT README:
|
||||
* ---------------------------------------------------------------
|
||||
* Frame buffer emulation is required. To enable it in GlideN64,
|
||||
* check "Emulate frame buffer" and "Render frame buffer to output"
|
||||
* in the "Frame buffer" tab.
|
||||
*
|
||||
* Your emulator's CPU core style should be set to interpreter for best results.
|
||||
*
|
||||
* See the DEBUG_ASSERT macro on how to call the crash screen for
|
||||
* detected exceptions.
|
||||
*
|
||||
*/
|
||||
|
||||
.set noat
|
||||
.set noreorder
|
||||
.set gp=64
|
||||
|
||||
.set COP0_CAUSE, $13
|
||||
.set COP0_EPC, $14
|
||||
.set COP0_BADVADDR, $8
|
||||
|
||||
glabel crashFont
|
||||
.incbin "enhancements/crash_font.bin"
|
||||
.align 4
|
||||
|
||||
glabel exceptionRegContext
|
||||
.fill 0x108
|
||||
|
||||
glabel pAssertFile
|
||||
.dword 0
|
||||
glabel nAssertLine
|
||||
.dword 0
|
||||
glabel pAssertExpression
|
||||
.dword 0
|
||||
glabel nAssertStopProgram
|
||||
.dword 0
|
||||
|
||||
glabel _n64_assert
|
||||
lui $at, %hi(pAssertFile)
|
||||
sw $a0, %lo(pAssertFile)($at)
|
||||
lui $at, %hi(nAssertLine)
|
||||
sw $a1, %lo(nAssertLine)($at)
|
||||
lui $at, %hi(pAssertExpression)
|
||||
sw $a2, %lo(pAssertExpression)($at)
|
||||
lui $at, %hi(nAssertStopProgram)
|
||||
sw $a3, %lo(nAssertStopProgram)($at)
|
||||
beqz $a3, .end_2
|
||||
nop
|
||||
syscall # trigger crash screen
|
||||
.end_2:
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
glabel cop0_get_cause
|
||||
jr $ra
|
||||
mfc0 $v0, COP0_CAUSE
|
||||
|
||||
glabel cop0_get_epc
|
||||
jr $ra
|
||||
mfc0 $v0, COP0_EPC
|
||||
|
||||
glabel cop0_get_badvaddr
|
||||
jr $ra
|
||||
mfc0 $v0, COP0_BADVADDR
|
||||
|
||||
# If the error code field of cop0's cause register is non-zero,
|
||||
# draw crash details to the screen and hang
|
||||
#
|
||||
# If there wasn't an error, continue to the original handler
|
||||
|
||||
glabel __crash_handler_entry
|
||||
mfc0 $k1, COP0_CAUSE
|
||||
andi $k1, $k1, (0x1F << 2)
|
||||
beqzl $k1, .end2 # exit if ExCode is 0
|
||||
lui $k0, %hi(__osException)
|
||||
la $k0, exceptionRegContext
|
||||
sd $zero, 0x018 ($k0)
|
||||
sd $at, 0x020 ($k0)
|
||||
sd $v0, 0x028 ($k0)
|
||||
sd $v1, 0x030 ($k0)
|
||||
sd $a0, 0x038 ($k0)
|
||||
sd $a1, 0x040 ($k0)
|
||||
sd $a2, 0x048 ($k0)
|
||||
sd $a3, 0x050 ($k0)
|
||||
sd $t0, 0x058 ($k0)
|
||||
sd $t1, 0x060 ($k0)
|
||||
sd $t2, 0x068 ($k0)
|
||||
sd $t3, 0x070 ($k0)
|
||||
sd $t4, 0x078 ($k0)
|
||||
sd $t5, 0x080 ($k0)
|
||||
sd $t6, 0x088 ($k0)
|
||||
sd $t7, 0x090 ($k0)
|
||||
sd $s0, 0x098 ($k0)
|
||||
sd $s1, 0x0A0 ($k0)
|
||||
sd $s2, 0x0A8 ($k0)
|
||||
sd $s3, 0x0B0 ($k0)
|
||||
sd $s4, 0x0B8 ($k0)
|
||||
sd $s5, 0x0C0 ($k0)
|
||||
sd $s6, 0x0C8 ($k0)
|
||||
sd $s7, 0x0D0 ($k0)
|
||||
sd $t8, 0x0D8 ($k0)
|
||||
sd $t9, 0x0E0 ($k0)
|
||||
sd $gp, 0x0E8 ($k0)
|
||||
sd $sp, 0x0F0 ($k0)
|
||||
sd $fp, 0x0F8 ($k0)
|
||||
sd $ra, 0x100 ($k0)
|
||||
# cop unusable exception fired twice on startup so we'll ignore it for now
|
||||
li $t0, (0x0B << 2)
|
||||
beq $k1, $t0, .end
|
||||
nop
|
||||
jal show_crash_screen_and_hang
|
||||
nop
|
||||
.end:
|
||||
ld $at, 0x020 ($k0)
|
||||
ld $v0, 0x028 ($k0)
|
||||
ld $v1, 0x030 ($k0)
|
||||
ld $a0, 0x038 ($k0)
|
||||
ld $a1, 0x040 ($k0)
|
||||
ld $a2, 0x048 ($k0)
|
||||
ld $a3, 0x050 ($k0)
|
||||
ld $t0, 0x058 ($k0)
|
||||
ld $t1, 0x060 ($k0)
|
||||
ld $t2, 0x068 ($k0)
|
||||
ld $t3, 0x070 ($k0)
|
||||
ld $t4, 0x078 ($k0)
|
||||
ld $t5, 0x080 ($k0)
|
||||
ld $t6, 0x088 ($k0)
|
||||
ld $t7, 0x090 ($k0)
|
||||
ld $s0, 0x098 ($k0)
|
||||
ld $s1, 0x0A0 ($k0)
|
||||
ld $s2, 0x0A8 ($k0)
|
||||
ld $s3, 0x0B0 ($k0)
|
||||
ld $s4, 0x0B8 ($k0)
|
||||
ld $s5, 0x0C0 ($k0)
|
||||
ld $s6, 0x0C8 ($k0)
|
||||
ld $s7, 0x0D0 ($k0)
|
||||
ld $t8, 0x0D8 ($k0)
|
||||
ld $t9, 0x0E0 ($k0)
|
||||
ld $gp, 0x0E8 ($k0)
|
||||
ld $sp, 0x0F0 ($k0)
|
||||
ld $fp, 0x0F8 ($k0)
|
||||
ld $ra, 0x100 ($k0)
|
||||
lui $k0, %hi(__osException)
|
||||
.end2:
|
||||
addiu $k0, $k0, %lo(__osException)
|
||||
jr $k0 # run the original handler
|
||||
nop
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
/* SM64 Crash Handler */
|
||||
|
||||
#include <sm64.h>
|
||||
|
||||
#include "crash.h"
|
||||
|
||||
extern u32 exceptionRegContext[];
|
||||
|
||||
extern char *pAssertFile;
|
||||
extern int nAssertLine;
|
||||
extern char *pAssertExpression;
|
||||
extern int nAssertStopProgram;
|
||||
|
||||
u16 fbFillColor = 0xFFFF;
|
||||
u16 fbShadeColor = 0x0000;
|
||||
u16 *fbAddress = NULL;
|
||||
|
||||
extern u8 crashFont[];
|
||||
|
||||
const char *szErrCodes[] = {
|
||||
"INTERRUPT",
|
||||
"TLB MOD",
|
||||
"UNMAPPED LOAD ADDR",
|
||||
"UNMAPPED STORE ADDR",
|
||||
"BAD LOAD ADDR",
|
||||
"BAD STORE ADDR",
|
||||
"BUS ERR ON INSTR FETCH",
|
||||
"BUS ERR ON LOADSTORE",
|
||||
"SYSCALL",
|
||||
"BREAKPOINT",
|
||||
"UNKNOWN INSTR",
|
||||
"COP UNUSABLE",
|
||||
"ARITHMETIC OVERFLOW",
|
||||
"TRAP EXC",
|
||||
"VIRTUAL COHERENCY INSTR",
|
||||
"FLOAT EXC",
|
||||
};
|
||||
|
||||
const char *szGPRegisters1[] = { "R0", "AT", "V0", "V1", "A0", "A1", "A2", "A3",
|
||||
"T0", "T1", "T2", "T3", "T4", "T5", "T6", NULL };
|
||||
|
||||
const char *szGPRegisters2[] = { "T7", "S0", "S1", "S2", "S3", "S4",
|
||||
"S5", "S6", "S7", "T8", "T9", /*"K0", "K1",*/
|
||||
"GP", "SP", "FP", "RA", NULL };
|
||||
|
||||
int crash_strlen(char *str) {
|
||||
int len = 0;
|
||||
while (*str++) {
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void show_crash_screen_and_hang(void) {
|
||||
u32 cause;
|
||||
u32 epc;
|
||||
u8 errno;
|
||||
|
||||
fb_set_address((void *) (*(u32 *) 0xA4400004 | 0x80000000)); // replace me
|
||||
|
||||
cause = cop0_get_cause();
|
||||
epc = cop0_get_epc();
|
||||
|
||||
errno = (cause >> 2) & 0x1F;
|
||||
|
||||
if (nAssertStopProgram == 0) {
|
||||
fbFillColor = 0x6253;
|
||||
fb_fill(10, 10, 300, 220);
|
||||
|
||||
fb_print_str(80, 20, "AN ERROR HAS OCCURRED!");
|
||||
fb_print_int_hex(80, 30, errno, 8);
|
||||
fb_print_str(95, 30, szErrCodes[errno]);
|
||||
|
||||
if (errno >= 2 && errno <= 5) {
|
||||
/*
|
||||
2 UNMAPPED LOAD ADDR
|
||||
3 UNMAPPED STORE ADDR
|
||||
4 BAD LOAD ADDR
|
||||
5 BAD STORE ADDR
|
||||
*/
|
||||
u32 badvaddr = cop0_get_badvaddr();
|
||||
|
||||
fb_print_str(145, 50, "VA");
|
||||
fb_print_int_hex(160, 50, badvaddr, 32);
|
||||
}
|
||||
} else {
|
||||
int afterFileX;
|
||||
int exprBoxWidth;
|
||||
fbFillColor = 0x5263;
|
||||
fb_fill(10, 10, 300, 220);
|
||||
|
||||
fb_print_str(80, 20, "ASSERTION FAILED!");
|
||||
|
||||
afterFileX = fb_print_str(80, 30, pAssertFile);
|
||||
fb_print_str(afterFileX, 30, ":");
|
||||
fb_print_uint(afterFileX + 5, 30, nAssertLine);
|
||||
|
||||
exprBoxWidth = (crash_strlen(pAssertExpression) * 5) + 2;
|
||||
fbFillColor = 0x0001;
|
||||
fb_fill(80 - 1, 40 - 1, exprBoxWidth, 10);
|
||||
fb_print_str(80, 40, pAssertExpression);
|
||||
}
|
||||
|
||||
fb_print_str(80, 50, "PC");
|
||||
fb_print_int_hex(95, 50, epc, 32);
|
||||
|
||||
fb_print_gpr_states(80, 70, szGPRegisters1, &exceptionRegContext[6 + 0]);
|
||||
fb_print_gpr_states(145, 70, szGPRegisters2, &exceptionRegContext[6 + 15 * 2]);
|
||||
|
||||
fb_swap();
|
||||
osWritebackDCacheAll();
|
||||
|
||||
while (1) // hang forever
|
||||
{
|
||||
UNUSED volatile int t = 0; // keep pj64 happy
|
||||
}
|
||||
}
|
||||
|
||||
u8 ascii_to_idx(char c) {
|
||||
return c - 0x20;
|
||||
}
|
||||
|
||||
void fb_set_address(void *address) {
|
||||
fbAddress = (u16 *) address;
|
||||
}
|
||||
|
||||
void fb_swap() {
|
||||
// update VI frame buffer register
|
||||
// todo other registers
|
||||
*(u32 *) (0xA4400004) = (u32) fbAddress & 0x00FFFFFF;
|
||||
}
|
||||
|
||||
void fb_fill(int baseX, int baseY, int width, int height) {
|
||||
int y, x;
|
||||
|
||||
for (y = baseY; y < baseY + height; y++) {
|
||||
for (x = baseX; x < baseX + width; x++) {
|
||||
fbAddress[y * 320 + x] = fbFillColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fb_draw_char(int x, int y, u8 idx) {
|
||||
u16 *out = &fbAddress[y * 320 + x];
|
||||
const u8 *in = &crashFont[idx * 3];
|
||||
int nbyte;
|
||||
int nrow;
|
||||
int ncol;
|
||||
|
||||
for (nbyte = 0; nbyte < 3; nbyte++) {
|
||||
u8 curbyte = in[nbyte];
|
||||
for (nrow = 0; nrow < 2; nrow++) {
|
||||
for (ncol = 0; ncol < 4; ncol++) {
|
||||
u8 px = curbyte & (1 << (7 - (nrow * 4 + ncol)));
|
||||
if (px != 0) {
|
||||
out[ncol] = fbFillColor;
|
||||
}
|
||||
}
|
||||
out += 320;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fb_draw_char_shaded(int x, int y, u8 idx) {
|
||||
fbFillColor = 0x0001;
|
||||
fb_draw_char(x - 1, y + 1, idx);
|
||||
|
||||
fbFillColor = 0xFFFF;
|
||||
fb_draw_char(x, y, idx);
|
||||
}
|
||||
|
||||
int fb_print_str(int x, int y, const char *str) {
|
||||
while (1) {
|
||||
int yoffs = 0;
|
||||
u8 idx;
|
||||
char c = *str++;
|
||||
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == ' ') {
|
||||
x += 5;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 'j':
|
||||
case 'g':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'y':
|
||||
case 'Q':
|
||||
yoffs = 1;
|
||||
break;
|
||||
case ',':
|
||||
yoffs = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
idx = ascii_to_idx(c);
|
||||
fb_draw_char_shaded(x, y + yoffs, idx);
|
||||
x += 5;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
void fb_print_int_hex(int x, int y, u32 value, int nbits) {
|
||||
nbits -= 4;
|
||||
|
||||
while (nbits >= 0) {
|
||||
int nib = ((value >> nbits) & 0xF);
|
||||
u8 idx;
|
||||
|
||||
if (nib > 9) {
|
||||
idx = ('A' - 0x20) + (nib - 0xa);
|
||||
} else {
|
||||
idx = ('0' - 0x20) + nib;
|
||||
}
|
||||
|
||||
fb_draw_char_shaded(x, y, idx);
|
||||
x += 5;
|
||||
|
||||
nbits -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
int fb_print_uint(int x, int y, u32 value) {
|
||||
int nchars = 0;
|
||||
|
||||
int v = value;
|
||||
int i;
|
||||
while (v /= 10) {
|
||||
nchars++;
|
||||
}
|
||||
|
||||
x += nchars * 5;
|
||||
|
||||
for (i = nchars; i >= 0; i--) {
|
||||
fb_draw_char_shaded(x, y, ('0' - 0x20) + (value % 10));
|
||||
value /= 10;
|
||||
x -= 5;
|
||||
}
|
||||
|
||||
return (x + nchars * 5);
|
||||
}
|
||||
|
||||
void fb_print_gpr_states(int x, int y, const char *regNames[], u32 *regContext) {
|
||||
int i;
|
||||
for (i = 0;; i++) {
|
||||
if (regNames[i] == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
fb_print_str(x, y, regNames[i]);
|
||||
fb_print_int_hex(x + 15, y, regContext[i * 2 + 1], 32);
|
||||
y += 10;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef _CRASH_H_
|
||||
#define _CRASH_H_
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define CRASH_SCREEN_INCLUDED 1
|
||||
|
||||
extern u32 cop0_get_cause(void);
|
||||
extern u32 cop0_get_epc(void);
|
||||
extern u32 cop0_get_badvaddr(void);
|
||||
|
||||
extern void _n64_assert(const char* pFile, int nLine, const char *pExpression, int nStopProgram);
|
||||
|
||||
extern u8 __crash_handler_entry[];
|
||||
|
||||
void show_crash_screen_and_hang(void);
|
||||
u8 ascii_to_idx(char c);
|
||||
void fb_set_address(void *address);
|
||||
void fb_swap(void);
|
||||
void fb_fill(int baseX, int baseY, int width, int height);
|
||||
void fb_draw_char(int x, int y, u8 idx);
|
||||
void fb_draw_char_shaded(int x, int y, u8 idx);
|
||||
int fb_print_str(int x, int y, const char *str);
|
||||
int fb_print_uint(int x, int y, u32 value);
|
||||
void fb_print_int_hex(int x, int y, u32 value, int nbits);
|
||||
void fb_print_gpr_states(int x, int y, const char* regStrs[], u32 *regContext);
|
||||
|
||||
#endif /* _CRASH_H_ */
|
||||
Loading…
Reference in New Issue