mirror of https://github.com/sm64pc/sm64pc.git
Merge branch 'master' into cmake
This commit is contained in:
commit
8bc5854b6e
|
@ -7,6 +7,10 @@
|
|||
*.ilk
|
||||
*.exp
|
||||
|
||||
# Patch and wiggle related residdue
|
||||
*.rej
|
||||
*.porig
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
|
14
Dockerfile
14
Dockerfile
|
@ -5,11 +5,14 @@ RUN apt-get update && \
|
|||
binutils-mips-linux-gnu \
|
||||
bsdmainutils \
|
||||
build-essential \
|
||||
git \
|
||||
libaudiofile-dev \
|
||||
libsdl2-dev \
|
||||
pkg-config \
|
||||
python3 \
|
||||
wget \
|
||||
zlib1g-dev
|
||||
zlib1g-dev && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN wget \
|
||||
https://github.com/n64decomp/qemu-irix/releases/download/v2.11-deb/qemu-irix-2.11.0-2169-g32ab296eef_amd64.deb \
|
||||
|
@ -18,9 +21,16 @@ RUN wget \
|
|||
dpkg -i qemu.deb && \
|
||||
rm qemu.deb
|
||||
|
||||
RUN cd /tmp && \
|
||||
git clone https://github.com/emscripten-core/emsdk.git && \
|
||||
cd emsdk && \
|
||||
./emsdk install latest && \
|
||||
cd .. && \
|
||||
rm -rf emsdk
|
||||
|
||||
RUN mkdir /sm64
|
||||
WORKDIR /sm64
|
||||
ENV PATH="/sm64/tools:${PATH}"
|
||||
ENV PATH="/sm64/tools:/emsdk:${PATH}"
|
||||
|
||||
CMD echo 'usage: docker run --rm --mount type=bind,source="$(pwd)",destination=/sm64 sm64 make VERSION=${VERSION:-us} -j4\n' \
|
||||
'see https://github.com/n64decomp/sm64/blob/master/README.md for advanced usage'
|
||||
|
|
321
Makefile
321
Makefile
|
@ -16,17 +16,18 @@ GRUCODE ?= f3d_old
|
|||
# If COMPARE is 1, check the output sha1sum when building 'all'
|
||||
COMPARE ?= 1
|
||||
# If NON_MATCHING is 1, define the NON_MATCHING and AVOID_UB macros when building (recommended)
|
||||
NON_MATCHING ?= 0
|
||||
# Build for the N64 (turn this off for ports)
|
||||
TARGET_N64 ?= 0
|
||||
NON_MATCHING ?= 1
|
||||
# Sane default until N64 build scripts rm'd
|
||||
TARGET_N64 = 0
|
||||
|
||||
# Build and optimize for Raspberry Pi(s)
|
||||
TARGET_RPI ?= 0
|
||||
# Compiler to use (ido or gcc)
|
||||
COMPILER ?= ido
|
||||
|
||||
ifeq ($(COMPILER),gcc)
|
||||
NON_MATCHING := 1
|
||||
endif
|
||||
# Enable better camera by default
|
||||
BETTERCAMERA ?= 1
|
||||
|
||||
# Build for Emscripten/WebGL
|
||||
TARGET_WEB ?= 0
|
||||
# Specify the target you are building for, 0 means native
|
||||
|
@ -39,18 +40,20 @@ else
|
|||
BITS :=
|
||||
endif
|
||||
|
||||
# Automatic settings only for ports
|
||||
ifeq ($(TARGET_N64),0)
|
||||
NON_MATCHING := 1
|
||||
GRUCODE := f3dex2e
|
||||
WINDOWS_BUILD := 0
|
||||
ifeq ($(TARGET_WEB),0)
|
||||
ifeq ($(OS),Windows_NT)
|
||||
WINDOWS_BUILD := 1
|
||||
endif
|
||||
endif
|
||||
# Automatic settings for PC port(s)
|
||||
# WINDOWS_BUILD IS NOT FOR COMPILING A WINDOWS EXECUTABLE UNDER LINUX!
|
||||
|
||||
# Release
|
||||
NON_MATCHING := 1
|
||||
GRUCODE := f3dex2e
|
||||
WINDOWS_BUILD := 0
|
||||
|
||||
ifeq ($(TARGET_WEB),0)
|
||||
ifeq ($(OS),Windows_NT)
|
||||
WINDOWS_BUILD := 1
|
||||
endif
|
||||
endif
|
||||
|
||||
# Release (version) flag defs
|
||||
|
||||
ifeq ($(VERSION),jp)
|
||||
VERSION_CFLAGS := -DVERSION_JP
|
||||
|
@ -103,7 +106,7 @@ ifeq ($(GRUCODE), f3dex2) # Fast3DEX2
|
|||
TARGET := $(TARGET).f3dex2
|
||||
COMPARE := 0
|
||||
else
|
||||
ifeq ($(GRUCODE), f3dex2e) # Fast3DEX2 Extended (for PC)
|
||||
ifeq ($(GRUCODE), f3dex2e) # Fast3DEX2 Extended (PC default)
|
||||
GRUCODE_CFLAGS := -DF3DEX_GBI_2E
|
||||
TARGET := $(TARGET).f3dex2e
|
||||
COMPARE := 0
|
||||
|
@ -126,18 +129,15 @@ endif
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_N64),0)
|
||||
NON_MATCHING := 1
|
||||
# Default build is for PC now
|
||||
VERSION_CFLAGS := $(VERSION_CFLAGS) -DNON_MATCHING -DAVOID_UB
|
||||
|
||||
ifeq ($(TARGET_RPI),1) # Define RPi to change SDL2 title & GLES2 hints
|
||||
VERSION_CFLAGS += -DUSE_GLES
|
||||
endif
|
||||
|
||||
ifeq ($(NON_MATCHING),1)
|
||||
VERSION_CFLAGS := $(VERSION_CFLAGS) -DNON_MATCHING -DAVOID_UB
|
||||
ifeq ($(TARGET_RPI),1) # Define RPi to change SDL2 title & GLES2 hints
|
||||
VERSION_CFLAGS += -DTARGET_RPI
|
||||
endif
|
||||
VERSION_ASFLAGS := --defsym AVOID_UB=1
|
||||
COMPARE := 0
|
||||
endif
|
||||
VERSION_ASFLAGS := --defsym AVOID_UB=1
|
||||
COMPARE := 0
|
||||
|
||||
ifeq ($(TARGET_WEB),1)
|
||||
VERSION_CFLAGS := $(VERSION_CFLAGS) -DTARGET_WEB
|
||||
|
@ -174,34 +174,30 @@ endif
|
|||
|
||||
# BUILD_DIR is location where all build artifacts are placed
|
||||
BUILD_DIR_BASE := build
|
||||
ifeq ($(TARGET_N64),1)
|
||||
BUILD_DIR := $(BUILD_DIR_BASE)/$(VERSION)
|
||||
else
|
||||
|
||||
ifeq ($(TARGET_WEB),1)
|
||||
BUILD_DIR := $(BUILD_DIR_BASE)/$(VERSION)_web
|
||||
else
|
||||
BUILD_DIR := $(BUILD_DIR_BASE)/$(VERSION)_pc
|
||||
endif
|
||||
endif
|
||||
|
||||
LIBULTRA := $(BUILD_DIR)/libultra.a
|
||||
|
||||
ifeq ($(TARGET_WEB),1)
|
||||
EXE := $(BUILD_DIR)/$(TARGET).html
|
||||
else
|
||||
ifeq ($(WINDOWS_BUILD),1)
|
||||
EXE := $(BUILD_DIR)/$(TARGET).exe
|
||||
else
|
||||
ifeq ($(WINDOWS_BUILD),1)
|
||||
EXE := $(BUILD_DIR)/$(TARGET).exe
|
||||
|
||||
else #Linux builds here
|
||||
ifeq ($(TARGET_RPI),1)
|
||||
EXE := $(BUILD_DIR)/$(TARGET).arm
|
||||
else
|
||||
EXE := $(BUILD_DIR)/$(TARGET)
|
||||
endif
|
||||
else # Linux builds/binary namer
|
||||
ifeq ($(TARGET_RPI),1)
|
||||
EXE := $(BUILD_DIR)/$(TARGET).arm
|
||||
else
|
||||
EXE := $(BUILD_DIR)/$(TARGET)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ROM := $(BUILD_DIR)/$(TARGET).z64
|
||||
ELF := $(BUILD_DIR)/$(TARGET).elf
|
||||
LD_SCRIPT := sm64.ld
|
||||
MIO0_DIR := $(BUILD_DIR)/bin
|
||||
|
@ -211,14 +207,11 @@ ACTOR_DIR := actors
|
|||
LEVEL_DIRS := $(patsubst levels/%,%,$(dir $(wildcard levels/*/header.h)))
|
||||
|
||||
# Directories containing source files
|
||||
SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels bin data assets
|
||||
ASM_DIRS := lib
|
||||
ifeq ($(TARGET_N64),1)
|
||||
ASM_DIRS := asm $(ASM_DIRS)
|
||||
else
|
||||
SRC_DIRS := $(SRC_DIRS) src/pc src/pc/gfx src/pc/audio src/pc/controller
|
||||
ASM_DIRS :=
|
||||
endif
|
||||
|
||||
# Hi, I'm a PC
|
||||
SRC_DIRS := src src/engine src/game src/audio src/menu src/buffers actors levels bin data assets src/pc src/pc/gfx src/pc/audio src/pc/controller
|
||||
ASM_DIRS :=
|
||||
|
||||
BIN_DIRS := bin bin/$(VERSION)
|
||||
|
||||
ULTRA_SRC_DIRS := lib/src lib/src/math
|
||||
|
@ -244,28 +237,26 @@ else
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_N64),0)
|
||||
OPT_FLAGS += $(BITS)
|
||||
endif
|
||||
# Set BITS (32/64) to compile for
|
||||
OPT_FLAGS += $(BITS)
|
||||
|
||||
ifeq ($(TARGET_WEB),1)
|
||||
OPT_FLAGS := -O2 -g4 --source-map-base http://localhost:8080/
|
||||
endif
|
||||
endif
|
||||
|
||||
# Use a default opt flag for gcc
|
||||
# Use a default opt flag for gcc, then override if RPi
|
||||
ifeq ($(COMPILER),gcc)
|
||||
OPT_FLAGS := -O2
|
||||
OPT_FLAGS := -O2 # Breaks sound on x86?
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_RPI),1)
|
||||
machine = $(shell sh -c 'uname -m 2>/dev/null || echo unknown')
|
||||
machine = $(shell sh -c 'uname -m 2>/dev/null || echo unknown')
|
||||
# Raspberry Pi B+, Zero, etc
|
||||
ifneq (,$(findstring armv6l,$(machine)))
|
||||
ifneq (,$(findstring armv6l,$(machine)))
|
||||
OPT_FLAGS := -march=armv6zk+fp -mfpu=vfp -Ofast
|
||||
endif
|
||||
|
||||
# Raspberry Pi 2 and 3
|
||||
# Raspberry Pi 2 and 3 in ARM 32bit mode
|
||||
ifneq (,$(findstring armv7l,$(machine)))
|
||||
model = $(shell sh -c 'cat /sys/firmware/devicetree/base/model 2>/dev/null || echo unknown')
|
||||
|
||||
|
@ -276,9 +267,16 @@ ifeq ($(TARGET_RPI),1)
|
|||
endif
|
||||
endif
|
||||
|
||||
# RPi4 / ARM A64 NEEDS TESTING 32BIT.
|
||||
# RPi3 or RPi4, in ARM64 (aarch64) mode. NEEDS TESTING 32BIT.
|
||||
# DO NOT pass -mfpu stuff here, thats for 32bit ARM only and will fail for 64bit ARM.
|
||||
ifneq (,$(findstring aarch64,$(machine)))
|
||||
OPT_FLAGS := -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -O3
|
||||
model = $(shell sh -c 'cat /sys/firmware/devicetree/base/model 2>/dev/null || echo unknown')
|
||||
ifneq (,$(findstring 3,$(model)))
|
||||
OPT_FLAGS := -march=armv8-a+crc -mtune=cortex-a53 -O3
|
||||
else ifneq (,$(findstring 4,$(model)))
|
||||
OPT_FLAGS := -march=armv8-a+crc+simd -mtune=cortex-a72 -O3
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -292,9 +290,7 @@ CXX_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp))
|
|||
S_FILES := $(foreach dir,$(ASM_DIRS),$(wildcard $(dir)/*.s))
|
||||
ULTRA_C_FILES := $(foreach dir,$(ULTRA_SRC_DIRS),$(wildcard $(dir)/*.c))
|
||||
GODDARD_C_FILES := $(foreach dir,$(GODDARD_SRC_DIRS),$(wildcard $(dir)/*.c))
|
||||
ifeq ($(TARGET_N64),1)
|
||||
ULTRA_S_FILES := $(foreach dir,$(ULTRA_ASM_DIRS),$(wildcard $(dir)/*.s))
|
||||
endif
|
||||
|
||||
GENERATED_C_FILES := $(BUILD_DIR)/assets/mario_anim_data.c $(BUILD_DIR)/assets/demo_data.c \
|
||||
$(addprefix $(BUILD_DIR)/bin/,$(addsuffix _skybox.c,$(notdir $(basename $(wildcard textures/skyboxes/*.png)))))
|
||||
|
||||
|
@ -302,7 +298,9 @@ ifeq ($(WINDOWS_BUILD),0)
|
|||
CXX_FILES :=
|
||||
endif
|
||||
|
||||
ifneq ($(TARGET_N64),1)
|
||||
# We need to keep this for now
|
||||
# If we're not N64 use below
|
||||
|
||||
ULTRA_C_FILES_SKIP := \
|
||||
sqrtf.c \
|
||||
string.c \
|
||||
|
@ -361,7 +359,8 @@ ifneq ($(TARGET_N64),1)
|
|||
|
||||
C_FILES := $(filter-out src/game/main.c,$(C_FILES))
|
||||
ULTRA_C_FILES := $(filter-out $(addprefix lib/src/,$(ULTRA_C_FILES_SKIP)),$(ULTRA_C_FILES))
|
||||
endif
|
||||
|
||||
# "If we're not N64, use the above"
|
||||
|
||||
ifeq ($(VERSION),sh)
|
||||
SOUND_BANK_FILES := $(wildcard sound/sound_banks/*.json)
|
||||
|
@ -386,7 +385,6 @@ SOUND_OBJ_FILES := $(SOUND_BIN_DIR)/sound_data.ctl.o \
|
|||
$(SOUND_BIN_DIR)/sequences.bin.o \
|
||||
$(SOUND_BIN_DIR)/bank_sets.o
|
||||
|
||||
|
||||
# Object files
|
||||
O_FILES := $(foreach file,$(C_FILES),$(BUILD_DIR)/$(file:.c=.o)) \
|
||||
$(foreach file,$(CXX_FILES),$(BUILD_DIR)/$(file:.cpp=.o)) \
|
||||
|
@ -401,13 +399,6 @@ GODDARD_O_FILES := $(foreach file,$(GODDARD_C_FILES),$(BUILD_DIR)/$(file:.c=.o))
|
|||
# Automatic dependency files
|
||||
DEP_FILES := $(O_FILES:.o=.d) $(ULTRA_O_FILES:.o=.d) $(GODDARD_O_FILES:.o=.d) $(BUILD_DIR)/$(LD_SCRIPT).d
|
||||
|
||||
# Files with GLOBAL_ASM blocks
|
||||
ifneq ($(NON_MATCHING),1)
|
||||
GLOBAL_ASM_C_FILES != grep -rl 'GLOBAL_ASM(' $(wildcard src/**/*.c)
|
||||
GLOBAL_ASM_O_FILES = $(foreach file,$(GLOBAL_ASM_C_FILES),$(BUILD_DIR)/$(file:.c=.o))
|
||||
GLOBAL_ASM_DEP = $(BUILD_DIR)/src/audio/non_matching_dep
|
||||
endif
|
||||
|
||||
# Segment elf files
|
||||
SEG_FILES := $(SEGMENT_ELF_FILES) $(ACTOR_ELF_FILES) $(LEVEL_ELF_FILES)
|
||||
|
||||
|
@ -415,82 +406,23 @@ SEG_FILES := $(SEGMENT_ELF_FILES) $(ACTOR_ELF_FILES) $(LEVEL_ELF_FILES)
|
|||
INCLUDE_CFLAGS := -I include -I $(BUILD_DIR) -I $(BUILD_DIR)/include -I src -I .
|
||||
ENDIAN_BITWIDTH := $(BUILD_DIR)/endian-and-bitwidth
|
||||
|
||||
ifeq ($(TARGET_N64),1)
|
||||
IRIX_ROOT := tools/ido5.3_compiler
|
||||
|
||||
ifeq ($(shell type mips-linux-gnu-ld >/dev/null 2>/dev/null; echo $$?), 0)
|
||||
CROSS := mips-linux-gnu-
|
||||
else ifeq ($(shell type mips64-linux-gnu-ld >/dev/null 2>/dev/null; echo $$?), 0)
|
||||
CROSS := mips64-linux-gnu-
|
||||
else ifeq ($(shell type mips64-elf-ld >/dev/null 2>/dev/null; echo $$?), 0)
|
||||
CROSS := mips64-elf-
|
||||
endif
|
||||
|
||||
# check that either QEMU_IRIX is set or qemu-irix package installed
|
||||
ifndef QEMU_IRIX
|
||||
QEMU_IRIX := $(shell which qemu-irix)
|
||||
ifeq (, $(QEMU_IRIX))
|
||||
$(error Please install qemu-irix package or set QEMU_IRIX env var to the full qemu-irix binary path)
|
||||
endif
|
||||
endif
|
||||
|
||||
AS := $(CROSS)as
|
||||
CC := $(QEMU_IRIX) -silent -L $(IRIX_ROOT) $(IRIX_ROOT)/usr/bin/cc
|
||||
CPP := cpp -P -Wno-trigraphs
|
||||
LD := $(CROSS)ld
|
||||
AR := $(CROSS)ar
|
||||
OBJDUMP := $(CROSS)objdump
|
||||
OBJCOPY := $(CROSS)objcopy
|
||||
PYTHON := python3
|
||||
|
||||
# change the compiler to gcc, to use the default, install the gcc-mips-linux-gnu package
|
||||
ifeq ($(COMPILER),gcc)
|
||||
CC := $(CROSS)gcc
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_N64),1)
|
||||
TARGET_CFLAGS := -nostdinc -I include/libc -DTARGET_N64
|
||||
CC_CFLAGS := -fno-builtin
|
||||
endif
|
||||
|
||||
# Check code syntax with host compiler
|
||||
CC_CHECK := gcc -fsyntax-only -fsigned-char $(CC_CFLAGS) $(TARGET_CFLAGS) $(INCLUDE_CFLAGS) -std=gnu90 -Wall -Wextra -Wno-format-security -Wno-main -DNON_MATCHING -DAVOID_UB $(VERSION_CFLAGS) $(GRUCODE_CFLAGS)
|
||||
|
||||
COMMON_CFLAGS = $(OPT_FLAGS) $(TARGET_CFLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(MIPSISET) $(GRUCODE_CFLAGS)
|
||||
|
||||
ASFLAGS := -march=vr4300 -mabi=32 -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS) $(GRUCODE_ASFLAGS)
|
||||
CFLAGS = -Wab,-r4300_mul -non_shared -G 0 -Xcpluscomm -Xfullwarn -signed $(COMMON_CFLAGS) $(MIPSBIT)
|
||||
OBJCOPYFLAGS := --pad-to=0x800000 --gap-fill=0xFF
|
||||
SYMBOL_LINKING_FLAGS := $(addprefix -R ,$(SEG_FILES))
|
||||
LDFLAGS := -T undefined_syms.txt -T $(BUILD_DIR)/$(LD_SCRIPT) -Map $(BUILD_DIR)/sm64.$(VERSION).map --no-check-sections $(SYMBOL_LINKING_FLAGS)
|
||||
ENDIAN_BITWIDTH := $(BUILD_DIR)/endian-and-bitwidth
|
||||
|
||||
ifeq ($(COMPILER),gcc)
|
||||
CFLAGS := -march=vr4300 -mfix4300 -mno-shared -G 0 -mhard-float -fno-stack-protector -fno-common -I include -I src/ -I $(BUILD_DIR)/include -fno-PIC -mno-abicalls -fno-strict-aliasing -fno-inline-functions -ffreestanding -fwrapv -Wall -Wextra $(COMMON_CFLAGS)
|
||||
endif
|
||||
|
||||
ifeq ($(shell getconf LONG_BIT), 32)
|
||||
# Work around memory allocation bug in QEMU
|
||||
export QEMU_GUEST_BASE := 1
|
||||
else
|
||||
# Ensure that gcc treats the code as 32-bit
|
||||
CC_CHECK += $(BITS)
|
||||
endif
|
||||
|
||||
else # TARGET_N64
|
||||
# Huge deleted N64 section was here
|
||||
|
||||
AS := as
|
||||
ifneq ($(TARGET_WEB),1)
|
||||
|
||||
ifneq ($(TARGET_WEB),1) # As in, not-web PC port
|
||||
CC := $(CROSS)gcc
|
||||
CXX := $(CROSS)g++
|
||||
else
|
||||
CC := emcc
|
||||
endif
|
||||
|
||||
ifeq ($(WINDOWS_BUILD),1)
|
||||
LD := $(CXX)
|
||||
else
|
||||
LD := $(CC)
|
||||
endif
|
||||
|
||||
CPP := cpp -P
|
||||
OBJDUMP := objdump
|
||||
OBJCOPY := objcopy
|
||||
|
@ -499,23 +431,33 @@ PYTHON := python3
|
|||
ifeq ($(WINDOWS_BUILD),1)
|
||||
CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) `$(CROSS)sdl2-config --cflags`
|
||||
CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(CROSS)sdl2-config --cflags`
|
||||
|
||||
else ifeq ($(TARGET_WEB),1)
|
||||
CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -s USE_SDL=2
|
||||
CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv -s USE_SDL=2
|
||||
|
||||
# Linux / Other builds below
|
||||
else
|
||||
CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -Wno-format-security $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) `$(CROSS)sdl2-config --cflags`
|
||||
CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(CROSS)sdl2-config --cflags`
|
||||
endif
|
||||
|
||||
# Check for better camera option
|
||||
ifeq ($(BETTERCAMERA),1)
|
||||
CC_CHECK += -DBETTERCAMERA
|
||||
CFLAGS += -DBETTERCAMERA
|
||||
endif
|
||||
|
||||
ASFLAGS := -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS)
|
||||
|
||||
ifeq ($(TARGET_WEB),1)
|
||||
LDFLAGS := -lm -lGL -lSDL2 -no-pie -s TOTAL_MEMORY=20MB -g4 --source-map-base http://localhost:8080/ -s "EXTRA_EXPORTED_RUNTIME_METHODS=['callMain']"
|
||||
else
|
||||
|
||||
ifeq ($(WINDOWS_BUILD),1)
|
||||
LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(CROSS)sdl2-config --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -no-pie -static
|
||||
else
|
||||
|
||||
# Linux / Other builds below
|
||||
ifeq ($(TARGET_RPI),1)
|
||||
LDFLAGS := $(OPT_FLAGS) -lm -lGLESv2 `$(CROSS)sdl2-config --libs` -no-pie
|
||||
|
@ -525,14 +467,13 @@ endif
|
|||
endif
|
||||
endif #Added for Pi ifeq
|
||||
|
||||
endif
|
||||
|
||||
# Prevent a crash with -sopt
|
||||
export LANG := C
|
||||
|
||||
####################### Other Tools #########################
|
||||
|
||||
# N64 tools
|
||||
# N64 conversion tools
|
||||
TOOLS_DIR = tools
|
||||
MIO0TOOL = $(TOOLS_DIR)/mio0
|
||||
N64CKSUM = $(TOOLS_DIR)/n64cksum
|
||||
|
@ -550,32 +491,13 @@ LOADER = loader64
|
|||
LOADER_FLAGS = -vwf
|
||||
SHA1SUM = sha1sum
|
||||
|
||||
# Use Objcopy instead of extract_data_for_mio
|
||||
ifeq ($(COMPILER),gcc)
|
||||
EXTRACT_DATA_FOR_MIO := $(OBJCOPY) -O binary --only-section=.data
|
||||
endif
|
||||
|
||||
###################### Dependency Check #####################
|
||||
|
||||
ifeq ($(TARGET_N64),1)
|
||||
BINUTILS_VER_MAJOR := $(shell $(LD) --version | grep ^GNU | sed 's/^.* //; s/\..*//g')
|
||||
BINUTILS_VER_MINOR := $(shell $(LD) --version | grep ^GNU | sed 's/^[^.]*\.//; s/\..*//g')
|
||||
BINUTILS_DEPEND := $(shell expr $(BINUTILS_VER_MAJOR) \>= 2 \& $(BINUTILS_VER_MINOR) \>= 27)
|
||||
ifeq ($(BINUTILS_DEPEND),0)
|
||||
$(error binutils version 2.27 required, version $(BINUTILS_VER_MAJOR).$(BINUTILS_VER_MINOR) detected)
|
||||
endif
|
||||
endif
|
||||
# Stubbed
|
||||
|
||||
######################## Targets #############################
|
||||
|
||||
ifeq ($(TARGET_N64),1)
|
||||
all: $(ROM)
|
||||
ifeq ($(COMPARE),1)
|
||||
@$(SHA1SUM) -c $(TARGET).sha1 || (echo 'The build succeeded, but did not match the official ROM. This is expected if you are making changes to the game.\nTo silence this message, use "make COMPARE=0"'. && false)
|
||||
endif
|
||||
else
|
||||
all: $(EXE)
|
||||
endif
|
||||
|
||||
clean:
|
||||
$(RM) -r $(BUILD_DIR_BASE)
|
||||
|
@ -600,16 +522,15 @@ asm/boot.s: $(BUILD_DIR)/lib/bin/ipl3_font.bin
|
|||
$(BUILD_DIR)/lib/bin/ipl3_font.bin: lib/ipl3_font.png
|
||||
$(IPLFONTUTIL) e $< $@
|
||||
|
||||
#Required so the compiler doesn't complain about this not existing.
|
||||
$(BUILD_DIR)/src/game/camera.o: $(BUILD_DIR)/include/text_strings.h
|
||||
|
||||
$(BUILD_DIR)/include/text_strings.h: include/text_strings.h.in
|
||||
$(TEXTCONV) charmap.txt $< $@
|
||||
|
||||
$(BUILD_DIR)/include/text_menu_strings.h: include/text_menu_strings.h.in
|
||||
$(TEXTCONV) charmap_menu.txt $< $@
|
||||
|
||||
ifeq ($(COMPILER),gcc)
|
||||
$(BUILD_DIR)/lib/src/math/%.o: CFLAGS += -fno-builtin
|
||||
endif
|
||||
|
||||
ifeq ($(VERSION),eu)
|
||||
TEXT_DIRS := text/de text/us text/fr
|
||||
|
||||
|
@ -635,7 +556,6 @@ $(BUILD_DIR)/bin/segment2.o: $(BUILD_DIR)/text/$(VERSION)/define_text.inc.c
|
|||
endif
|
||||
endif
|
||||
|
||||
|
||||
$(BUILD_DIR)/text/%/define_courses.inc.c: text/define_courses.inc.c text/%/courses.h
|
||||
$(CPP) $(VERSION_CFLAGS) $< -o $@ -I text/$*/
|
||||
$(TEXTCONV) charmap.txt $@ $@
|
||||
|
@ -650,6 +570,7 @@ ALL_DIRS := $(BUILD_DIR) $(addprefix $(BUILD_DIR)/,$(SRC_DIRS) $(ASM_DIRS) $(GOD
|
|||
DUMMY != mkdir -p $(ALL_DIRS)
|
||||
|
||||
$(BUILD_DIR)/include/text_strings.h: $(BUILD_DIR)/include/text_menu_strings.h
|
||||
|
||||
ifeq ($(VERSION),eu)
|
||||
$(BUILD_DIR)/src/menu/file_select.o: $(BUILD_DIR)/include/text_strings.h $(BUILD_DIR)/bin/eu/translation_en.o $(BUILD_DIR)/bin/eu/translation_de.o $(BUILD_DIR)/bin/eu/translation_fr.o
|
||||
$(BUILD_DIR)/src/menu/star_select.o: $(BUILD_DIR)/include/text_strings.h $(BUILD_DIR)/bin/eu/translation_en.o $(BUILD_DIR)/bin/eu/translation_de.o $(BUILD_DIR)/bin/eu/translation_fr.o
|
||||
|
@ -685,38 +606,7 @@ $(BUILD_DIR)/%.ci4: %.ci4.png
|
|||
|
||||
# compressed segment generation
|
||||
|
||||
ifeq ($(TARGET_N64),1)
|
||||
# TODO: ideally this would be `-Trodata-segment=0x07000000` but that doesn't set the address
|
||||
|
||||
$(BUILD_DIR)/bin/%.elf: $(BUILD_DIR)/bin/%.o
|
||||
$(LD) -e 0 -Ttext=$(SEGMENT_ADDRESS) -Map $@.map -o $@ $<
|
||||
$(BUILD_DIR)/actors/%.elf: $(BUILD_DIR)/actors/%.o
|
||||
$(LD) -e 0 -Ttext=$(SEGMENT_ADDRESS) -Map $@.map -o $@ $<
|
||||
|
||||
# Override for level.elf, which otherwise matches the above pattern
|
||||
.SECONDEXPANSION:
|
||||
$(BUILD_DIR)/levels/%/leveldata.elf: $(BUILD_DIR)/levels/%/leveldata.o $(BUILD_DIR)/bin/$$(TEXTURE_BIN).elf
|
||||
$(LD) -e 0 -Ttext=$(SEGMENT_ADDRESS) -Map $@.map --just-symbols=$(BUILD_DIR)/bin/$(TEXTURE_BIN).elf -o $@ $<
|
||||
|
||||
$(BUILD_DIR)/bin/%.bin: $(BUILD_DIR)/bin/%.elf
|
||||
$(EXTRACT_DATA_FOR_MIO) $< $@
|
||||
|
||||
$(BUILD_DIR)/actors/%.bin: $(BUILD_DIR)/actors/%.elf
|
||||
$(EXTRACT_DATA_FOR_MIO) $< $@
|
||||
|
||||
$(BUILD_DIR)/levels/%/leveldata.bin: $(BUILD_DIR)/levels/%/leveldata.elf
|
||||
$(EXTRACT_DATA_FOR_MIO) $< $@
|
||||
|
||||
$(BUILD_DIR)/%.mio0: $(BUILD_DIR)/%.bin
|
||||
$(MIO0TOOL) $< $@
|
||||
|
||||
$(BUILD_DIR)/%.mio0.o: $(BUILD_DIR)/%.mio0.s
|
||||
$(AS) $(ASFLAGS) -o $@ $<
|
||||
|
||||
$(BUILD_DIR)/%.mio0.s: $(BUILD_DIR)/%.mio0
|
||||
printf ".section .data\n\n.incbin \"$<\"\n" > $@
|
||||
endif
|
||||
|
||||
# PC Area
|
||||
$(BUILD_DIR)/%.table: %.aiff
|
||||
$(AIFF_EXTRACT_CODEBOOK) $< >$@
|
||||
|
||||
|
@ -753,10 +643,7 @@ $(SOUND_BIN_DIR)/%.m64: $(SOUND_BIN_DIR)/%.o
|
|||
$(SOUND_BIN_DIR)/%.o: $(SOUND_BIN_DIR)/%.s
|
||||
$(AS) $(ASFLAGS) -o $@ $<
|
||||
|
||||
ifeq ($(TARGET_N64),1)
|
||||
$(SOUND_BIN_DIR)/%.s: $(SOUND_BIN_DIR)/%
|
||||
printf ".section .data\n\n.incbin \"$<\"\n" > $@
|
||||
else
|
||||
|
||||
$(SOUND_BIN_DIR)/sound_data.ctl.c: $(SOUND_BIN_DIR)/sound_data.ctl
|
||||
echo "unsigned char gSoundDataADSR[] = {" > $@
|
||||
hexdump -v -e '1/1 "0x%X,"' $< >> $@
|
||||
|
@ -773,10 +660,9 @@ $(SOUND_BIN_DIR)/sequences.bin.c: $(SOUND_BIN_DIR)/sequences.bin
|
|||
echo "};" >> $@
|
||||
|
||||
$(SOUND_BIN_DIR)/bank_sets.c: $(SOUND_BIN_DIR)/bank_sets
|
||||
echo "unsigned char gBankSetsData[] = {" > $@
|
||||
echo "unsigned char gBankSetsData[0x100] = {" > $@
|
||||
hexdump -v -e '1/1 "0x%X,"' $< >> $@
|
||||
echo "};" >> $@
|
||||
endif
|
||||
|
||||
$(BUILD_DIR)/levels/scripts.o: $(BUILD_DIR)/include/level_headers.h
|
||||
|
||||
|
@ -833,9 +719,6 @@ $(BUILD_DIR)/src/audio/%.copt: $(BUILD_DIR)/src/audio/%.acpp
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(NON_MATCHING),0)
|
||||
$(GLOBAL_ASM_O_FILES): CC := $(PYTHON) tools/asm_processor/build.py $(CC) -- $(AS) $(ASFLAGS) --
|
||||
endif
|
||||
|
||||
# Rebuild files with 'GLOBAL_ASM' if the NON_MATCHING flag changes.
|
||||
$(GLOBAL_ASM_O_FILES): $(GLOBAL_ASM_DEP).$(NON_MATCHING)
|
||||
|
@ -859,32 +742,10 @@ $(BUILD_DIR)/%.o: $(BUILD_DIR)/%.c
|
|||
$(BUILD_DIR)/%.o: %.s
|
||||
$(AS) $(ASFLAGS) -MD $(BUILD_DIR)/$*.d -o $@ $<
|
||||
|
||||
ifeq ($(TARGET_N64),1)
|
||||
$(BUILD_DIR)/$(LD_SCRIPT): $(LD_SCRIPT)
|
||||
$(CPP) $(VERSION_CFLAGS) -MMD -MP -MT $@ -MF $@.d -I include/ -I . -DBUILD_DIR=$(BUILD_DIR) -o $@ $<
|
||||
|
||||
$(BUILD_DIR)/libultra.a: $(ULTRA_O_FILES)
|
||||
$(AR) rcs -o $@ $(ULTRA_O_FILES)
|
||||
tools/patch_libultra_math $@
|
||||
|
||||
$(BUILD_DIR)/libgoddard.a: $(GODDARD_O_FILES)
|
||||
$(AR) rcs -o $@ $(GODDARD_O_FILES)
|
||||
|
||||
$(ELF): $(O_FILES) $(MIO0_OBJ_FILES) $(SOUND_OBJ_FILES) $(SEG_FILES) $(BUILD_DIR)/$(LD_SCRIPT) undefined_syms.txt $(BUILD_DIR)/libultra.a $(BUILD_DIR)/libgoddard.a
|
||||
$(LD) -L $(BUILD_DIR) $(LDFLAGS) -o $@ $(O_FILES)$(LIBS) -lultra -lgoddard
|
||||
|
||||
$(ROM): $(ELF)
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) $< $(@:.z64=.bin) -O binary
|
||||
$(N64CKSUM) $(@:.z64=.bin) $@
|
||||
|
||||
$(BUILD_DIR)/$(TARGET).objdump: $(ELF)
|
||||
$(OBJDUMP) -D $< > $@
|
||||
|
||||
else
|
||||
$(EXE): $(O_FILES) $(MIO0_FILES:.mio0=.o) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES)
|
||||
$(LD) -L $(BUILD_DIR) -o $@ $(O_FILES) $(SOUND_OBJ_FILES) $(ULTRA_O_FILES) $(GODDARD_O_FILES) $(LDFLAGS)
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: all clean distclean default diff test load libultra
|
||||
.PRECIOUS: $(BUILD_DIR)/bin/%.elf $(SOUND_BIN_DIR)/%.ctl $(SOUND_BIN_DIR)/%.tbl $(SOUND_SAMPLE_TABLES) $(SOUND_BIN_DIR)/%.s $(BUILD_DIR)/%
|
||||
|
|
78
README.md
78
README.md
|
@ -12,80 +12,4 @@ Run `./extract-assets.py --clean && make clean` or `make distclean` to remove RO
|
|||
* True analog camera control is now available on our [testing branch](https://github.com/sm64pc/sm64pc/tree/testing).
|
||||
|
||||
## Building
|
||||
|
||||
### On Linux
|
||||
|
||||
#### 1. Copy baserom(s) for asset extraction
|
||||
|
||||
For each version (jp/us/eu) that you want to build an executable for, put an existing ROM at
|
||||
`./baserom.<version>.z64` for asset extraction.
|
||||
|
||||
#### 2. Install build dependencies
|
||||
|
||||
The build system has the following package requirements:
|
||||
* python3 >= 3.6
|
||||
* libsdl2-dev
|
||||
* [audiofile](https://audiofile.68k.org/)
|
||||
* libglew-dev
|
||||
* git
|
||||
|
||||
|
||||
__Debian / Ubuntu - targeting 32 bits__
|
||||
```
|
||||
sudo apt install build-essential git python3 libaudiofile-dev libglew-dev:i386 libsdl2-dev:i386
|
||||
```
|
||||
__Debian / Ubuntu - targeting 64 bits__
|
||||
```
|
||||
sudo apt install build-essential git python3 libaudiofile-dev libglew-dev libsdl2-dev
|
||||
```
|
||||
|
||||
__Arch Linux__
|
||||
```
|
||||
sudo pacman -S base-devel python audiofile sdl2 glew
|
||||
```
|
||||
|
||||
__Void Linux - targeting 64 bits__
|
||||
```
|
||||
sudo xbps-install -S base-devel python3 audiofile-devel SDL2-devel glew-devel
|
||||
```
|
||||
|
||||
__Void Linux - targeting 32 bits__
|
||||
```
|
||||
sudo xbps-install -S base-devel python3 audiofile-devel-32bit SDL2-devel-32bit glew-devel-32bit
|
||||
```
|
||||
|
||||
#### 3. Build the executable.
|
||||
|
||||
Run `make` to build (defaults to `VERSION=us`)
|
||||
|
||||
```
|
||||
make VERSION=jp -j6 # build (J) version with 6 jobs
|
||||
make VERSION=us WINDOWS_BUILD=1 # builds a (U) Windows executable
|
||||
```
|
||||
|
||||
### On Windows
|
||||
|
||||
A full guide is to be written. You can use [mxe](https://mxe.cc/) and MinGW.
|
||||
|
||||
### For the web
|
||||
|
||||
The game can be compiled for web browsers that support WebGL using [Emscripten](https://github.com/emscripten-core). To do so, install [emsdk](https://github.com/emscripten-core/emsdk) and run `make TARGET_WEB=1`.
|
||||
|
||||
## Optional enhancements
|
||||
|
||||
On the `./enhancements` folder, you'll find several .patch files, which can be applied in the following manner:
|
||||
|
||||
```
|
||||
git apply fps.patch --ignore-whitespace --reject
|
||||
```
|
||||
If any rejections occur, you can search for them with `find | grep .rej`.
|
||||
Try to solve rejections through [wiggle](https://github.com/neilbrown/wiggle).
|
||||
```
|
||||
wiggle rejection.rej --replace
|
||||
```
|
||||
|
||||
### Current issues
|
||||
|
||||
* Support for the EU version is still experimental.
|
||||
* There seems to be savedata-related problems on some 64-bits builds.
|
||||
* Camera controls are also bugged for some.
|
||||
For building instructions, please refer to the [wiki](https://github.com/sm64pc/sm64pc/wiki).
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
# L-trigger mapping
|
||||
|
||||
Some parts of the code might require the pressing of the L-trigger for testing reasons.
|
||||
|
||||
If you need that, alter `controller_sdl.c`.
|
||||
In the following line:
|
||||
```
|
||||
if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_LEFTSHOULDER)) pad->button |= Z_TRIG;
|
||||
```
|
||||
Replace `Z_TRIG` with `L_TRIG`, save and rebuild.
|
||||
|
||||
On a DS4, this now means that Z-trigger will be mapped to L2 and the L-trigger to L1.
|
|
@ -1,6 +1,10 @@
|
|||
#ifndef _SEGMENTS_H
|
||||
#define _SEGMENTS_H
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
#define USE_EXT_RAM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Memory addresses for segments. Ideally, this header file would not be
|
||||
* needed, and the addresses would be defined in sm64.ld and linker-inserted
|
||||
|
@ -44,10 +48,17 @@
|
|||
*/
|
||||
|
||||
#define SEG_BUFFERS 0x8005C000 // 0x0085000 in size
|
||||
#ifdef BETTERCAMERA
|
||||
#define SEG_MAIN 0x800F1000 // 0x1328000 in size
|
||||
#define SEG_ENGINE 0x80223800 // 0x0017000 in size
|
||||
#define SEG_FRAMEBUFFERS 0x8023A800 // 0x0070800 in size
|
||||
#define SEG_POOL_START 0x802AB000 // 0x0165000 in size
|
||||
#else
|
||||
#define SEG_MAIN 0x800E1000 // 0x1328000 in size
|
||||
#define SEG_ENGINE 0x80213800 // 0x0017000 in size
|
||||
#define SEG_FRAMEBUFFERS 0x8022A800 // 0x0070800 in size
|
||||
#define SEG_POOL_START 0x8029B000 // 0x0165000 in size
|
||||
#endif
|
||||
#define SEG_POOL_END 0x80800000
|
||||
#define SEG_POOL_END_4MB 0x80400000 // For the error message screen enhancement.
|
||||
#define SEG_GODDARD SEG_POOL_START + 0x113000
|
||||
|
|
|
@ -3,6 +3,21 @@
|
|||
|
||||
#include "text_menu_strings.h"
|
||||
|
||||
#define NC_CAMX _("Camera X Sensitivity")
|
||||
#define NC_CAMY _("Camera Y Sensitivity")
|
||||
#define NC_INVERTX _("Invert X Axis")
|
||||
#define NC_INVERTY _("Invert Y Axis")
|
||||
#define NC_CAMC _("Camera Centre Aggression")
|
||||
#define NC_CAMP _("Camera Pan Level")
|
||||
#define NC_ENABLED _("Enabled")
|
||||
#define NC_DISABLED _("Disabled")
|
||||
#define NC_BUTTON _("[R]: Options")
|
||||
#define NC_BUTTON2 _("[R]: Return")
|
||||
#define NC_OPTION _("OPTIONS")
|
||||
#define NC_HIGHLIGHT _("O")
|
||||
#define NC_ANALOGUE _("Analogue Camera")
|
||||
#define NC_MOUSE _("Mouse Look")
|
||||
|
||||
/**
|
||||
* Global Symbols
|
||||
*/
|
||||
|
|
|
@ -50,7 +50,7 @@ const LevelScript level_main_menu_entry_1[] = {
|
|||
GET_OR_SET(/*op*/ OP_SET, /*var*/ VAR_CURR_SAVE_FILE_NUM),
|
||||
STOP_MUSIC(/*fadeOutTime*/ 0x00BE),
|
||||
TRANSITION(/*transType*/ WARP_TRANSITION_FADE_INTO_COLOR, /*time*/ 16, /*color*/ 0xFF, 0xFF, 0xFF),
|
||||
SLEEP(/*frames*/ 24),
|
||||
SLEEP(/*frames*/ 16),
|
||||
CLEAR_LEVEL(),
|
||||
SLEEP_BEFORE_EXIT(/*frames*/ 1),
|
||||
SET_REG(/*value*/ LEVEL_CASTLE_GROUNDS),
|
||||
|
@ -89,7 +89,7 @@ const LevelScript level_main_menu_entry_2[] = {
|
|||
/*35*/ GET_OR_SET(/*op*/ OP_SET, /*var*/ VAR_CURR_ACT_NUM),
|
||||
/*36*/ STOP_MUSIC(/*fadeOutTime*/ 0x00BE),
|
||||
/*37*/ TRANSITION(/*transType*/ WARP_TRANSITION_FADE_INTO_COLOR, /*time*/ 16, /*color*/ 0xFF, 0xFF, 0xFF),
|
||||
/*39*/ SLEEP(/*frames*/ 24),
|
||||
/*39*/ SLEEP(/*frames*/ 16),
|
||||
/*40*/ CLEAR_LEVEL(),
|
||||
/*41*/ SLEEP_BEFORE_EXIT(/*frames*/ 1),
|
||||
// L1:
|
||||
|
|
|
@ -49,6 +49,15 @@ void *vec3f_sum(Vec3f dest, Vec3f a, Vec3f b) {
|
|||
return &dest; //! warning: function returns address of local variable
|
||||
}
|
||||
|
||||
/// Multiply vector 'dest' by a
|
||||
void *vec3f_mul(Vec3f dest, f32 a)
|
||||
{
|
||||
dest[0] *= a;
|
||||
dest[1] *= a;
|
||||
dest[2] *= a;
|
||||
return &dest; //! warning: function returns address of local variable
|
||||
}
|
||||
|
||||
/// Copy vector src to dest
|
||||
void *vec3s_copy(Vec3s dest, Vec3s src) {
|
||||
dest[0] = src[0];
|
||||
|
@ -81,11 +90,11 @@ void *vec3s_sum(Vec3s dest, Vec3s a, Vec3s b) {
|
|||
return &dest; //! warning: function returns address of local variable
|
||||
}
|
||||
|
||||
/// Subtract vector a from 'dest'
|
||||
void *vec3s_sub(Vec3s dest, Vec3s a) {
|
||||
dest[0] -= a[0];
|
||||
dest[1] -= a[1];
|
||||
dest[2] -= a[2];
|
||||
/// Make 'dest' the difference of vectors a and b.
|
||||
void *vec3f_dif(Vec3f dest, Vec3f a, Vec3f b) {
|
||||
dest[0] = a[0] - b[0];
|
||||
dest[1] = a[1] - b[1];
|
||||
dest[2] = a[2] - b[2];
|
||||
return &dest; //! warning: function returns address of local variable
|
||||
}
|
||||
|
||||
|
@ -140,6 +149,18 @@ void *vec3f_normalize(Vec3f dest) {
|
|||
return &dest; //! warning: function returns address of local variable
|
||||
}
|
||||
|
||||
/// Get length of vector 'a'
|
||||
f32 vec3f_length(Vec3f a)
|
||||
{
|
||||
return sqrtf(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
|
||||
}
|
||||
|
||||
/// Get dot product of vectors 'a' and 'b'
|
||||
f32 vec3f_dot(Vec3f a, Vec3f b)
|
||||
{
|
||||
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
/// Copy matrix 'src' to 'dest'
|
||||
|
|
|
@ -29,10 +29,14 @@ extern f32 gCosineTable[];
|
|||
|
||||
#define sqr(x) ((x) * (x))
|
||||
|
||||
#define abs(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
void *vec3f_copy(Vec3f dest, Vec3f src);
|
||||
void *vec3f_set(Vec3f dest, f32 x, f32 y, f32 z);
|
||||
void *vec3f_add(Vec3f dest, Vec3f a);
|
||||
void *vec3f_sum(Vec3f dest, Vec3f a, Vec3f b);
|
||||
void *vec3f_dif(Vec3f dest, Vec3f a, Vec3f b);
|
||||
void *vec3f_mul(Vec3f dest, f32 a);
|
||||
void *vec3s_copy(Vec3s dest, Vec3s src);
|
||||
void *vec3s_set(Vec3s dest, s16 x, s16 y, s16 z);
|
||||
void *vec3s_add(Vec3s dest, Vec3s a);
|
||||
|
@ -43,6 +47,8 @@ void *vec3f_to_vec3s(Vec3s dest, Vec3f a);
|
|||
void *find_vector_perpendicular_to_plane(Vec3f dest, Vec3f a, Vec3f b, Vec3f c);
|
||||
void *vec3f_cross(Vec3f dest, Vec3f a, Vec3f b);
|
||||
void *vec3f_normalize(Vec3f dest);
|
||||
f32 vec3f_length(Vec3f a);
|
||||
f32 vec3f_dot(Vec3f a, Vec3f b);
|
||||
void mtxf_copy(f32 dest[4][4], f32 src[4][4]);
|
||||
void mtxf_identity(f32 mtx[4][4]);
|
||||
void mtxf_translate(f32 a[4][4], Vec3f b);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "surface_collision.h"
|
||||
#include "surface_load.h"
|
||||
#include "game/object_list_processor.h"
|
||||
#include "math_util.h"
|
||||
|
||||
/**************************************************
|
||||
* WALLS *
|
||||
|
@ -779,3 +780,167 @@ s32 unused_resolve_floor_or_ceil_collisions(s32 checkCeil, f32 *px, f32 *py, f32
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Raycast functions
|
||||
*/
|
||||
s32 ray_surface_intersect(Vec3f orig, Vec3f dir, f32 dir_length, struct Surface *surface, Vec3f hit_pos, f32 *length)
|
||||
{
|
||||
Vec3f v0, v1, v2, e1, e2, h, s, q;
|
||||
f32 a, f, u, v;
|
||||
Vec3f add_dir;
|
||||
|
||||
// Get surface normal and some other stuff
|
||||
vec3s_to_vec3f(v0, surface->vertex1);
|
||||
vec3s_to_vec3f(v1, surface->vertex2);
|
||||
vec3s_to_vec3f(v2, surface->vertex3);
|
||||
|
||||
vec3f_dif(e1, v1, v0);
|
||||
vec3f_dif(e2, v2, v0);
|
||||
|
||||
vec3f_cross(h, dir, e2);
|
||||
|
||||
// Check if we're perpendicular from the surface
|
||||
a = vec3f_dot(e1, h);
|
||||
if (a > -0.00001f && a < 0.00001f)
|
||||
return FALSE;
|
||||
|
||||
// Check if we're making contact with the surface
|
||||
f = 1.0f / a;
|
||||
|
||||
vec3f_dif(s, orig, v0);
|
||||
u = f * vec3f_dot(s, h);
|
||||
if (u < 0.0f || u > 1.0f)
|
||||
return FALSE;
|
||||
|
||||
vec3f_cross(q, s, e1);
|
||||
v = f * vec3f_dot(dir, q);
|
||||
if (v < 0.0f || u + v > 1.0f)
|
||||
return FALSE;
|
||||
|
||||
// Get the length between our origin and the surface contact point
|
||||
*length = f * vec3f_dot(e2, q);
|
||||
if (*length <= 0.00001 || *length > dir_length)
|
||||
return FALSE;
|
||||
|
||||
// Successful contact
|
||||
vec3f_copy(add_dir, dir);
|
||||
vec3f_mul(add_dir, *length);
|
||||
vec3f_sum(hit_pos, orig, add_dir);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void find_surface_on_ray_list(struct SurfaceNode *list, Vec3f orig, Vec3f dir, f32 dir_length, struct Surface **hit_surface, Vec3f hit_pos, f32 *max_length)
|
||||
{
|
||||
s32 hit;
|
||||
f32 length;
|
||||
Vec3f chk_hit_pos;
|
||||
f32 top, bottom;
|
||||
|
||||
// Get upper and lower bounds of ray
|
||||
if (dir[1] >= 0.0f)
|
||||
{
|
||||
top = orig[1] + dir[1] * dir_length;
|
||||
bottom = orig[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
top = orig[1];
|
||||
bottom = orig[1] + dir[1] * dir_length;
|
||||
}
|
||||
|
||||
// Iterate through every surface of the list
|
||||
for (; list != NULL; list = list->next)
|
||||
{
|
||||
// Reject surface if out of vertical bounds
|
||||
if (list->surface->lowerY > top || list->surface->upperY < bottom)
|
||||
continue;
|
||||
|
||||
// Check intersection between the ray and this surface
|
||||
if ((hit = ray_surface_intersect(orig, dir, dir_length, list->surface, chk_hit_pos, &length)) != 0)
|
||||
{
|
||||
if (length <= *max_length)
|
||||
{
|
||||
*hit_surface = list->surface;
|
||||
vec3f_copy(hit_pos, chk_hit_pos);
|
||||
*max_length = length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void find_surface_on_ray_cell(s16 cellX, s16 cellZ, Vec3f orig, Vec3f normalized_dir, f32 dir_length, struct Surface **hit_surface, Vec3f hit_pos, f32 *max_length)
|
||||
{
|
||||
// Skip if OOB
|
||||
if (cellX >= 0 && cellX <= 0xF && cellZ >= 0 && cellZ <= 0xF)
|
||||
{
|
||||
// Iterate through each surface in this partition
|
||||
if (normalized_dir[1] > -0.99f)
|
||||
{
|
||||
find_surface_on_ray_list(gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length);
|
||||
find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length);
|
||||
}
|
||||
if (normalized_dir[1] < 0.99f)
|
||||
{
|
||||
find_surface_on_ray_list(gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length);
|
||||
find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length);
|
||||
}
|
||||
find_surface_on_ray_list(gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length);
|
||||
find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length);
|
||||
}
|
||||
}
|
||||
|
||||
void find_surface_on_ray(Vec3f orig, Vec3f dir, struct Surface **hit_surface, Vec3f hit_pos)
|
||||
{
|
||||
f32 max_length;
|
||||
s16 cellZ, cellX;
|
||||
f32 fCellZ, fCellX;
|
||||
f32 dir_length;
|
||||
Vec3f normalized_dir;
|
||||
f32 step, dx, dz;
|
||||
u32 i;
|
||||
|
||||
// Set that no surface has been hit
|
||||
*hit_surface = NULL;
|
||||
vec3f_sum(hit_pos, orig, dir);
|
||||
|
||||
// Get normalized direction
|
||||
dir_length = vec3f_length(dir);
|
||||
max_length = dir_length;
|
||||
vec3f_copy(normalized_dir, dir);
|
||||
vec3f_normalize(normalized_dir);
|
||||
|
||||
// Get our cell coordinate
|
||||
fCellX = (orig[0] + LEVEL_BOUNDARY_MAX) / CELL_SIZE;
|
||||
fCellZ = (orig[2] + LEVEL_BOUNDARY_MAX) / CELL_SIZE;
|
||||
cellX = (s16)fCellX;
|
||||
cellZ = (s16)fCellZ;
|
||||
|
||||
// Don't do DDA if straight down
|
||||
if (normalized_dir[1] >= 1.0f || normalized_dir[1] <= -1.0f)
|
||||
{
|
||||
find_surface_on_ray_cell(cellX, cellZ, orig, normalized_dir, dir_length, hit_surface, hit_pos, &max_length);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get cells we cross using DDA
|
||||
if (abs(dir[0]) >= abs(dir[2]))
|
||||
step = abs(dir[0]) / CELL_SIZE;
|
||||
else
|
||||
step = abs(dir[2]) / CELL_SIZE;
|
||||
|
||||
dx = dir[0] / step / CELL_SIZE;
|
||||
dz = dir[2] / step / CELL_SIZE;
|
||||
|
||||
for (i = 0; i < step && *hit_surface == NULL; i++)
|
||||
{
|
||||
find_surface_on_ray_cell(cellX, cellZ, orig, normalized_dir, dir_length, hit_surface, hit_pos, &max_length);
|
||||
|
||||
// Move cell coordinate
|
||||
fCellX += dx;
|
||||
fCellZ += dz;
|
||||
cellX = (s16)fCellX;
|
||||
cellZ = (s16)fCellZ;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,6 @@ f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor);
|
|||
f32 find_water_level(f32 x, f32 z);
|
||||
f32 find_poison_gas_level(f32 x, f32 z);
|
||||
void debug_surface_list_info(f32 xPos, f32 zPos);
|
||||
|
||||
void find_surface_on_ray(Vec3f orig, Vec3f dir, struct Surface **hit_surface, Vec3f hit_pos);
|
||||
|
||||
#endif /* _SURFACE_COLLISION_H */
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
enum newcam_flagvalues
|
||||
{
|
||||
NC_FLAG_XTURN = 0x0001,//If this flag is set, the camera's yaw can be moved by the player.
|
||||
NC_FLAG_YTURN = 0x0002, //If this flag is set, the camera's pitch can be moved by the player.
|
||||
NC_FLAG_ZOOM = 0x0004, //If this flag is set, the camera's distance can be set by the player.
|
||||
NC_FLAG_8D = 0x0008, //If this flag is set, the camera will snap to an 8 directional axis
|
||||
NC_FLAG_4D = 0x0010, //If this flag is set, the camera will snap to a 4 directional axis
|
||||
NC_FLAG_2D = 0x0020, //If this flag is set, the camera will stick to 2D.
|
||||
NC_FLAG_FOCUSX = 0x0040, //If this flag is set, the camera will point towards its focus on the X axis.
|
||||
NC_FLAG_FOCUSY = 0x0080, //If this flag is set, the camera will point towards its focus on the Y axis.
|
||||
NC_FLAG_FOCUSZ = 0x0100, //If this flag is set, the camera will point towards its focus on the Z axis.
|
||||
NC_FLAG_POSX = 0x0200, //If this flag is set, the camera will move along the X axis.
|
||||
NC_FLAG_POSY = 0x0400, //If this flag is set, the camera will move along the Y axis.
|
||||
NC_FLAG_POSZ = 0x0800, //If this flag is set, the camera will move along the Z axis.
|
||||
NC_FLAG_COLLISION = 0x1000, //If this flag is set, the camera will collide and correct itself with terrain.
|
||||
NC_FLAG_SLIDECORRECT = 0x2000, //If this flag is set, the camera will attempt to centre itself behind Mario whenever he's sliding.
|
||||
|
||||
NC_MODE_NORMAL = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION,
|
||||
NC_MODE_SLIDE = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION | NC_FLAG_SLIDECORRECT,
|
||||
NC_MODE_FIXED = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ,
|
||||
NC_MODE_2D = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION,
|
||||
NC_MODE_8D = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_8D | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION,
|
||||
NC_MODE_FIXED_NOMOVE = 0x0000,
|
||||
NC_MODE_NOTURN = NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION,
|
||||
NC_MODE_NOROTATE = NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION
|
||||
|
||||
};
|
||||
|
||||
extern void newcam_display_options(void);
|
||||
extern void newcam_check_pause_buttons(void);
|
||||
extern void newcam_init_settings(void);
|
||||
extern void newcam_render_option_text(void);
|
||||
extern void newcam_diagnostics(void);
|
||||
|
||||
extern u8 newcam_option_open;
|
||||
|
||||
extern u8 newcam_sensitivityX; //How quick the camera works.
|
||||
extern u8 newcam_sensitivityY;
|
||||
extern u8 newcam_invertX;
|
||||
extern u8 newcam_invertY;
|
||||
extern u8 newcam_panlevel; //How much the camera sticks out a bit in the direction you're looking.
|
||||
extern u8 newcam_aggression; //How much the camera tries to centre itself to Mario's facing and movement.
|
||||
extern u8 newcam_active; // basically the thing that governs if newcam is on.
|
||||
extern u8 newcam_analogue;
|
||||
extern u16 newcam_intendedmode;
|
||||
|
||||
extern u16 newcam_mode;
|
||||
extern s16 newcam_yaw;
|
|
@ -0,0 +1,901 @@
|
|||
#include "sm64.h"
|
||||
#include "game/camera.h"
|
||||
#include "game/level_update.h"
|
||||
#include "game/print.h"
|
||||
#include "engine/math_util.h"
|
||||
#include "game/segment2.h"
|
||||
#include "game/save_file.h"
|
||||
#include "bettercamera.h"
|
||||
#include "include/text_strings.h"
|
||||
#include "engine/surface_collision.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Quick explanation of the camera modes
|
||||
|
||||
NC_MODE_NORMAL: Standard mode, allows dualaxial movement and free control of the camera.
|
||||
NC_MODE_FIXED: Disables control of camera, and the actual position of the camera doesn't update.
|
||||
NC_MODE_2D: Disables horizontal control of the camera and locks Mario's direction to the X axis. NYI though.
|
||||
NC_MODE_8D: 8 directional movement. Similar to standard, except the camera direction snaps to 8 directions.
|
||||
NC_MODE_FIXED_NOMOVE: Disables control and movement of the camera.
|
||||
NC_MODE_NOTURN: Disables horizontal and vertical control of the camera.
|
||||
**/
|
||||
|
||||
//!A bunch of developer intended options, to cover every base, really.
|
||||
//#define NEWCAM_DEBUG //Some print values for puppycam. Not useful anymore, but never hurts to keep em around.
|
||||
//#define nosound //If for some reason you hate the concept of audio, you can disable it.
|
||||
//#define noaccel //Disables smooth movement of the camera with the C buttons.
|
||||
#define DEGRADE 0.1f //What percent of the remaining camera movement is degraded. Default is 10%
|
||||
|
||||
|
||||
//!Hardcoded camera angle stuff. They're essentially area boxes that when Mario is inside, will trigger some view changes.
|
||||
///Don't touch this btw, unless you know what you're doing, this has to be above for religious reasons.
|
||||
struct newcam_hardpos
|
||||
{
|
||||
u8 newcam_hard_levelID;
|
||||
u8 newcam_hard_areaID;
|
||||
u8 newcam_hard_permaswap;
|
||||
u16 newcam_hard_modeset;
|
||||
s16 newcam_hard_X1;
|
||||
s16 newcam_hard_Y1;
|
||||
s16 newcam_hard_Z1;
|
||||
s16 newcam_hard_X2;
|
||||
s16 newcam_hard_Y2;
|
||||
s16 newcam_hard_Z2;
|
||||
s16 newcam_hard_camX;
|
||||
s16 newcam_hard_camY;
|
||||
s16 newcam_hard_camZ;
|
||||
s16 newcam_hard_lookX;
|
||||
s16 newcam_hard_lookY;
|
||||
s16 newcam_hard_lookZ;
|
||||
};
|
||||
|
||||
///This is the bit that defines where the angles happen. They're basically environment boxes that dictate camera behaviour.
|
||||
//Permaswap is a boolean that simply determines wether or not when the camera changes at this point it stays changed. 0 means it resets when you leave, and 1 means it stays changed.
|
||||
//The camera position fields accept "32767" as an ignore flag.
|
||||
struct newcam_hardpos newcam_fixedcam[] =
|
||||
{
|
||||
{/*Level ID*/ 16,/*Area ID*/ 1,/*Permaswap*/ 0,/*Mode*/ NC_MODE_FIXED_NOMOVE, //Standard params.
|
||||
/*X begin*/ -540,/*Y begin*/ 800,/*Z begin*/ -3500, //Where the activation box begins
|
||||
/*X end*/ 540,/*Y end*/ 2000,/*Z end*/ -1500, //Where the activation box ends.
|
||||
/*Cam X*/ 0,/*Cam Y*/ 1500,/*Cam Z*/ -1000, //The position the camera gets placed for NC_MODE_FIXED and NC_MODE_FIXED_NOMOVE
|
||||
/*Look X*/ 0,/*Look Y*/ 800,/*Look Z*/ -2500}, //The position the camera looks at for NC_MODE_FIXED_NOMOVE
|
||||
};
|
||||
|
||||
|
||||
#ifdef noaccel
|
||||
u8 accel = 255;
|
||||
#else
|
||||
u8 accel = 10;
|
||||
#endif // noaccel
|
||||
|
||||
s16 newcam_yaw; //Z axis rotation
|
||||
s8 newcam_yaw_acc;
|
||||
s16 newcam_tilt = 1500; //Y axis rotation
|
||||
s8 newcam_tilt_acc;
|
||||
u16 newcam_distance = 750; //The distance the camera stays from the player
|
||||
u16 newcam_distance_target = 750; //The distance the player camera tries to reach.
|
||||
f32 newcam_pos_target[3]; //The position the camera is basing calculations off. *usually* Mario.
|
||||
f32 newcam_pos[3]; //Position the camera is in the world
|
||||
f32 newcam_lookat[3]; //Position the camera is looking at
|
||||
f32 newcam_framessincec[2];
|
||||
f32 newcam_extheight = 125;
|
||||
u8 newcam_centering = 0; // The flag that depicts wether the camera's goin gto try centering.
|
||||
s16 newcam_yaw_target; // The yaw value the camera tries to set itself to when the centre flag is active. Is set to Mario's face angle.
|
||||
f32 newcam_turnwait; // The amount of time to wait after landing before allowing the camera to turn again
|
||||
f32 newcam_pan_x;
|
||||
f32 newcam_pan_z;
|
||||
u8 newcam_cstick_down = 0; //Just a value that triggers true when the player 2 stick is moved in 8 direction move to prevent holding it down.
|
||||
u8 newcam_target;
|
||||
|
||||
u8 newcam_sensitivityX; //How quick the camera works.
|
||||
u8 newcam_sensitivityY;
|
||||
u8 newcam_invertX; //Reverses movement of the camera axis.
|
||||
u8 newcam_invertY;
|
||||
u8 newcam_panlevel; //How much the camera sticks out a bit in the direction you're looking.
|
||||
u8 newcam_aggression; //How much the camera tries to centre itself to Mario's facing and movement.
|
||||
u8 newcam_analogue; //Wether to accept inputs from a player 2 joystick, and then disables C button input.
|
||||
u8 newcam_mouse; // Whether to accept mouse input
|
||||
s16 newcam_distance_values[] = {750,1250,2000};
|
||||
u8 newcam_active = 1; // basically the thing that governs if newcam is on.
|
||||
u16 newcam_mode;
|
||||
u16 newcam_intendedmode = 0; // which camera mode the camera's going to try to be in when not forced into another.
|
||||
u16 newcam_modeflags;
|
||||
|
||||
u8 newcam_option_open = 0;
|
||||
s8 newcam_option_selection = 0;
|
||||
f32 newcam_option_timer = 0;
|
||||
u8 newcam_option_index = 0;
|
||||
u8 newcam_option_scroll = 0;
|
||||
u8 newcam_option_scroll_last = 0;
|
||||
u8 newcam_total = 8; //How many options there are in newcam_uptions.
|
||||
|
||||
u8 newcam_options[][64] = {{NC_ANALOGUE}, {NC_MOUSE}, {NC_CAMX}, {NC_CAMY}, {NC_INVERTX}, {NC_INVERTY}, {NC_CAMC}, {NC_CAMP}};
|
||||
u8 newcam_flags[][64] = {{NC_DISABLED}, {NC_ENABLED}};
|
||||
u8 newcam_strings[][64] = {{NC_BUTTON}, {NC_BUTTON2}, {NC_OPTION}, {NC_HIGHLIGHT}};
|
||||
|
||||
extern int mouse_x;
|
||||
extern int mouse_y;
|
||||
|
||||
///This is called at every level initialisation.
|
||||
void newcam_init(struct Camera *c, u8 dv)
|
||||
{
|
||||
newcam_tilt = 1500;
|
||||
newcam_distance_target = newcam_distance_values[dv];
|
||||
newcam_yaw = -c->yaw+0x4000; //Mario and the camera's yaw have this offset between them.
|
||||
newcam_mode = NC_MODE_NORMAL;
|
||||
///This here will dictate what modes the camera will start in at the beginning of a level. Below are some examples.
|
||||
switch (gCurrLevelNum)
|
||||
{
|
||||
case LEVEL_BITDW: newcam_yaw = 0x4000; newcam_mode = NC_MODE_8D; newcam_tilt = 4000; newcam_distance_target = newcam_distance_values[2]; break;
|
||||
case LEVEL_BITFS: newcam_yaw = 0x4000; newcam_mode = NC_MODE_8D; newcam_tilt = 4000; newcam_distance_target = newcam_distance_values[2]; break;
|
||||
case LEVEL_BITS: newcam_yaw = 0x4000; newcam_mode = NC_MODE_8D; newcam_tilt = 4000; newcam_distance_target = newcam_distance_values[2]; break;
|
||||
case LEVEL_WF: newcam_yaw = 0x4000; newcam_tilt = 2000; newcam_distance_target = newcam_distance_values[1]; break;
|
||||
case LEVEL_RR: newcam_yaw = 0x6000; newcam_tilt = 2000; newcam_distance_target = newcam_distance_values[2]; break;
|
||||
case LEVEL_CCM: if (gCurrAreaIndex == 1) {newcam_yaw = -0x4000; newcam_tilt = 2000; newcam_distance_target = newcam_distance_values[1];} else newcam_mode = NC_MODE_SLIDE; break;
|
||||
case LEVEL_WDW: newcam_yaw = 0x2000; newcam_tilt = 3000; newcam_distance_target = newcam_distance_values[1]; break;
|
||||
case 27: newcam_mode = NC_MODE_SLIDE; break;
|
||||
case LEVEL_THI: if (gCurrAreaIndex == 2) newcam_mode = NC_MODE_SLIDE; break;
|
||||
}
|
||||
|
||||
newcam_distance = newcam_distance_target;
|
||||
newcam_intendedmode = newcam_mode;
|
||||
newcam_modeflags = newcam_mode;
|
||||
}
|
||||
static f32 newcam_clamp(f32 value, f32 max, f32 min)
|
||||
{
|
||||
if (value > max)
|
||||
value = max;
|
||||
if (value < min)
|
||||
value = min;
|
||||
return value;
|
||||
}
|
||||
///These are the default settings for Puppycam. You may change them to change how they'll be set for first timers.
|
||||
void newcam_init_settings()
|
||||
{
|
||||
if (save_check_firsttime())
|
||||
{
|
||||
save_file_get_setting();
|
||||
newcam_clamp(newcam_sensitivityX, 10, 250);
|
||||
newcam_clamp(newcam_sensitivityY, 10, 250);
|
||||
newcam_clamp(newcam_aggression, 0, 100);
|
||||
newcam_clamp(newcam_panlevel, 0, 100);
|
||||
newcam_clamp(newcam_invertX, 0, 1);
|
||||
newcam_clamp(newcam_invertY, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
newcam_sensitivityX = 75;
|
||||
newcam_sensitivityY = 75;
|
||||
newcam_aggression = 0;
|
||||
newcam_panlevel = 75;
|
||||
newcam_invertX = 0;
|
||||
newcam_invertY = 0;
|
||||
save_set_firsttime();
|
||||
}
|
||||
}
|
||||
|
||||
/** Mathematic calculations. This stuffs so basic even *I* understand it lol
|
||||
Basically, it just returns a position based on angle */
|
||||
static s16 lengthdir_x(f32 length, s16 dir)
|
||||
{
|
||||
return (s16) (length * coss(dir));
|
||||
}
|
||||
static s16 lengthdir_y(f32 length, s16 dir)
|
||||
{
|
||||
return (s16) (length * sins(dir));
|
||||
}
|
||||
|
||||
void newcam_diagnostics(void)
|
||||
{
|
||||
print_text_fmt_int(32,192,"Lv %d",gCurrLevelNum);
|
||||
print_text_fmt_int(32,176,"Area %d",gCurrAreaIndex);
|
||||
print_text_fmt_int(32,160,"X %d",gMarioState->pos[0]);
|
||||
print_text_fmt_int(32,144,"Y %d",gMarioState->pos[1]);
|
||||
print_text_fmt_int(32,128,"Z %d",gMarioState->pos[2]);
|
||||
print_text_fmt_int(32,112,"FLAGS %d",newcam_modeflags);
|
||||
print_text_fmt_int(180,112,"INTM %d",newcam_intendedmode);
|
||||
print_text_fmt_int(32,96,"TILT UP %d",newcam_tilt_acc);
|
||||
print_text_fmt_int(32,80,"YAW UP %d",newcam_yaw_acc);
|
||||
print_text_fmt_int(32,64,"YAW %d",newcam_yaw);
|
||||
print_text_fmt_int(32,48,"TILT %d",newcam_tilt);
|
||||
print_text_fmt_int(32,32,"DISTANCE %d",newcam_distance);
|
||||
}
|
||||
|
||||
static s16 newcam_adjust_value(s16 var, s16 val)
|
||||
{
|
||||
var += val;
|
||||
if (var > 100)
|
||||
var = 100;
|
||||
if (var < -100)
|
||||
var = -100;
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
static f32 newcam_approach_float(f32 var, f32 val, f32 inc)
|
||||
{
|
||||
if (var < val)
|
||||
return min(var + inc, val);
|
||||
else
|
||||
return max(var - inc, val);
|
||||
}
|
||||
|
||||
static s16 newcam_approach_s16(s16 var, s16 val, s16 inc)
|
||||
{
|
||||
if (var < val)
|
||||
return max(var + inc, val);
|
||||
else
|
||||
return min(var - inc, val);
|
||||
}
|
||||
|
||||
static u8 ivrt(u8 axis)
|
||||
{
|
||||
if (axis == 0)
|
||||
{
|
||||
if (newcam_invertX == 0)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newcam_invertY == 0)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void newcam_rotate_button(void)
|
||||
{
|
||||
if ((newcam_modeflags & NC_FLAG_8D || newcam_modeflags & NC_FLAG_4D) && newcam_modeflags & NC_FLAG_XTURN) //8 directional camera rotation input for buttons.
|
||||
{
|
||||
if ((gPlayer1Controller->buttonPressed & L_CBUTTONS) && newcam_analogue == 0)
|
||||
{
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||
#endif
|
||||
if (newcam_modeflags & NC_FLAG_8D)
|
||||
newcam_yaw_target = newcam_yaw_target+0x2000;
|
||||
else
|
||||
newcam_yaw_target = newcam_yaw_target+0x4000;
|
||||
newcam_centering = 1;
|
||||
}
|
||||
else
|
||||
if ((gPlayer1Controller->buttonPressed & R_CBUTTONS) && newcam_analogue == 0)
|
||||
{
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||
#endif
|
||||
if (newcam_modeflags & NC_FLAG_8D)
|
||||
newcam_yaw_target = newcam_yaw_target-0x2000;
|
||||
else
|
||||
newcam_yaw_target = newcam_yaw_target-0x4000;
|
||||
newcam_centering = 1;
|
||||
}
|
||||
}
|
||||
else //Standard camera movement
|
||||
if (newcam_modeflags & NC_FLAG_XTURN)
|
||||
{
|
||||
if ((gPlayer1Controller->buttonDown & L_CBUTTONS) && newcam_analogue == 0)
|
||||
newcam_yaw_acc = newcam_adjust_value(newcam_yaw_acc,accel);
|
||||
else if ((gPlayer1Controller->buttonDown & R_CBUTTONS) && newcam_analogue == 0)
|
||||
newcam_yaw_acc = newcam_adjust_value(newcam_yaw_acc,-accel);
|
||||
else
|
||||
#ifdef noaccel
|
||||
newcam_yaw_acc = 0;
|
||||
#else
|
||||
newcam_yaw_acc -= (newcam_yaw_acc*(DEGRADE));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (gPlayer1Controller->buttonDown & U_CBUTTONS && newcam_modeflags & NC_FLAG_YTURN && newcam_analogue == 0)
|
||||
newcam_tilt_acc = newcam_adjust_value(newcam_tilt_acc,accel);
|
||||
else if (gPlayer1Controller->buttonDown & D_CBUTTONS && newcam_modeflags & NC_FLAG_YTURN && newcam_analogue == 0)
|
||||
newcam_tilt_acc = newcam_adjust_value(newcam_tilt_acc,-accel);
|
||||
else
|
||||
#ifdef noaccel
|
||||
newcam_tilt_acc = 0;
|
||||
#else
|
||||
newcam_tilt_acc -= (newcam_tilt_acc*(DEGRADE));
|
||||
#endif
|
||||
|
||||
newcam_framessincec[0] += 1;
|
||||
newcam_framessincec[1] += 1;
|
||||
if ((gPlayer1Controller->buttonPressed & L_CBUTTONS) && newcam_modeflags & NC_FLAG_XTURN && !(newcam_modeflags & NC_FLAG_8D) && newcam_analogue == 0)
|
||||
{
|
||||
if (newcam_framessincec[0] < 6)
|
||||
{
|
||||
newcam_yaw_target = newcam_yaw+0x3000;
|
||||
newcam_centering = 1;
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||
#endif
|
||||
}
|
||||
newcam_framessincec[0] = 0;
|
||||
}
|
||||
if ((gPlayer1Controller->buttonPressed & R_CBUTTONS) && newcam_modeflags & NC_FLAG_XTURN && !(newcam_modeflags & NC_FLAG_8D) && newcam_analogue == 0)
|
||||
{
|
||||
if (newcam_framessincec[1] < 6)
|
||||
{
|
||||
newcam_yaw_target = newcam_yaw-0x3000;
|
||||
newcam_centering = 1;
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||
#endif
|
||||
}
|
||||
newcam_framessincec[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
if (newcam_analogue == 1) //There's not much point in keeping this behind a check, but it wouldn't hurt, just incase any 2player shenanigans ever happen, it makes it easy to disable.
|
||||
{ //The joystick values cap at 80, so divide by 8 to get the same net result at maximum turn as the button
|
||||
if (ABS(gPlayer2Controller->stickX) > 20 && newcam_modeflags & NC_FLAG_XTURN)
|
||||
{
|
||||
if (newcam_modeflags & NC_FLAG_8D)
|
||||
{
|
||||
if (newcam_cstick_down == 0)
|
||||
{
|
||||
newcam_cstick_down = 1;
|
||||
newcam_centering = 1;
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs);
|
||||
#endif
|
||||
if (gPlayer2Controller->stickX > 20)
|
||||
{
|
||||
if (newcam_modeflags & NC_FLAG_8D)
|
||||
newcam_yaw_target = newcam_yaw_target+0x2000;
|
||||
else
|
||||
newcam_yaw_target = newcam_yaw_target+0x4000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newcam_modeflags & NC_FLAG_8D)
|
||||
newcam_yaw_target = newcam_yaw_target-0x2000;
|
||||
else
|
||||
newcam_yaw_target = newcam_yaw_target-0x4000;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
newcam_yaw_acc = newcam_adjust_value(newcam_yaw_acc,(-gPlayer2Controller->stickX/4));
|
||||
}
|
||||
else
|
||||
{
|
||||
newcam_cstick_down = 0;
|
||||
newcam_yaw_acc -= (newcam_yaw_acc*(DEGRADE));
|
||||
}
|
||||
|
||||
if (ABS(gPlayer2Controller->stickY) > 20 && newcam_modeflags & NC_FLAG_YTURN)
|
||||
newcam_tilt_acc = newcam_adjust_value(newcam_tilt_acc,(-gPlayer2Controller->stickY/4));
|
||||
else
|
||||
newcam_tilt_acc -= (newcam_tilt_acc*(DEGRADE));
|
||||
}
|
||||
|
||||
if (newcam_mouse == 1)
|
||||
{
|
||||
newcam_yaw += mouse_x * 16;
|
||||
newcam_tilt += mouse_y * 16;
|
||||
}
|
||||
}
|
||||
|
||||
static void newcam_zoom_button(void)
|
||||
{
|
||||
//Smoothly move the camera to the new spot.
|
||||
if (newcam_distance > newcam_distance_target)
|
||||
{
|
||||
newcam_distance -= 250;
|
||||
if (newcam_distance < newcam_distance_target)
|
||||
newcam_distance = newcam_distance_target;
|
||||
}
|
||||
if (newcam_distance < newcam_distance_target)
|
||||
{
|
||||
newcam_distance += 250;
|
||||
if (newcam_distance > newcam_distance_target)
|
||||
newcam_distance = newcam_distance_target;
|
||||
}
|
||||
|
||||
//When you press L and R together, set the flag for centering the camera. Afterwards, start setting the yaw to the Player's yaw at the time.
|
||||
if (gPlayer1Controller->buttonDown & L_TRIG && gPlayer1Controller->buttonDown & R_TRIG && newcam_modeflags & NC_FLAG_ZOOM)
|
||||
{
|
||||
newcam_yaw_target = -gMarioState->faceAngle[1]-0x4000;
|
||||
newcam_centering = 1;
|
||||
}
|
||||
else //Each time the player presses R, but NOT L the camera zooms out more, until it hits the limit and resets back to close view.
|
||||
if (gPlayer1Controller->buttonPressed & R_TRIG && newcam_modeflags & NC_FLAG_XTURN)
|
||||
{
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CLICK_CHANGE_VIEW, gDefaultSoundArgs);
|
||||
#endif
|
||||
|
||||
if (newcam_distance_target == newcam_distance_values[0])
|
||||
newcam_distance_target = newcam_distance_values[1];
|
||||
else
|
||||
if (newcam_distance_target == newcam_distance_values[1])
|
||||
newcam_distance_target = newcam_distance_values[2];
|
||||
else
|
||||
newcam_distance_target = newcam_distance_values[0];
|
||||
|
||||
}
|
||||
if (newcam_centering && newcam_modeflags & NC_FLAG_XTURN)
|
||||
{
|
||||
newcam_yaw = approach_s16_symmetric(newcam_yaw,newcam_yaw_target,0x800);
|
||||
if (newcam_yaw = newcam_yaw_target)
|
||||
newcam_centering = 0;
|
||||
}
|
||||
else
|
||||
newcam_yaw_target = newcam_yaw;
|
||||
}
|
||||
|
||||
static void newcam_update_values(void)
|
||||
{//For tilt, this just limits it so it doesn't go further than 90 degrees either way. 90 degrees is actually 16384, but can sometimes lead to issues, so I just leave it shy of 90.
|
||||
u8 waterflag = 0;
|
||||
newcam_sensitivityX = 75;
|
||||
newcam_sensitivityY = 75;
|
||||
if (newcam_modeflags & NC_FLAG_XTURN)
|
||||
newcam_yaw += (ivrt(0)*(newcam_yaw_acc*(newcam_sensitivityX/10)));
|
||||
if (((newcam_tilt < 12000 && newcam_tilt_acc*ivrt(1) > 0) || (newcam_tilt > -12000 && newcam_tilt_acc*ivrt(1) < 0)) && newcam_modeflags & NC_FLAG_YTURN)
|
||||
newcam_tilt += (ivrt(1)*(newcam_tilt_acc*(newcam_sensitivityY/10)));
|
||||
else
|
||||
{
|
||||
if (newcam_tilt > 12000)
|
||||
newcam_tilt = 12000;
|
||||
if (newcam_tilt < -12000)
|
||||
newcam_tilt = -12000;
|
||||
}
|
||||
|
||||
if (newcam_turnwait > 0 && gMarioState->vel[1] == 0)
|
||||
{
|
||||
newcam_turnwait -= 1;
|
||||
if (newcam_turnwait < 0)
|
||||
newcam_turnwait = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gMarioState->intendedMag > 0 && gMarioState->vel[1] == 0 && newcam_modeflags & NC_FLAG_XTURN)
|
||||
newcam_yaw = (approach_s16_symmetric(newcam_yaw,-gMarioState->faceAngle[1]-0x4000,((newcam_aggression*(ABS(gPlayer1Controller->stickX/10)))*(gMarioState->forwardVel/32))));
|
||||
else
|
||||
newcam_turnwait = 10;
|
||||
}
|
||||
|
||||
if (newcam_modeflags & NC_FLAG_SLIDECORRECT)
|
||||
{
|
||||
switch (gMarioState->action)
|
||||
{
|
||||
case ACT_BUTT_SLIDE: if (gMarioState->forwardVel > 8) waterflag = 1; break;
|
||||
case ACT_STOMACH_SLIDE: if (gMarioState->forwardVel > 8) waterflag = 1; break;
|
||||
case ACT_HOLD_BUTT_SLIDE: if (gMarioState->forwardVel > 8) waterflag = 1; break;
|
||||
case ACT_HOLD_STOMACH_SLIDE: if (gMarioState->forwardVel > 8) waterflag = 1; break;
|
||||
}
|
||||
}
|
||||
switch (gMarioState->action)
|
||||
{
|
||||
case ACT_SHOT_FROM_CANNON: waterflag = 1; break;
|
||||
case ACT_FLYING: waterflag = 1; break;
|
||||
}
|
||||
|
||||
if (gMarioState->action & ACT_FLAG_SWIMMING)
|
||||
{
|
||||
if (gMarioState->forwardVel > 2)
|
||||
waterflag = 1;
|
||||
}
|
||||
|
||||
if (waterflag && newcam_modeflags & NC_FLAG_XTURN)
|
||||
{
|
||||
newcam_yaw = (approach_s16_symmetric(newcam_yaw,-gMarioState->faceAngle[1]-0x4000,(gMarioState->forwardVel*128)));
|
||||
if ((signed)gMarioState->forwardVel > 1)
|
||||
newcam_tilt = (approach_s16_symmetric(newcam_tilt,(-gMarioState->faceAngle[0]*0.8)+3000,(gMarioState->forwardVel*32)));
|
||||
else
|
||||
newcam_tilt = (approach_s16_symmetric(newcam_tilt,3000,32));
|
||||
}
|
||||
}
|
||||
|
||||
static void newcam_collision(void)
|
||||
{
|
||||
struct Surface *surf;
|
||||
Vec3f camdir;
|
||||
Vec3f hitpos;
|
||||
|
||||
camdir[0] = newcam_pos[0]-newcam_lookat[0];
|
||||
camdir[1] = newcam_pos[1]-newcam_lookat[1];
|
||||
camdir[2] = newcam_pos[2]-newcam_lookat[2];
|
||||
|
||||
|
||||
|
||||
find_surface_on_ray(newcam_pos_target, camdir, &surf, &hitpos);
|
||||
|
||||
if (surf)
|
||||
{
|
||||
newcam_pos[0] = hitpos[0];
|
||||
newcam_pos[1] = approach_f32(hitpos[1],newcam_pos[1],25,-25);
|
||||
newcam_pos[2] = hitpos[2];
|
||||
newcam_pan_x = 0;
|
||||
newcam_pan_z = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void newcam_set_pan(void)
|
||||
{
|
||||
//Apply panning values based on Mario's direction.
|
||||
if (gMarioState->action != ACT_HOLDING_BOWSER && gMarioState->action != ACT_SLEEPING && gMarioState->action != ACT_START_SLEEPING)
|
||||
{
|
||||
approach_f32_asymptotic_bool(&newcam_pan_x, lengthdir_x((160*newcam_panlevel)/100, -gMarioState->faceAngle[1]-0x4000), 0.05);
|
||||
approach_f32_asymptotic_bool(&newcam_pan_z, lengthdir_y((160*newcam_panlevel)/100, -gMarioState->faceAngle[1]-0x4000), 0.05);
|
||||
}
|
||||
else
|
||||
{
|
||||
approach_f32_asymptotic_bool(&newcam_pan_x, 0, 0.05);
|
||||
approach_f32_asymptotic_bool(&newcam_pan_z, 0, 0.05);
|
||||
}
|
||||
|
||||
newcam_pan_x = newcam_pan_x*(min(newcam_distance/newcam_distance_target,1));
|
||||
newcam_pan_z = newcam_pan_z*(min(newcam_distance/newcam_distance_target,1));
|
||||
}
|
||||
|
||||
static void newcam_position_cam(void)
|
||||
{
|
||||
f32 floorY = 0;
|
||||
f32 floorY2 = 0;
|
||||
s16 shakeX;
|
||||
s16 shakeY;
|
||||
|
||||
if (!(gMarioState->action & ACT_FLAG_SWIMMING))
|
||||
calc_y_to_curr_floor(&floorY, 1.f, 200.f, &floorY2, 0.9f, 200.f);
|
||||
|
||||
newcam_update_values();
|
||||
shakeX = gLakituState.shakeMagnitude[1];
|
||||
shakeY = gLakituState.shakeMagnitude[0];
|
||||
//Fetch Mario's current position. Not hardcoded just for the sake of flexibility, though this specific bit is temp, because it won't always want to be focusing on Mario.
|
||||
newcam_pos_target[0] = gMarioState->pos[0];
|
||||
newcam_pos_target[1] = gMarioState->pos[1]+newcam_extheight;
|
||||
newcam_pos_target[2] = gMarioState->pos[2];
|
||||
//These will set the position of the camera to where Mario is supposed to be, minus adjustments for where the camera should be, on top of.
|
||||
if (newcam_modeflags & NC_FLAG_POSX)
|
||||
newcam_pos[0] = newcam_pos_target[0]+lengthdir_x(lengthdir_x(newcam_distance,newcam_tilt+shakeX),newcam_yaw+shakeY);
|
||||
if (newcam_modeflags & NC_FLAG_POSY)
|
||||
newcam_pos[2] = newcam_pos_target[2]+lengthdir_y(lengthdir_x(newcam_distance,newcam_tilt+shakeX),newcam_yaw+shakeY);
|
||||
if (newcam_modeflags & NC_FLAG_POSZ)
|
||||
newcam_pos[1] = newcam_pos_target[1]+lengthdir_y(newcam_distance,newcam_tilt+gLakituState.shakeMagnitude[0])+floorY;
|
||||
if ((newcam_modeflags & NC_FLAG_FOCUSX) && (newcam_modeflags & NC_FLAG_FOCUSY) && (newcam_modeflags & NC_FLAG_FOCUSZ))
|
||||
newcam_set_pan();
|
||||
//Set where the camera wants to be looking at. This is almost always the place it's based off, too.
|
||||
if (newcam_modeflags & NC_FLAG_FOCUSX)
|
||||
newcam_lookat[0] = newcam_pos_target[0]-newcam_pan_x;
|
||||
if (newcam_modeflags & NC_FLAG_FOCUSY)
|
||||
newcam_lookat[1] = newcam_pos_target[1]+floorY2;
|
||||
if (newcam_modeflags & NC_FLAG_FOCUSZ)
|
||||
newcam_lookat[2] = newcam_pos_target[2]-newcam_pan_z;
|
||||
|
||||
if (newcam_modeflags & NC_FLAG_COLLISION)
|
||||
newcam_collision();
|
||||
|
||||
}
|
||||
|
||||
//Nested if's baybeeeee
|
||||
static void newcam_find_fixed(void)
|
||||
{
|
||||
u8 i = 0;
|
||||
newcam_mode = newcam_intendedmode;
|
||||
newcam_modeflags = newcam_mode;
|
||||
for (i = 0; i < sizeof(newcam_fixedcam); i++)
|
||||
{
|
||||
if (newcam_fixedcam[i].newcam_hard_levelID == gCurrLevelNum && newcam_fixedcam[i].newcam_hard_areaID == gCurrAreaIndex)
|
||||
{//I didn't wanna just obliterate the horizontal plane of the IDE with a beefy if statement, besides, I think this runs slightly better anyway?
|
||||
if (newcam_pos_target[0] > newcam_fixedcam[i].newcam_hard_X1)
|
||||
if (newcam_pos_target[0] < newcam_fixedcam[i].newcam_hard_X2)
|
||||
if (newcam_pos_target[1] > newcam_fixedcam[i].newcam_hard_Y1)
|
||||
if (newcam_pos_target[1] < newcam_fixedcam[i].newcam_hard_Y2)
|
||||
if (newcam_pos_target[2] > newcam_fixedcam[i].newcam_hard_Z1)
|
||||
if (newcam_pos_target[2] < newcam_fixedcam[i].newcam_hard_Z2)
|
||||
{
|
||||
if (newcam_fixedcam[i].newcam_hard_permaswap)
|
||||
newcam_intendedmode = newcam_fixedcam[i].newcam_hard_modeset;
|
||||
newcam_mode = newcam_fixedcam[i].newcam_hard_modeset;
|
||||
newcam_modeflags = newcam_mode;
|
||||
|
||||
if (newcam_fixedcam[i].newcam_hard_camX != 32767 && !(newcam_modeflags & NC_FLAG_POSX))
|
||||
newcam_pos[0] = newcam_fixedcam[i].newcam_hard_camX;
|
||||
if (newcam_fixedcam[i].newcam_hard_camY != 32767 && !(newcam_modeflags & NC_FLAG_POSY))
|
||||
newcam_pos[1] = newcam_fixedcam[i].newcam_hard_camY;
|
||||
if (newcam_fixedcam[i].newcam_hard_camZ != 32767 && !(newcam_modeflags & NC_FLAG_POSZ))
|
||||
newcam_pos[2] = newcam_fixedcam[i].newcam_hard_camZ;
|
||||
|
||||
if (newcam_fixedcam[i].newcam_hard_lookX != 32767 && !(newcam_modeflags & NC_FLAG_FOCUSX))
|
||||
newcam_lookat[0] = newcam_fixedcam[i].newcam_hard_lookX;
|
||||
if (newcam_fixedcam[i].newcam_hard_lookY != 32767 && !(newcam_modeflags & NC_FLAG_FOCUSY))
|
||||
newcam_lookat[1] = newcam_fixedcam[i].newcam_hard_lookY;
|
||||
if (newcam_fixedcam[i].newcam_hard_lookZ != 32767 && !(newcam_modeflags & NC_FLAG_FOCUSZ))
|
||||
newcam_lookat[2] = newcam_fixedcam[i].newcam_hard_lookZ;
|
||||
|
||||
newcam_yaw = atan2s(newcam_pos[0]-newcam_pos_target[0],newcam_pos[2]-newcam_pos_target[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void newcam_apply_values(struct Camera *c)
|
||||
{
|
||||
|
||||
c->pos[0] = newcam_pos[0];
|
||||
c->pos[1] = newcam_pos[1];
|
||||
c->pos[2] = newcam_pos[2];
|
||||
|
||||
c->focus[0] = newcam_lookat[0];
|
||||
c->focus[1] = newcam_lookat[1];
|
||||
c->focus[2] = newcam_lookat[2];
|
||||
|
||||
gLakituState.pos[0] = newcam_pos[0];
|
||||
gLakituState.pos[1] = newcam_pos[1];
|
||||
gLakituState.pos[2] = newcam_pos[2];
|
||||
|
||||
gLakituState.focus[0] = newcam_lookat[0];
|
||||
gLakituState.focus[1] = newcam_lookat[1];
|
||||
gLakituState.focus[2] = newcam_lookat[2];
|
||||
|
||||
c->yaw = -newcam_yaw+0x4000;
|
||||
gLakituState.yaw = -newcam_yaw+0x4000;
|
||||
|
||||
//Adds support for wing mario tower
|
||||
if (gMarioState->floor->type == SURFACE_LOOK_UP_WARP) {
|
||||
if (save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 0x18) >= 10) {
|
||||
if (newcam_tilt < -8000 && gMarioState->forwardVel == 0) {
|
||||
level_trigger_warp(gMarioState, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//The ingame cutscene system is such a spaghetti mess I actually have to resort to something as stupid as this to cover every base.
|
||||
void newcam_apply_outside_values(struct Camera *c, u8 bit)
|
||||
{
|
||||
if (newcam_modeflags == NC_FLAG_XTURN)
|
||||
{
|
||||
if (bit)
|
||||
newcam_yaw = -gMarioState->faceAngle[1]-0x4000;
|
||||
else
|
||||
newcam_yaw = -c->yaw+0x4000;
|
||||
}
|
||||
}
|
||||
|
||||
//Main loop.
|
||||
void newcam_loop(struct Camera *c)
|
||||
{
|
||||
newcam_rotate_button();
|
||||
newcam_zoom_button();
|
||||
newcam_position_cam();
|
||||
newcam_find_fixed();
|
||||
if (gMarioObject)
|
||||
newcam_apply_values(c);
|
||||
|
||||
//Just some visual information on the values of the camera. utilises ifdef because it's better at runtime.
|
||||
#ifdef NEWCAM_DEBUG
|
||||
newcam_diagnostics();
|
||||
#endif // NEWCAM_DEBUG
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Displays a box.
|
||||
void newcam_display_box(s16 x1, s16 y1, s16 x2, s16 y2, u8 r, u8 g, u8 b)
|
||||
{
|
||||
gDPPipeSync(gDisplayListHead++);
|
||||
gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
|
||||
gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
|
||||
gDPSetFillColor(gDisplayListHead++, GPACK_RGBA5551(r, g, b, 255));
|
||||
gDPFillRectangle(gDisplayListHead++, x1, y1, x2 - 1, y2 - 1);
|
||||
gDPPipeSync(gDisplayListHead++);
|
||||
gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE);
|
||||
}
|
||||
|
||||
//I actually took the time to redo this, properly. Lmao. Please don't bully me over this anymore :(
|
||||
void newcam_change_setting(u8 toggle)
|
||||
{
|
||||
switch (newcam_option_selection)
|
||||
{
|
||||
case 0:
|
||||
newcam_analogue ^= 1;
|
||||
break;
|
||||
case 1:
|
||||
newcam_mouse ^= 1;
|
||||
break;
|
||||
case 2:
|
||||
if (newcam_sensitivityX > 10 && newcam_sensitivityX < 250)
|
||||
newcam_sensitivityX += toggle;
|
||||
break;
|
||||
case 3:
|
||||
if (newcam_sensitivityY > 10 && newcam_sensitivityY < 250)
|
||||
newcam_sensitivityY += toggle;
|
||||
break;
|
||||
case 4:
|
||||
newcam_invertX ^= 1;
|
||||
break;
|
||||
case 5:
|
||||
newcam_invertY ^= 1;
|
||||
break;
|
||||
case 6:
|
||||
if (newcam_aggression > 0 && newcam_aggression < 100)
|
||||
newcam_aggression += toggle;
|
||||
break;
|
||||
case 7:
|
||||
if (newcam_panlevel > 0 && newcam_panlevel < 100)
|
||||
newcam_panlevel += toggle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void newcam_text(s16 x, s16 y, u8 str[], u8 col)
|
||||
{
|
||||
u8 textX;
|
||||
textX = get_str_x_pos_from_center(x,str,10.0f);
|
||||
gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 255);
|
||||
print_generic_string(textX+1,y-1,str);
|
||||
if (col != 0)
|
||||
{
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 32, 32, 255);
|
||||
}
|
||||
print_generic_string(textX,y,str);
|
||||
}
|
||||
|
||||
//Options menu
|
||||
void newcam_display_options()
|
||||
{
|
||||
u8 i = 0;
|
||||
u8 newstring[32];
|
||||
s16 scroll;
|
||||
s16 scrollpos;
|
||||
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin);
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255);
|
||||
print_hud_lut_string(HUD_LUT_GLOBAL, 118, 40, newcam_strings[2]);
|
||||
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end);
|
||||
|
||||
if (newcam_total>4)
|
||||
{
|
||||
newcam_display_box(272,90,280,208,0x80,0x80,0x80);
|
||||
scrollpos = (54)*((f32)newcam_option_scroll/(newcam_total-4));
|
||||
newcam_display_box(272,90+scrollpos,280,154+scrollpos,0xFF,0xFF,0xFF);
|
||||
}
|
||||
|
||||
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 80, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
for (i = 0; i < newcam_total; i++)
|
||||
{
|
||||
scroll = 140-(32*i)+(newcam_option_scroll*32);
|
||||
if (scroll <= 140 && scroll > 32)
|
||||
{
|
||||
newcam_text(160,scroll,newcam_options[i],newcam_option_selection-i);
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
newcam_text(160,scroll-12,newcam_flags[newcam_analogue],newcam_option_selection-i);
|
||||
break;
|
||||
case 1:
|
||||
newcam_text(160,scroll-12,newcam_flags[newcam_mouse],newcam_option_selection-i);
|
||||
break;
|
||||
case 2:
|
||||
int_to_str(newcam_sensitivityX,newstring);
|
||||
newcam_text(160,scroll-12,newstring,newcam_option_selection-i);
|
||||
break;
|
||||
case 3:
|
||||
int_to_str(newcam_sensitivityY,newstring);
|
||||
newcam_text(160,scroll-12,newstring,newcam_option_selection-i);
|
||||
break;
|
||||
case 4:
|
||||
newcam_text(160,scroll-12,newcam_flags[newcam_invertX],newcam_option_selection-i);
|
||||
break;
|
||||
case 5:
|
||||
newcam_text(160,scroll-12,newcam_flags[newcam_invertY],newcam_option_selection-i);
|
||||
break;
|
||||
case 6:
|
||||
int_to_str(newcam_aggression,newstring);
|
||||
newcam_text(160,scroll-12,newstring,newcam_option_selection-i);
|
||||
break;
|
||||
case 7:
|
||||
int_to_str(newcam_panlevel,newstring);
|
||||
newcam_text(160,scroll-12,newstring,newcam_option_selection-i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255);
|
||||
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin);
|
||||
print_hud_lut_string(HUD_LUT_GLOBAL, 80, 90+(32*(newcam_option_selection-newcam_option_scroll)), newcam_strings[3]);
|
||||
print_hud_lut_string(HUD_LUT_GLOBAL, 224, 90+(32*(newcam_option_selection-newcam_option_scroll)), newcam_strings[3]);
|
||||
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end);
|
||||
}
|
||||
|
||||
//This has been separated for interesting reasons. Don't question it.
|
||||
void newcam_render_option_text(void)
|
||||
{
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
|
||||
newcam_text(278,212,newcam_strings[newcam_option_open],1);
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
||||
}
|
||||
|
||||
void newcam_check_pause_buttons()
|
||||
{
|
||||
if (gPlayer1Controller->buttonPressed & R_TRIG)
|
||||
{
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs);
|
||||
#endif
|
||||
if (newcam_option_open == 0)
|
||||
newcam_option_open = 1;
|
||||
else
|
||||
{
|
||||
newcam_option_open = 0;
|
||||
save_file_set_setting();
|
||||
}
|
||||
}
|
||||
|
||||
if (newcam_option_open)
|
||||
{
|
||||
if (ABS(gPlayer1Controller->stickY) > 60)
|
||||
{
|
||||
newcam_option_timer -= 1;
|
||||
if (newcam_option_timer <= 0)
|
||||
{
|
||||
switch (newcam_option_index)
|
||||
{
|
||||
case 0: newcam_option_index++; newcam_option_timer += 10; break;
|
||||
default: newcam_option_timer += 5; break;
|
||||
}
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs);
|
||||
#endif
|
||||
if (gPlayer1Controller->stickY >= 60)
|
||||
{
|
||||
newcam_option_selection--;
|
||||
if (newcam_option_selection < 0)
|
||||
newcam_option_selection = newcam_total-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
newcam_option_selection++;
|
||||
if (newcam_option_selection >= newcam_total)
|
||||
newcam_option_selection = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (ABS(gPlayer1Controller->stickX) > 60)
|
||||
{
|
||||
newcam_option_timer -= 1;
|
||||
if (newcam_option_timer <= 0)
|
||||
{
|
||||
switch (newcam_option_index)
|
||||
{
|
||||
case 0: newcam_option_index++; newcam_option_timer += 10; break;
|
||||
default: newcam_option_timer += 5; break;
|
||||
}
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs);
|
||||
#endif
|
||||
if (gPlayer1Controller->stickX >= 60)
|
||||
newcam_change_setting(1);
|
||||
else
|
||||
newcam_change_setting(-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newcam_option_timer = 0;
|
||||
newcam_option_index = 0;
|
||||
}
|
||||
|
||||
while (newcam_option_scroll - newcam_option_selection < -3 && newcam_option_selection > newcam_option_scroll)
|
||||
newcam_option_scroll +=1;
|
||||
while (newcam_option_scroll + newcam_option_selection > 0 && newcam_option_selection < newcam_option_scroll)
|
||||
newcam_option_scroll -=1;
|
||||
}
|
||||
}
|
|
@ -701,6 +701,10 @@ f32 calc_y_to_curr_floor(f32 *posOff, f32 posMul, f32 posBound, f32 *focOff, f32
|
|||
*focOff = -focBound;
|
||||
}
|
||||
}
|
||||
//Compiler gets mad if I put this any further above. thanks refresh 7
|
||||
#ifdef BETTERCAMERA
|
||||
#include "bettercamera.inc.h"
|
||||
#endif
|
||||
|
||||
void focus_on_mario(Vec3f focus, Vec3f pos, f32 posYOff, f32 focYOff, f32 dist, s16 pitch, s16 yaw) {
|
||||
Vec3f marioPos;
|
||||
|
@ -2853,6 +2857,10 @@ void set_camera_mode(struct Camera *c, s16 mode, s16 frames) {
|
|||
struct LinearTransitionPoint *start = &sModeInfo.transitionStart;
|
||||
struct LinearTransitionPoint *end = &sModeInfo.transitionEnd;
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
if (mode != CAMERA_MODE_NEWCAM && gLakituState.mode != CAMERA_MODE_NEWCAM)
|
||||
{
|
||||
#endif
|
||||
if (mode == CAMERA_MODE_WATER_SURFACE && gCurrLevelArea == AREA_TTM_OUTSIDE) {
|
||||
} else {
|
||||
// Clear movement flags that would affect the transition
|
||||
|
@ -2896,6 +2904,9 @@ void set_camera_mode(struct Camera *c, s16 mode, s16 frames) {
|
|||
vec3f_get_dist_and_angle(start->focus, start->pos, &start->dist, &start->pitch, &start->yaw);
|
||||
vec3f_get_dist_and_angle(end->focus, end->pos, &end->dist, &end->pitch, &end->yaw);
|
||||
}
|
||||
#ifdef BETTERCAMERA
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2980,7 +2991,12 @@ void update_lakitu(struct Camera *c) {
|
|||
gLakituState.roll += sHandheldShakeRoll;
|
||||
gLakituState.roll += gLakituState.keyDanceRoll;
|
||||
|
||||
if (c->mode != CAMERA_MODE_C_UP && c->cutscene == 0) {
|
||||
if (c->mode != CAMERA_MODE_C_UP && c->cutscene == 0
|
||||
#ifdef BETTERCAMERA
|
||||
&& c->mode != CAMERA_MODE_NEWCAM
|
||||
#endif
|
||||
)
|
||||
{
|
||||
gCheckingSurfaceCollisionsForCamera = TRUE;
|
||||
distToFloor = find_floor(gLakituState.pos[0],
|
||||
gLakituState.pos[1] + 20.0f,
|
||||
|
@ -3013,7 +3029,11 @@ void update_camera(struct Camera *c) {
|
|||
update_camera_hud_status(c);
|
||||
if (c->cutscene == 0) {
|
||||
// Only process R_TRIG if 'fixed' is not selected in the menu
|
||||
if (cam_select_alt_mode(0) == CAM_SELECTION_MARIO) {
|
||||
if (cam_select_alt_mode(0) == CAM_SELECTION_MARIO
|
||||
#ifdef BETTERCAMERA
|
||||
&& c->mode != CAMERA_MODE_NEWCAM
|
||||
#endif
|
||||
) {
|
||||
if (gPlayer1Controller->buttonPressed & R_TRIG) {
|
||||
if (set_cam_angle(0) == CAM_ANGLE_LAKITU) {
|
||||
set_cam_angle(CAM_ANGLE_MARIO);
|
||||
|
@ -3051,10 +3071,16 @@ void update_camera(struct Camera *c) {
|
|||
c->mode = gLakituState.mode;
|
||||
c->defMode = gLakituState.defMode;
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
if (c->mode != CAMERA_MODE_NEWCAM)
|
||||
{
|
||||
#endif
|
||||
camera_course_processing(c);
|
||||
stub_camera_3(c);
|
||||
sCButtonsPressed = find_c_buttons_pressed(sCButtonsPressed, gPlayer1Controller->buttonPressed,
|
||||
gPlayer1Controller->buttonDown);
|
||||
sCButtonsPressed = find_c_buttons_pressed(sCButtonsPressed, gPlayer1Controller->buttonPressed,gPlayer1Controller->buttonDown);
|
||||
#ifdef BETTERCAMERA
|
||||
}
|
||||
#endif
|
||||
|
||||
if (c->cutscene != 0) {
|
||||
sYawSpeed = 0;
|
||||
|
@ -3092,6 +3118,12 @@ void update_camera(struct Camera *c) {
|
|||
mode_cannon_camera(c);
|
||||
break;
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
case CAMERA_MODE_NEWCAM:
|
||||
newcam_loop(c);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
mode_mario_camera(c);
|
||||
}
|
||||
|
@ -3151,6 +3183,12 @@ void update_camera(struct Camera *c) {
|
|||
case CAMERA_MODE_SPIRAL_STAIRS:
|
||||
mode_spiral_stairs_camera(c);
|
||||
break;
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
case CAMERA_MODE_NEWCAM:
|
||||
newcam_loop(c);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3426,6 +3464,15 @@ void init_camera(struct Camera *c) {
|
|||
gLakituState.nextYaw = gLakituState.yaw;
|
||||
c->yaw = gLakituState.yaw;
|
||||
c->nextYaw = gLakituState.yaw;
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
if (newcam_active == 1)
|
||||
{
|
||||
gLakituState.mode = CAMERA_MODE_NEWCAM;
|
||||
gLakituState.defMode = CAMERA_MODE_NEWCAM;
|
||||
newcam_init(c, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5514,6 +5561,10 @@ void set_camera_mode_8_directions(struct Camera *c) {
|
|||
s8DirModeBaseYaw = 0;
|
||||
s8DirModeYawOffset = 0;
|
||||
}
|
||||
#ifdef BETTERCAMERA
|
||||
if (newcam_active == 1)
|
||||
c->mode = CAMERA_MODE_NEWCAM;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5532,6 +5583,10 @@ void set_camera_mode_close_cam(u8 *mode) {
|
|||
sStatusFlags &= ~CAM_FLAG_SMOOTH_MOVEMENT;
|
||||
*mode = CAMERA_MODE_CLOSE;
|
||||
}
|
||||
#ifdef BETTERCAMERA
|
||||
if (newcam_active == 1)
|
||||
*mode = CAMERA_MODE_NEWCAM;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5556,6 +5611,10 @@ void set_camera_mode_radial(struct Camera *c, s16 transitionTime) {
|
|||
}
|
||||
sModeOffsetYaw = 0;
|
||||
}
|
||||
#ifdef BETTERCAMERA
|
||||
if (newcam_active == 1)
|
||||
c->mode = CAMERA_MODE_NEWCAM;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6934,6 +6993,9 @@ s16 cutscene_object(u8 cutscene, struct Object *o) {
|
|||
void update_camera_yaw(struct Camera *c) {
|
||||
c->nextYaw = calculate_yaw(c->focus, c->pos);
|
||||
c->yaw = c->nextYaw;
|
||||
#ifdef BETTERCAMERA
|
||||
newcam_apply_outside_values(c,0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cutscene_reset_spline(void) {
|
||||
|
@ -9202,7 +9264,14 @@ BAD_RETURN(s32) cutscene_non_painting_end(struct Camera *c) {
|
|||
|
||||
if (c->defMode == CAMERA_MODE_CLOSE) {
|
||||
c->mode = CAMERA_MODE_CLOSE;
|
||||
} else {
|
||||
} else
|
||||
#ifdef BETTERCAMERA
|
||||
if (c->defMode == CAMERA_MODE_NEWCAM) {
|
||||
c->mode = CAMERA_MODE_NEWCAM;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
c->mode = CAMERA_MODE_FREE_ROAM;
|
||||
}
|
||||
|
||||
|
@ -9958,6 +10027,9 @@ BAD_RETURN(s32) cutscene_sliding_doors_follow_mario(struct Camera *c) {
|
|||
BAD_RETURN(s32) cutscene_sliding_doors_open(struct Camera *c) {
|
||||
UNUSED u32 pad[2];
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
newcam_apply_outside_values(c,1);
|
||||
#endif
|
||||
reset_pan_distance(c);
|
||||
cutscene_event(cutscene_sliding_doors_open_start, c, 0, 8);
|
||||
cutscene_event(cutscene_sliding_doors_open_set_cvars, c, 8, 8);
|
||||
|
@ -10154,7 +10226,12 @@ BAD_RETURN(s32) cutscene_unused_exit_focus_mario(struct Camera *c) {
|
|||
* Give control back to the player.
|
||||
*/
|
||||
BAD_RETURN(s32) cutscene_exit_painting_end(struct Camera *c) {
|
||||
c->mode = CAMERA_MODE_CLOSE;
|
||||
#ifdef BETTERCAMERA
|
||||
if (newcam_active == 1)
|
||||
c->mode = CAMERA_MODE_NEWCAM;
|
||||
else
|
||||
#endif
|
||||
c->mode = CAMERA_MODE_CLOSE;
|
||||
c->cutscene = 0;
|
||||
gCutsceneTimer = CUTSCENE_STOP;
|
||||
sStatusFlags |= CAM_FLAG_SMOOTH_MOVEMENT;
|
||||
|
@ -10314,11 +10391,24 @@ BAD_RETURN(s32) cutscene_door_follow_mario(struct Camera *c) {
|
|||
* Ends the door cutscene. Sets the camera mode to close mode unless the default is free roam.
|
||||
*/
|
||||
BAD_RETURN(s32) cutscene_door_end(struct Camera *c) {
|
||||
#ifndef BETTERCAMERA
|
||||
if (c->defMode == CAMERA_MODE_FREE_ROAM) {
|
||||
c->mode = CAMERA_MODE_FREE_ROAM;
|
||||
} else {
|
||||
c->mode = CAMERA_MODE_CLOSE;
|
||||
}
|
||||
#else
|
||||
if (c->defMode == CAMERA_MODE_CLOSE) {
|
||||
c->mode = CAMERA_MODE_CLOSE;
|
||||
} else
|
||||
if (c->defMode == CAMERA_MODE_NEWCAM) {
|
||||
c->mode = CAMERA_MODE_NEWCAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->mode = CAMERA_MODE_FREE_ROAM;
|
||||
}
|
||||
#endif
|
||||
|
||||
c->cutscene = 0;
|
||||
gCutsceneTimer = CUTSCENE_STOP;
|
||||
|
|
|
@ -110,6 +110,9 @@
|
|||
#define CAMERA_MODE_8_DIRECTIONS 0x0E // AKA Parallel Camera, Bowser Courses & Rainbow Road
|
||||
#define CAMERA_MODE_FREE_ROAM 0x10
|
||||
#define CAMERA_MODE_SPIRAL_STAIRS 0x11
|
||||
#ifdef BETTERCAMERA
|
||||
#define CAMERA_MODE_NEWCAM 0x12
|
||||
#endif
|
||||
|
||||
#define CAM_MOVE_RETURN_TO_MIDDLE 0x0001
|
||||
#define CAM_MOVE_ZOOMED_OUT 0x0002
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include "main_entry.h"
|
||||
#include "thread6.h"
|
||||
#include <prevent_bss_reordering.h>
|
||||
#ifdef BETTERCAMERA
|
||||
#include "bettercamera.h"
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
@ -58,6 +61,8 @@ struct DemoInput *gCurrDemoInput = NULL; // demo input sequence
|
|||
u16 gDemoInputListID = 0;
|
||||
struct DemoInput gRecordedDemoInput = { 0 }; // possibly removed in EU. TODO: Check
|
||||
|
||||
extern int c_rightx;
|
||||
extern int c_righty;
|
||||
/**
|
||||
* Initializes the Reality Display Processor (RDP).
|
||||
* This function initializes settings such as texture filtering mode,
|
||||
|
@ -225,7 +230,7 @@ void create_task_structure(void) {
|
|||
gGfxSPTask->task.t.dram_stack_size = SP_DRAM_STACK_SIZE8;
|
||||
#ifdef VERSION_EU
|
||||
// terrible hack
|
||||
gGfxSPTask->task.t.output_buff =
|
||||
gGfxSPTask->task.t.output_buff =
|
||||
(u64 *)((u8 *) gGfxSPTaskOutputBuffer - 0x670 + 0x280);
|
||||
gGfxSPTask->task.t.output_buff_size =
|
||||
(u64 *)((u8 *) gGfxSPTaskOutputBuffer+ 0x280 + 0x17790);
|
||||
|
@ -306,7 +311,7 @@ void rendering_init(void) {
|
|||
}
|
||||
|
||||
void config_gfx_pool(void) {
|
||||
gGfxPool = &gGfxPools[gGlobalTimer % 2];
|
||||
gGfxPool = &gGfxPools[gGlobalTimer % GFX_NUM_POOLS];
|
||||
set_segment_base_addr(1, gGfxPool->buffer);
|
||||
gGfxSPTask = &gGfxPool->spTask;
|
||||
gDisplayListHead = gGfxPool->buffer;
|
||||
|
@ -482,36 +487,72 @@ void read_controller_inputs(void) {
|
|||
if (gControllerBits) {
|
||||
osRecvMesg(&gSIEventMesgQueue, &D_80339BEC, OS_MESG_BLOCK);
|
||||
osContGetReadData(&gControllerPads[0]);
|
||||
#ifdef VERSION_SH
|
||||
release_rumble_pak_control();
|
||||
#endif
|
||||
}
|
||||
run_demo_inputs();
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
#ifdef BETTERCAMERA
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
struct Controller *controller = &gControllers[i];
|
||||
|
||||
// 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;
|
||||
controller->buttonPressed = controller->controllerData->button
|
||||
& (controller->controllerData->button ^ controller->buttonDown);
|
||||
// 0.5x A presses are a good meme
|
||||
controller->buttonDown = controller->controllerData->button;
|
||||
adjust_analog_stick(controller);
|
||||
} else // otherwise, if the controllerData is NULL, 0 out all of the inputs.
|
||||
if (i==1) // This is related to the analog camera control, using a P2 controller hack. P2 will no longer be correctly available for multiplayer.
|
||||
{
|
||||
controller->rawStickX = 0;
|
||||
controller->rawStickY = 0;
|
||||
controller->buttonPressed = 0;
|
||||
controller->buttonDown = 0;
|
||||
controller->stickX = 0;
|
||||
controller->stickY = 0;
|
||||
controller->stickMag = 0;
|
||||
controller->rawStickX = c_rightx;
|
||||
controller->rawStickY = c_righty;
|
||||
controller->stickX = c_rightx;
|
||||
controller->stickY = c_righty;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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;
|
||||
controller->buttonPressed = controller->controllerData->button
|
||||
& (controller->controllerData->button ^ controller->buttonDown);
|
||||
// 0.5x A presses are a good meme
|
||||
controller->buttonDown = controller->controllerData->button;
|
||||
adjust_analog_stick(controller);
|
||||
} else // otherwise, if the controllerData is NULL, 0 out all of the inputs.
|
||||
{
|
||||
controller->rawStickX = 0;
|
||||
controller->rawStickY = 0;
|
||||
controller->buttonPressed = 0;
|
||||
controller->buttonDown = 0;
|
||||
controller->stickX = 0;
|
||||
controller->stickY = 0;
|
||||
controller->stickMag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#else
|
||||
for (i = 0; i < 2; i++) {
|
||||
struct Controller *controller = &gControllers[i];
|
||||
|
||||
// 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;
|
||||
controller->buttonPressed = controller->controllerData->button
|
||||
& (controller->controllerData->button ^ controller->buttonDown);
|
||||
// 0.5x A presses are a good meme
|
||||
controller->buttonDown = controller->controllerData->button;
|
||||
adjust_analog_stick(controller);
|
||||
} else // otherwise, if the controllerData is NULL, 0 out all of the inputs.
|
||||
{
|
||||
controller->rawStickX = 0;
|
||||
controller->rawStickY = 0;
|
||||
controller->buttonPressed = 0;
|
||||
controller->buttonDown = 0;
|
||||
controller->stickX = 0;
|
||||
controller->stickY = 0;
|
||||
controller->stickMag = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// For some reason, player 1's inputs are copied to player 3's port. This
|
||||
// potentially may have been a way the developers "recorded" the inputs
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include "print.h"
|
||||
#include "engine/math_util.h"
|
||||
#include "course_table.h"
|
||||
#ifdef BETTERCAMERA
|
||||
#include "bettercamera.h"
|
||||
#endif
|
||||
|
||||
extern Gfx *gDisplayListHead;
|
||||
extern s16 gCurrCourseNum;
|
||||
|
@ -693,7 +696,7 @@ void print_credits_string(s16 x, s16 y, const u8 *str) {
|
|||
gDPSetTile(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0,
|
||||
G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOLOD, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOLOD);
|
||||
gDPTileSync(gDisplayListHead++);
|
||||
gDPSetTile(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 2, 0, G_TX_RENDERTILE, 0,
|
||||
gDPSetTile(gDisplayListHead++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 2, 0, G_TX_RENDERTILE, 0,
|
||||
G_TX_CLAMP, 3, G_TX_NOLOD, G_TX_CLAMP, 3, G_TX_NOLOD);
|
||||
gDPSetTileSize(gDisplayListHead++, G_TX_RENDERTILE, 0, 0, (8 - 1) << G_TEXTURE_IMAGE_FRAC, (8 - 1) << G_TEXTURE_IMAGE_FRAC);
|
||||
|
||||
|
@ -2615,7 +2618,10 @@ s16 render_pause_courses_and_castle(void) {
|
|||
#ifdef VERSION_EU
|
||||
gInGameLanguage = eu_get_language();
|
||||
#endif
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
if (newcam_option_open == 0)
|
||||
{
|
||||
#endif
|
||||
switch (gDialogBoxState) {
|
||||
case DIALOG_STATE_OPENING:
|
||||
gDialogLineNum = 1;
|
||||
|
@ -2691,6 +2697,16 @@ s16 render_pause_courses_and_castle(void) {
|
|||
if (gDialogTextAlpha < 250) {
|
||||
gDialogTextAlpha += 25;
|
||||
}
|
||||
#ifdef BETTERCAMERA
|
||||
}
|
||||
else
|
||||
{
|
||||
shade_screen();
|
||||
newcam_display_options();
|
||||
}
|
||||
newcam_check_pause_buttons();
|
||||
newcam_render_option_text();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#include "engine/surface_collision.h"
|
||||
#include "level_table.h"
|
||||
#include "thread6.h"
|
||||
#ifdef BETTERCAMERA
|
||||
#include "bettercamera.h"
|
||||
#endif
|
||||
|
||||
u32 unused80339F10;
|
||||
s8 filler80339F1C[20];
|
||||
|
@ -350,7 +353,7 @@ void play_mario_heavy_landing_sound_once(struct MarioState *m, u32 soundBits) {
|
|||
void play_mario_sound(struct MarioState *m, s32 actionSound, s32 marioSound) {
|
||||
if (actionSound == SOUND_ACTION_TERRAIN_JUMP) {
|
||||
play_mario_action_sound(
|
||||
m, (m->flags & MARIO_METAL_CAP) ? (s32)SOUND_ACTION_METAL_JUMP
|
||||
m, (m->flags & MARIO_METAL_CAP) ? (s32)SOUND_ACTION_METAL_JUMP
|
||||
: (s32)SOUND_ACTION_TERRAIN_JUMP, 1);
|
||||
} else {
|
||||
play_sound_if_no_flag(m, actionSound, MARIO_ACTION_SOUND_PLAYED);
|
||||
|
@ -1306,7 +1309,14 @@ void update_mario_joystick_inputs(struct MarioState *m) {
|
|||
}
|
||||
|
||||
if (m->intendedMag > 0.0f) {
|
||||
#ifndef BETTERCAMERA
|
||||
m->intendedYaw = atan2s(-controller->stickY, controller->stickX) + m->area->camera->yaw;
|
||||
#else
|
||||
if (gLakituState.mode != CAMERA_MODE_NEWCAM)
|
||||
m->intendedYaw = atan2s(-controller->stickY, controller->stickX) + m->area->camera->yaw;
|
||||
else
|
||||
m->intendedYaw = atan2s(-controller->stickY, controller->stickX)-newcam_yaw+0x4000;
|
||||
#endif
|
||||
m->input |= INPUT_NONZERO_ANALOG;
|
||||
} else {
|
||||
m->intendedYaw = m->faceAngle[1];
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#include "audio/external.h"
|
||||
#include "engine/graph_node.h"
|
||||
#include "thread6.h"
|
||||
#ifdef BETTERCAMERA
|
||||
#include "bettercamera.h"
|
||||
#endif
|
||||
|
||||
void play_flip_sounds(struct MarioState *m, s16 frame1, s16 frame2, s16 frame3) {
|
||||
s32 animFrame = m->marioObj->header.gfx.unk38.animFrame;
|
||||
|
@ -455,8 +458,8 @@ s32 act_jump(struct MarioState *m) {
|
|||
}
|
||||
|
||||
s32 act_double_jump(struct MarioState *m) {
|
||||
s32 animation = (m->vel[1] >= 0.0f)
|
||||
? MARIO_ANIM_DOUBLE_JUMP_RISE
|
||||
s32 animation = (m->vel[1] >= 0.0f)
|
||||
? MARIO_ANIM_DOUBLE_JUMP_RISE
|
||||
: MARIO_ANIM_DOUBLE_JUMP_FALL;
|
||||
|
||||
if (check_kick_or_dive_in_air(m)) {
|
||||
|
@ -1676,7 +1679,17 @@ s32 act_shot_from_cannon(struct MarioState *m) {
|
|||
case AIR_STEP_LANDED:
|
||||
set_mario_action(m, ACT_DIVE_SLIDE, 0);
|
||||
m->faceAngle[0] = 0;
|
||||
#ifndef BETTERCAMERA
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
#else
|
||||
if (newcam_active == 0)
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
else
|
||||
{
|
||||
m->area->camera->mode = CAMERA_MODE_NEWCAM;
|
||||
gLakituState.mode = CAMERA_MODE_NEWCAM;
|
||||
}
|
||||
#endif
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 80);
|
||||
#endif
|
||||
|
@ -1692,7 +1705,17 @@ s32 act_shot_from_cannon(struct MarioState *m) {
|
|||
|
||||
m->particleFlags |= PARTICLE_VERTICAL_STAR;
|
||||
set_mario_action(m, ACT_BACKWARD_AIR_KB, 0);
|
||||
#ifndef BETTERCAMERA
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
#else
|
||||
if (newcam_active == 0)
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
else
|
||||
{
|
||||
m->area->camera->mode = CAMERA_MODE_NEWCAM;
|
||||
gLakituState.mode = CAMERA_MODE_NEWCAM;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case AIR_STEP_HIT_LAVA_WALL:
|
||||
|
@ -1722,20 +1745,50 @@ s32 act_flying(struct MarioState *m) {
|
|||
|
||||
if (m->input & INPUT_Z_PRESSED) {
|
||||
if (m->area->camera->mode == CAMERA_MODE_BEHIND_MARIO) {
|
||||
#ifndef BETTERCAMERA
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
#else
|
||||
if (newcam_active == 0)
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
else
|
||||
{
|
||||
m->area->camera->mode = CAMERA_MODE_NEWCAM;
|
||||
gLakituState.mode = CAMERA_MODE_NEWCAM;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return set_mario_action(m, ACT_GROUND_POUND, 1);
|
||||
}
|
||||
|
||||
if (!(m->flags & MARIO_WING_CAP)) {
|
||||
if (m->area->camera->mode == CAMERA_MODE_BEHIND_MARIO) {
|
||||
#ifndef BETTERCAMERA
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
#else
|
||||
if (newcam_active == 0)
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
else
|
||||
{
|
||||
m->area->camera->mode = CAMERA_MODE_NEWCAM;
|
||||
gLakituState.mode = CAMERA_MODE_NEWCAM;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return set_mario_action(m, ACT_FREEFALL, 0);
|
||||
}
|
||||
|
||||
if (m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) {
|
||||
#ifndef BETTERCAMERA
|
||||
set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1);
|
||||
#else
|
||||
if (newcam_active == 0)
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
else
|
||||
{
|
||||
m->area->camera->mode = CAMERA_MODE_NEWCAM;
|
||||
gLakituState.mode = CAMERA_MODE_NEWCAM;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (m->actionState == 0) {
|
||||
|
@ -1775,7 +1828,17 @@ s32 act_flying(struct MarioState *m) {
|
|||
set_anim_to_frame(m, 7);
|
||||
|
||||
m->faceAngle[0] = 0;
|
||||
#ifndef BETTERCAMERA
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
#else
|
||||
if (newcam_active == 0)
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
else
|
||||
{
|
||||
m->area->camera->mode = CAMERA_MODE_NEWCAM;
|
||||
gLakituState.mode = CAMERA_MODE_NEWCAM;
|
||||
}
|
||||
#endif
|
||||
#ifdef VERSION_SH
|
||||
queue_rumble_data(5, 80);
|
||||
#endif
|
||||
|
@ -1796,7 +1859,17 @@ s32 act_flying(struct MarioState *m) {
|
|||
|
||||
m->particleFlags |= PARTICLE_VERTICAL_STAR;
|
||||
set_mario_action(m, ACT_BACKWARD_AIR_KB, 0);
|
||||
#ifndef BETTERCAMERA
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
#else
|
||||
if (newcam_active == 0)
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
else
|
||||
{
|
||||
m->area->camera->mode = CAMERA_MODE_NEWCAM;
|
||||
gLakituState.mode = CAMERA_MODE_NEWCAM;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if (m->actionTimer++ == 0) {
|
||||
play_sound(SOUND_ACTION_HIT, m->marioObj->header.gfx.cameraToObject);
|
||||
|
@ -1877,7 +1950,17 @@ s32 act_flying_triple_jump(struct MarioState *m) {
|
|||
#ifndef VERSION_JP
|
||||
if (m->input & (INPUT_B_PRESSED | INPUT_Z_PRESSED)) {
|
||||
if (m->area->camera->mode == CAMERA_MODE_BEHIND_MARIO) {
|
||||
#ifndef BETTERCAMERA
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
#else
|
||||
if (newcam_active == 0)
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
else
|
||||
{
|
||||
m->area->camera->mode = CAMERA_MODE_NEWCAM;
|
||||
gLakituState.mode = CAMERA_MODE_NEWCAM;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (m->input & INPUT_B_PRESSED) {
|
||||
return set_mario_action(m, ACT_DIVE, 0);
|
||||
|
@ -1918,7 +2001,17 @@ s32 act_flying_triple_jump(struct MarioState *m) {
|
|||
|
||||
if (m->vel[1] < 4.0f) {
|
||||
if (m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) {
|
||||
#ifndef BETTERCAMERA
|
||||
set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1);
|
||||
#else
|
||||
if (newcam_active == 0)
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
else
|
||||
{
|
||||
m->area->camera->mode = CAMERA_MODE_NEWCAM;
|
||||
gLakituState.mode = CAMERA_MODE_NEWCAM;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (m->forwardVel < 32.0f) {
|
||||
|
@ -1928,9 +2021,11 @@ s32 act_flying_triple_jump(struct MarioState *m) {
|
|||
set_mario_action(m, ACT_FLYING, 1);
|
||||
}
|
||||
|
||||
#ifndef BETTERCAMERA
|
||||
if (m->actionTimer++ == 10 && m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) {
|
||||
set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
update_air_without_turn(m);
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#include "level_table.h"
|
||||
#include "course_table.h"
|
||||
#include "thread6.h"
|
||||
#ifdef BETTERCAMERA
|
||||
#include "bettercamera.h"
|
||||
#endif
|
||||
|
||||
#define MENU_DATA_MAGIC 0x4849
|
||||
#define SAVE_FILE_MAGIC 0x4441
|
||||
|
@ -565,6 +568,50 @@ u16 save_file_get_sound_mode(void) {
|
|||
return gSaveBuffer.menuData[0].soundMode;
|
||||
}
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
void save_file_set_setting(void) {
|
||||
|
||||
gSaveBuffer.menuData[0].camx = newcam_sensitivityX;
|
||||
gSaveBuffer.menuData[0].camy = newcam_sensitivityY;
|
||||
gSaveBuffer.menuData[0].invertx = newcam_invertX;
|
||||
gSaveBuffer.menuData[0].inverty = newcam_invertY;
|
||||
gSaveBuffer.menuData[0].camc = newcam_aggression;
|
||||
gSaveBuffer.menuData[0].camp = newcam_panlevel;
|
||||
gSaveBuffer.menuData[0].analogue = newcam_analogue;
|
||||
|
||||
gSaveBuffer.menuData[0].firsttime = 1;
|
||||
|
||||
|
||||
gMainMenuDataModified = TRUE;
|
||||
save_main_menu_data();
|
||||
}
|
||||
|
||||
void save_file_get_setting(void) {
|
||||
newcam_sensitivityX = gSaveBuffer.menuData[0].camx;
|
||||
newcam_sensitivityY = gSaveBuffer.menuData[0].camy;
|
||||
newcam_invertX = gSaveBuffer.menuData[0].invertx;
|
||||
newcam_invertY = gSaveBuffer.menuData[0].inverty;
|
||||
newcam_aggression = gSaveBuffer.menuData[0].camc;
|
||||
newcam_panlevel = gSaveBuffer.menuData[0].camp;
|
||||
newcam_analogue = gSaveBuffer.menuData[0].analogue;
|
||||
|
||||
}
|
||||
|
||||
u8 save_check_firsttime(void)
|
||||
{
|
||||
return gSaveBuffer.menuData[0].firsttime;
|
||||
}
|
||||
|
||||
|
||||
void save_set_firsttime(void)
|
||||
{
|
||||
gSaveBuffer.menuData[0].firsttime = 1;
|
||||
|
||||
gMainMenuDataModified = TRUE;
|
||||
save_main_menu_data();
|
||||
}
|
||||
#endif
|
||||
|
||||
void save_file_move_cap_to_default_location(void) {
|
||||
if (save_file_get_flags() & SAVE_FLAG_CAP_ON_GROUND) {
|
||||
switch (gSaveBuffer.files[gCurrSaveFileNum - 1][0].capLevel) {
|
||||
|
|
|
@ -6,7 +6,11 @@
|
|||
|
||||
#include "course_table.h"
|
||||
|
||||
#ifndef BETTERCAMERA
|
||||
#define EEPROM_SIZE 0x200
|
||||
#else
|
||||
#define EEPROM_SIZE 0x800
|
||||
#endif
|
||||
#define NUM_SAVE_FILES 4
|
||||
|
||||
struct SaveBlockSignature
|
||||
|
@ -50,7 +54,16 @@ struct MainMenuSaveData
|
|||
// on the high score screen.
|
||||
u32 coinScoreAges[NUM_SAVE_FILES];
|
||||
u16 soundMode;
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
u8 camx;
|
||||
u8 camy;
|
||||
u8 analogue;
|
||||
u8 invertx;
|
||||
u8 inverty;
|
||||
u8 camc;
|
||||
u8 camp;
|
||||
u8 firsttime;
|
||||
#endif
|
||||
#ifdef VERSION_EU
|
||||
u16 language;
|
||||
#define SUBTRAHEND 8
|
||||
|
@ -58,8 +71,11 @@ struct MainMenuSaveData
|
|||
#define SUBTRAHEND 6
|
||||
#endif
|
||||
|
||||
|
||||
// Pad to match the EEPROM size of 0x200 (10 bytes on JP/US, 8 bytes on EU)
|
||||
#ifndef BETTERCAMERA
|
||||
u8 filler[EEPROM_SIZE / 2 - SUBTRAHEND - NUM_SAVE_FILES * (4 + sizeof(struct SaveFile))];
|
||||
#endif
|
||||
|
||||
struct SaveBlockSignature signature;
|
||||
};
|
||||
|
@ -70,6 +86,9 @@ struct SaveBuffer
|
|||
struct SaveFile files[NUM_SAVE_FILES][2];
|
||||
// The main menu data has two copies. If one is bad, the other is used as a backup.
|
||||
struct MainMenuSaveData menuData[2];
|
||||
#ifdef BETTERCAMERA
|
||||
u8 filler[1535]; //!I still haven't done an algorithm for this yet lol
|
||||
#endif
|
||||
};
|
||||
|
||||
struct WarpNode;
|
||||
|
@ -144,6 +163,12 @@ s32 save_file_get_cap_pos(Vec3s capPos);
|
|||
void save_file_set_sound_mode(u16 mode);
|
||||
u16 save_file_get_sound_mode(void);
|
||||
void save_file_move_cap_to_default_location(void);
|
||||
#ifdef BETTERCAMERA
|
||||
void save_set_firsttime(void);
|
||||
u8 save_check_firsttime(void);
|
||||
void save_file_get_setting(void);
|
||||
void save_file_set_setting(void);
|
||||
#endif
|
||||
|
||||
void disable_warp_checkpoint(void);
|
||||
void check_if_should_set_warp_checkpoint(struct WarpNode *a);
|
||||
|
|
|
@ -20,6 +20,6 @@ enum GdSfx {
|
|||
extern void gd_reset_sfx(void);
|
||||
extern u32 gd_new_sfx_to_play(void);
|
||||
extern void gd_sfx_played(void);
|
||||
extern void gd_play_sfx(u32);
|
||||
extern void gd_play_sfx(enum GdSfx sfx);
|
||||
|
||||
#endif /* GD_MARIO_HEAD_SFX_H */
|
||||
|
|
|
@ -34,6 +34,7 @@ bool configFullscreen = false;
|
|||
unsigned int configKeyA = 0x26;
|
||||
unsigned int configKeyB = 0x33;
|
||||
unsigned int configKeyStart = 0x39;
|
||||
unsigned int configKeyL = 0x34;
|
||||
unsigned int configKeyR = 0x36;
|
||||
unsigned int configKeyZ = 0x25;
|
||||
unsigned int configKeyCUp = 0x148;
|
||||
|
@ -44,6 +45,19 @@ unsigned int configKeyStickUp = 0x11;
|
|||
unsigned int configKeyStickDown = 0x1F;
|
||||
unsigned int configKeyStickLeft = 0x1E;
|
||||
unsigned int configKeyStickRight = 0x20;
|
||||
// Gamepad mappings (SDL_GameControllerButton values)
|
||||
unsigned int configJoyA = 0;
|
||||
unsigned int configJoyB = 2;
|
||||
unsigned int configJoyStart = 6;
|
||||
unsigned int configJoyL = 7;
|
||||
unsigned int configJoyR = 10;
|
||||
unsigned int configJoyZ = 9;
|
||||
// Mouse button mappings (0 for none, 1 for left, 2 for middle, 3 for right)
|
||||
unsigned int configMouseA = 3;
|
||||
unsigned int configMouseB = 1;
|
||||
unsigned int configMouseL = 4;
|
||||
unsigned int configMouseR = 5;
|
||||
unsigned int configMouseZ = 2;
|
||||
|
||||
|
||||
static const struct ConfigOption options[] = {
|
||||
|
@ -51,6 +65,7 @@ static const struct ConfigOption options[] = {
|
|||
{.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},
|
||||
{.name = "key_l", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyL},
|
||||
{.name = "key_r", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyR},
|
||||
{.name = "key_z", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyZ},
|
||||
{.name = "key_cup", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyCUp},
|
||||
|
@ -61,6 +76,17 @@ static const struct ConfigOption options[] = {
|
|||
{.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 = "joy_a", .type = CONFIG_TYPE_UINT, .uintValue = &configJoyA},
|
||||
{.name = "joy_b", .type = CONFIG_TYPE_UINT, .uintValue = &configJoyB},
|
||||
{.name = "joy_start", .type = CONFIG_TYPE_UINT, .uintValue = &configJoyStart},
|
||||
{.name = "joy_l", .type = CONFIG_TYPE_UINT, .uintValue = &configJoyL},
|
||||
{.name = "joy_r", .type = CONFIG_TYPE_UINT, .uintValue = &configJoyR},
|
||||
{.name = "joy_z", .type = CONFIG_TYPE_UINT, .uintValue = &configJoyZ},
|
||||
{.name = "mouse_a", .type = CONFIG_TYPE_UINT, .uintValue = &configMouseA},
|
||||
{.name = "mouse_b", .type = CONFIG_TYPE_UINT, .uintValue = &configMouseB},
|
||||
{.name = "mouse_l", .type = CONFIG_TYPE_UINT, .uintValue = &configMouseL},
|
||||
{.name = "mouse_r", .type = CONFIG_TYPE_UINT, .uintValue = &configMouseR},
|
||||
{.name = "mouse_z", .type = CONFIG_TYPE_UINT, .uintValue = &configMouseZ},
|
||||
};
|
||||
|
||||
// Reads an entire line from a file (excluding the newline character) and returns an allocated string
|
||||
|
|
|
@ -5,6 +5,7 @@ extern bool configFullscreen;
|
|||
extern unsigned int configKeyA;
|
||||
extern unsigned int configKeyB;
|
||||
extern unsigned int configKeyStart;
|
||||
extern unsigned int configKeyL;
|
||||
extern unsigned int configKeyR;
|
||||
extern unsigned int configKeyZ;
|
||||
extern unsigned int configKeyCUp;
|
||||
|
@ -15,6 +16,18 @@ extern unsigned int configKeyStickUp;
|
|||
extern unsigned int configKeyStickDown;
|
||||
extern unsigned int configKeyStickLeft;
|
||||
extern unsigned int configKeyStickRight;
|
||||
extern unsigned int configJoyA;
|
||||
extern unsigned int configJoyB;
|
||||
extern unsigned int configJoyStart;
|
||||
extern unsigned int configJoyL;
|
||||
extern unsigned int configJoyR;
|
||||
extern unsigned int configJoyZ;
|
||||
extern unsigned int configMouseA;
|
||||
extern unsigned int configMouseB;
|
||||
extern unsigned int configMouseStart;
|
||||
extern unsigned int configMouseL;
|
||||
extern unsigned int configMouseR;
|
||||
extern unsigned int configMouseZ;
|
||||
|
||||
void configfile_load(const char *filename);
|
||||
void configfile_save(const char *filename);
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
#ifndef CONTROLLER_API
|
||||
#define CONTROLLER_API
|
||||
|
||||
#define DEADZONE 4960
|
||||
|
||||
// Analog camera movement by Pathétique (github.com/vrmiguel), y0shin and Mors
|
||||
// Contribute or communicate bugs at github.com/vrmiguel/sm64-analog-camera
|
||||
|
||||
#include <ultra64.h>
|
||||
|
||||
struct ControllerAPI {
|
||||
|
|
|
@ -6,6 +6,14 @@
|
|||
|
||||
#include "controller_sdl.h"
|
||||
|
||||
// Analog camera movement by Pathétique (github.com/vrmiguel), y0shin and Mors
|
||||
// Contribute or communicate bugs at github.com/vrmiguel/sm64-analog-camera
|
||||
|
||||
int16_t rightx;
|
||||
int16_t righty;
|
||||
int c_rightx;
|
||||
int c_righty;
|
||||
|
||||
static struct ControllerAPI *controller_implementations[] = {
|
||||
&controller_recorded_tas,
|
||||
&controller_sdl,
|
||||
|
@ -30,6 +38,20 @@ void osContGetReadData(OSContPad *pad) {
|
|||
pad->stick_y = 0;
|
||||
pad->errnum = 0;
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
uint32_t magnitude_sq = (uint32_t)(rightx * rightx) + (uint32_t)(righty * righty);
|
||||
if (magnitude_sq > (uint32_t)(DEADZONE * DEADZONE)) {
|
||||
c_rightx = rightx / 0x100;
|
||||
int stick_y = -righty / 0x100;
|
||||
c_righty = stick_y == 128 ? 127 : stick_y;
|
||||
} else
|
||||
{
|
||||
c_rightx = 0;
|
||||
c_righty = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
for (size_t i = 0; i < sizeof(controller_implementations) / sizeof(struct ControllerAPI *); i++) {
|
||||
controller_implementations[i]->read(pad);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
static int keyboard_buttons_down;
|
||||
|
||||
static int keyboard_mapping[13][2];
|
||||
static int keyboard_mapping[14][2];
|
||||
|
||||
static int keyboard_map_scancode(int scancode) {
|
||||
int ret = 0;
|
||||
|
@ -58,6 +58,7 @@ static void keyboard_init(void) {
|
|||
set_keyboard_mapping(i++, L_CBUTTONS, configKeyCLeft);
|
||||
set_keyboard_mapping(i++, D_CBUTTONS, configKeyCDown);
|
||||
set_keyboard_mapping(i++, R_CBUTTONS, configKeyCRight);
|
||||
set_keyboard_mapping(i++, L_TRIG, configKeyL);
|
||||
set_keyboard_mapping(i++, R_TRIG, configKeyR);
|
||||
set_keyboard_mapping(i++, START_BUTTON, configKeyStart);
|
||||
|
||||
|
|
|
@ -5,21 +5,40 @@
|
|||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
// Analog camera movement by Pathétique (github.com/vrmiguel), y0shin and Mors
|
||||
// Contribute or communicate bugs at github.com/vrmiguel/sm64-analog-camera
|
||||
|
||||
#include <ultra64.h>
|
||||
|
||||
#include "controller_api.h"
|
||||
|
||||
#define DEADZONE 4960
|
||||
#include "../configfile.h"
|
||||
|
||||
extern int16_t rightx;
|
||||
extern int16_t righty;
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
|
||||
extern u8 newcam_mouse;
|
||||
#endif
|
||||
|
||||
static bool init_ok;
|
||||
static SDL_GameController *sdl_cntrl;
|
||||
|
||||
static void controller_sdl_init(void) {
|
||||
if (SDL_Init(SDL_INIT_GAMECONTROLLER) != 0) {
|
||||
if (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS) != 0) {
|
||||
fprintf(stderr, "SDL init error: %s\n", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
if (newcam_mouse == 1)
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
SDL_GetRelativeMouseState(&mouse_x, &mouse_y);
|
||||
#endif
|
||||
|
||||
init_ok = true;
|
||||
}
|
||||
|
||||
|
@ -28,6 +47,21 @@ static void controller_sdl_read(OSContPad *pad) {
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
if (newcam_mouse == 1)
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
else
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
|
||||
const u32 mbuttons = SDL_GetRelativeMouseState(&mouse_x, &mouse_y);
|
||||
|
||||
if (configMouseA && (mbuttons & SDL_BUTTON(configMouseA))) pad->button |= A_BUTTON;
|
||||
if (configMouseB && (mbuttons & SDL_BUTTON(configMouseB))) pad->button |= B_BUTTON;
|
||||
if (configMouseL && (mbuttons & SDL_BUTTON(configMouseL))) pad->button |= L_TRIG;
|
||||
if (configMouseR && (mbuttons & SDL_BUTTON(configMouseR))) pad->button |= R_TRIG;
|
||||
if (configMouseZ && (mbuttons & SDL_BUTTON(configMouseZ))) pad->button |= Z_TRIG;
|
||||
#endif
|
||||
|
||||
SDL_GameControllerUpdate();
|
||||
|
||||
if (sdl_cntrl != NULL && !SDL_GameControllerGetAttached(sdl_cntrl)) {
|
||||
|
@ -48,16 +82,17 @@ static void controller_sdl_read(OSContPad *pad) {
|
|||
}
|
||||
}
|
||||
|
||||
if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_START)) pad->button |= START_BUTTON;
|
||||
if (SDL_GameControllerGetButton(sdl_cntrl, SDL_CONTROLLER_BUTTON_LEFTSHOULDER)) pad->button |= Z_TRIG;
|
||||
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, configJoyStart)) pad->button |= START_BUTTON;
|
||||
if (SDL_GameControllerGetButton(sdl_cntrl, configJoyZ)) pad->button |= Z_TRIG;
|
||||
if (SDL_GameControllerGetButton(sdl_cntrl, configJoyL)) pad->button |= L_TRIG;
|
||||
if (SDL_GameControllerGetButton(sdl_cntrl, configJoyR)) pad->button |= R_TRIG;
|
||||
if (SDL_GameControllerGetButton(sdl_cntrl, configJoyA)) pad->button |= A_BUTTON;
|
||||
if (SDL_GameControllerGetButton(sdl_cntrl, configJoyB)) pad->button |= B_BUTTON;
|
||||
|
||||
int16_t leftx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTX);
|
||||
int16_t lefty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTY);
|
||||
int16_t rightx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_RIGHTX);
|
||||
int16_t righty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_RIGHTY);
|
||||
rightx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_RIGHTX);
|
||||
righty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_RIGHTY);
|
||||
|
||||
int16_t ltrig = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_TRIGGERLEFT);
|
||||
int16_t rtrig = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
|
||||
|
|
|
@ -78,13 +78,31 @@ const SDL_Scancode scancode_rmapping_nonextended[][2] = {
|
|||
{SDL_SCANCODE_KP_MULTIPLY, SDL_SCANCODE_PRINTSCREEN}
|
||||
};
|
||||
|
||||
static void gfx_sdl_set_fullscreen(bool fullscreen)
|
||||
{
|
||||
if (fullscreen)
|
||||
{
|
||||
SDL_SetWindowFullscreen(wnd, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_SetWindowFullscreen(wnd, 0);
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
}
|
||||
|
||||
configFullscreen = fullscreen;
|
||||
}
|
||||
|
||||
static void gfx_sdl_init(void) {
|
||||
Uint32 window_flags = 0;
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
#ifdef TARGET_RPI
|
||||
#ifdef USE_GLES
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); // These attributes allow for hardware acceleration on RPis.
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
|
@ -92,23 +110,33 @@ static void gfx_sdl_init(void) {
|
|||
|
||||
//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
|
||||
//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
|
||||
|
||||
#ifndef TARGET_RPI
|
||||
wnd = SDL_CreateWindow("Super Mario 64 PC-Port", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
||||
#else
|
||||
wnd = SDL_CreateWindow("Super Mario 64 RPi (GLES2)", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
||||
#endif
|
||||
|
||||
if (configFullscreen)
|
||||
{
|
||||
SDL_SetWindowFullscreen(wnd, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE;
|
||||
|
||||
if (configFullscreen) {
|
||||
window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
|
||||
|
||||
SDL_DisplayMode sdl_displaymode;
|
||||
SDL_GetCurrentDisplayMode(0, &sdl_displaymode);
|
||||
|
||||
const char* window_title =
|
||||
#ifndef USE_GLES
|
||||
"Super Mario 64 PC port (OpenGL)";
|
||||
#else
|
||||
"Super Mario 64 PC port (OpenGL_ES2)";
|
||||
#endif
|
||||
|
||||
if (configFullscreen) {
|
||||
wnd = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
sdl_displaymode.w, sdl_displaymode.h, window_flags);
|
||||
} else {
|
||||
wnd = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, window_flags);
|
||||
}
|
||||
|
||||
SDL_GL_CreateContext(wnd);
|
||||
SDL_GL_SetSwapInterval(2); // TODO 0, 1 or 2 or remove this line
|
||||
SDL_GL_SetSwapInterval(1); // We have a double buffered GL context, it makes no sense to want tearing.
|
||||
|
||||
for (size_t i = 0; i < sizeof(windows_scancode_table) / sizeof(SDL_Scancode); i++) {
|
||||
inverted_scancode_table[windows_scancode_table[i]] = i;
|
||||
|
@ -119,8 +147,8 @@ static void gfx_sdl_init(void) {
|
|||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof(scancode_rmapping_nonextended) / sizeof(scancode_rmapping_nonextended[0]); i++) {
|
||||
inverted_scancode_table[scancode_rmapping_extended[i][0]] = inverted_scancode_table[scancode_rmapping_extended[i][1]];
|
||||
inverted_scancode_table[scancode_rmapping_extended[i][1]] += 0x100;
|
||||
inverted_scancode_table[scancode_rmapping_nonextended[i][0]] = inverted_scancode_table[scancode_rmapping_nonextended[i][1]];
|
||||
inverted_scancode_table[scancode_rmapping_nonextended[i][1]] += 0x100;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,24 +184,11 @@ static void gfx_sdl_onkeydown(int scancode) {
|
|||
|
||||
if (state[SDL_SCANCODE_LALT] && state[SDL_SCANCODE_RETURN])
|
||||
{
|
||||
if (!configFullscreen)
|
||||
{
|
||||
SDL_SetWindowFullscreen(wnd, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_SetWindowFullscreen(wnd, 0);
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
}
|
||||
|
||||
configFullscreen = !configFullscreen;
|
||||
gfx_sdl_set_fullscreen(!configFullscreen);
|
||||
}
|
||||
else if (state[SDL_SCANCODE_ESCAPE] && configFullscreen)
|
||||
{
|
||||
SDL_SetWindowFullscreen(wnd, 0);
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
configFullscreen = false;
|
||||
gfx_sdl_set_fullscreen(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue