mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-22 03:55:11 +00:00
Merge remote-tracking branch 'upstream/master' into mingw.org-compatible
This commit is contained in:
commit
753be9e1b7
106 changed files with 2160 additions and 1845 deletions
127
Makefile
127
Makefile
|
@ -1,3 +1,4 @@
|
|||
|
||||
# Makefile to rebuild SM64 split image
|
||||
|
||||
### Default target ###
|
||||
|
@ -22,16 +23,32 @@ TARGET_N64 = 0
|
|||
|
||||
# Build and optimize for Raspberry Pi(s)
|
||||
TARGET_RPI ?= 0
|
||||
# Compiler to use (ido or gcc)
|
||||
COMPILER ?= ido
|
||||
|
||||
# Makeflag to enable OSX fixes
|
||||
OSX_BUILD ?= 0
|
||||
|
||||
# Disable better camera by default
|
||||
BETTERCAMERA ?= 0
|
||||
# Disable no drawing distance by default
|
||||
NODRAWINGDISTANCE ?= 0
|
||||
# Disable texture fixes by default (helps with them purists)
|
||||
TEXTURE_FIX ?= 0
|
||||
# Enable extended options menu by default
|
||||
EXT_OPTIONS_MENU ?= 1
|
||||
|
||||
# Build for Emscripten/WebGL
|
||||
TARGET_WEB ?= 0
|
||||
# Specify the target you are building for, 0 means native
|
||||
TARGET_ARCH ?= native
|
||||
|
||||
ifeq ($(CROSS),i686-w64-mingw32.static-)
|
||||
TARGET_ARCH = i386pe
|
||||
else ifeq ($(CROSS),x86_64-w64-mingw32.static-)
|
||||
TARGET_ARCH = i386pe
|
||||
else
|
||||
TARGET_ARCH = native
|
||||
endif
|
||||
|
||||
TARGET_BITS ?= 0
|
||||
|
||||
ifneq ($(TARGET_BITS),0)
|
||||
|
@ -41,8 +58,6 @@ else
|
|||
endif
|
||||
|
||||
# Automatic settings for PC port(s)
|
||||
# WINDOWS_BUILD IS NOT FOR COMPILING A WINDOWS EXECUTABLE UNDER LINUX OR WSL!
|
||||
# USE THE WIKI GUIDE WITH MSYS2 FOR COMPILING A WINDOWS EXECUTABLE!
|
||||
|
||||
NON_MATCHING := 1
|
||||
GRUCODE := f3dex2e
|
||||
|
@ -137,6 +152,10 @@ ifeq ($(TARGET_RPI),1) # Define RPi to change SDL2 title & GLES2 hints
|
|||
VERSION_CFLAGS += -DUSE_GLES
|
||||
endif
|
||||
|
||||
ifeq ($(OSX_BUILD),1) # Modify GFX & SDL2 for OSX GL
|
||||
VERSION_CFLAGS += -DOSX_BUILD
|
||||
endif
|
||||
|
||||
VERSION_ASFLAGS := --defsym AVOID_UB=1
|
||||
COMPARE := 0
|
||||
|
||||
|
@ -163,7 +182,7 @@ endif
|
|||
endif
|
||||
|
||||
# Make tools if out of date
|
||||
DUMMY != make -s -C tools >&2 || echo FAIL
|
||||
DUMMY != make -C tools >&2 || echo FAIL
|
||||
ifeq ($(DUMMY),FAIL)
|
||||
$(error Failed to build tools)
|
||||
endif
|
||||
|
@ -224,10 +243,6 @@ GODDARD_SRC_DIRS := src/goddard src/goddard/dynlists
|
|||
MIPSISET := -mips2
|
||||
MIPSBIT := -32
|
||||
|
||||
ifeq ($(COMPILER),gcc)
|
||||
MIPSISET := -mips3
|
||||
endif
|
||||
|
||||
ifeq ($(VERSION),eu)
|
||||
OPT_FLAGS := -O2
|
||||
else
|
||||
|
@ -246,9 +261,8 @@ ifeq ($(TARGET_WEB),1)
|
|||
endif
|
||||
|
||||
# Use a default opt flag for gcc, then override if RPi
|
||||
ifeq ($(COMPILER),gcc)
|
||||
OPT_FLAGS := -O2 # Breaks sound on x86?
|
||||
endif
|
||||
|
||||
# OPT_FLAGS := -O2 # "Whole-compile optimization flag" Breaks sound on x86.
|
||||
|
||||
ifeq ($(TARGET_RPI),1)
|
||||
machine = $(shell sh -c 'uname -m 2>/dev/null || echo unknown')
|
||||
|
@ -411,6 +425,10 @@ ENDIAN_BITWIDTH := $(BUILD_DIR)/endian-and-bitwidth
|
|||
|
||||
AS := as
|
||||
|
||||
ifeq ($(OSX_BUILD),1)
|
||||
AS := i686-w64-mingw32-as
|
||||
endif
|
||||
|
||||
ifneq ($(TARGET_WEB),1) # As in, not-web PC port
|
||||
CC := $(CROSS)gcc
|
||||
CXX := $(CROSS)g++
|
||||
|
@ -419,14 +437,33 @@ else
|
|||
endif
|
||||
|
||||
ifeq ($(WINDOWS_BUILD),1)
|
||||
LD := $(CXX)
|
||||
ifeq ($(CROSS),i686-w64-mingw32.static-) # fixes compilation in MXE on Linux and WSL
|
||||
LD := $(CC)
|
||||
else ifeq ($(CROSS),x86_64-w64-mingw32.static-)
|
||||
LD := $(CC)
|
||||
else
|
||||
LD := $(CXX)
|
||||
endif
|
||||
else
|
||||
LD := $(CC)
|
||||
endif
|
||||
|
||||
CPP := $(CROSS)cpp -P
|
||||
OBJDUMP := $(CROSS)objdump
|
||||
OBJCOPY := $(CROSS)objcopy
|
||||
ifeq ($(WINDOWS_BUILD),1) # fixes compilation in MXE on Linux and WSL
|
||||
CPP := cpp -P
|
||||
OBJCOPY := objcopy
|
||||
OBJDUMP := $(CROSS)objdump
|
||||
else
|
||||
ifeq ($(OSX_BUILD),1)
|
||||
CPP := cpp-9 -P
|
||||
OBJDUMP := i686-w64-mingw32-objdump
|
||||
OBJCOPY := i686-w64-mingw32-objcopy
|
||||
else # Linux & other builds
|
||||
CPP := $(CROSS)cpp -P
|
||||
OBJCOPY := $(CROSS)objcopy
|
||||
OBJDUMP := $(CROSS)objdump
|
||||
endif
|
||||
endif
|
||||
|
||||
PYTHON := python3
|
||||
SDLCONFIG := $(CROSS)sdl2-config
|
||||
|
||||
|
@ -444,34 +481,55 @@ CC_CHECK := $(CC) -fsyntax-only -fsigned-char $(INCLUDE_CFLAGS) -Wall -Wextra -W
|
|||
CFLAGS := $(OPT_FLAGS) $(INCLUDE_CFLAGS) $(VERSION_CFLAGS) $(GRUCODE_CFLAGS) -fno-strict-aliasing -fwrapv `$(SDLCONFIG) --cflags`
|
||||
endif
|
||||
|
||||
# Check for better camera option
|
||||
# Check for enhancement options
|
||||
|
||||
# Check for Puppycam option
|
||||
ifeq ($(BETTERCAMERA),1)
|
||||
CC_CHECK += -DBETTERCAMERA
|
||||
CFLAGS += -DBETTERCAMERA
|
||||
CC_CHECK += -DBETTERCAMERA
|
||||
CFLAGS += -DBETTERCAMERA
|
||||
EXT_OPTIONS_MENU := 1
|
||||
endif
|
||||
|
||||
# Check for no drawing distance option
|
||||
ifeq ($(NODRAWINGDISTANCE),1)
|
||||
CC_CHECK += -DNODRAWINGDISTANCE
|
||||
CFLAGS += -DNODRAWINGDISTANCE
|
||||
endif
|
||||
|
||||
# Check for texture fix option
|
||||
ifeq ($(TEXTURE_FIX),1)
|
||||
CC_CHECK += -DTEXTURE_FIX
|
||||
CFLAGS += -DTEXTURE_FIX
|
||||
endif
|
||||
|
||||
# Check for extended options menu option
|
||||
ifeq ($(EXT_OPTIONS_MENU),1)
|
||||
CC_CHECK += -DEXT_OPTIONS_MENU
|
||||
CFLAGS += -DEXT_OPTIONS_MENU
|
||||
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 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -no-pie -static
|
||||
ifeq ($(WINDOWS_CONSOLE),1)
|
||||
LDFLAGS += -mconsole
|
||||
endif
|
||||
else
|
||||
|
||||
else ifeq ($(WINDOWS_BUILD),1)
|
||||
LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -Llib -lpthread -lglew32 `$(SDLCONFIG) --static-libs` -lm -lglu32 -lsetupapi -ldinput8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lwinmm -lversion -luuid -lopengl32 -static
|
||||
ifeq ($(CROSS),)
|
||||
LDFLAGS += -no-pie
|
||||
endif
|
||||
ifeq ($(WINDOWS_CONSOLE),1)
|
||||
LDFLAGS += -mconsole
|
||||
endif
|
||||
else ifeq ($(TARGET_RPI),1)
|
||||
# Linux / Other builds below
|
||||
ifeq ($(TARGET_RPI),1)
|
||||
LDFLAGS := $(OPT_FLAGS) -lm -lGLESv2 `$(SDLCONFIG) --libs` -no-pie
|
||||
else
|
||||
ifeq ($(OSX_BUILD),1)
|
||||
LDFLAGS := -lm -framework OpenGL `$(SDLCONFIG) --libs` -no-pie -lpthread `pkg-config --libs libusb-1.0 glfw3 glew`
|
||||
else
|
||||
LDFLAGS := $(BITS) -march=$(TARGET_ARCH) -lm -lGL `$(SDLCONFIG) --libs` -no-pie -lpthread
|
||||
endif
|
||||
endif
|
||||
endif #Added for Pi ifeq
|
||||
|
||||
endif # End of LDFLAGS
|
||||
|
||||
# Prevent a crash with -sopt
|
||||
export LANG := C
|
||||
|
@ -580,11 +638,13 @@ 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
|
||||
$(BUILD_DIR)/src/game/ingame_menu.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/game/options_menu.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
|
||||
O_FILES += $(BUILD_DIR)/bin/eu/translation_en.o $(BUILD_DIR)/bin/eu/translation_de.o $(BUILD_DIR)/bin/eu/translation_fr.o
|
||||
else
|
||||
$(BUILD_DIR)/src/menu/file_select.o: $(BUILD_DIR)/include/text_strings.h
|
||||
$(BUILD_DIR)/src/menu/star_select.o: $(BUILD_DIR)/include/text_strings.h
|
||||
$(BUILD_DIR)/src/game/ingame_menu.o: $(BUILD_DIR)/include/text_strings.h
|
||||
$(BUILD_DIR)/src/game/options_menu.o: $(BUILD_DIR)/include/text_strings.h
|
||||
endif
|
||||
|
||||
################################################################
|
||||
|
@ -680,7 +740,6 @@ $(BUILD_DIR)/assets/mario_anim_data.c: $(wildcard assets/anims/*.inc.c)
|
|||
$(BUILD_DIR)/assets/demo_data.c: assets/demo_data.json $(wildcard assets/demos/*.bin)
|
||||
$(PYTHON) tools/demo_data_converter.py assets/demo_data.json $(VERSION_CFLAGS) > $@
|
||||
|
||||
ifeq ($(COMPILER),ido)
|
||||
# Source code
|
||||
$(BUILD_DIR)/levels/%/leveldata.o: OPT_FLAGS := -g
|
||||
$(BUILD_DIR)/actors/%.o: OPT_FLAGS := -g
|
||||
|
@ -722,8 +781,6 @@ $(BUILD_DIR)/src/audio/%.acpp: src/audio/%.c
|
|||
$(BUILD_DIR)/src/audio/%.copt: $(BUILD_DIR)/src/audio/%.acpp
|
||||
$(QEMU_IRIX) -silent -L $(IRIX_ROOT) $(IRIX_ROOT)/usr/lib/copt -signed -I=$< -CMP=$@ -cp=i -scalaroptimize=1
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
# Rebuild files with 'GLOBAL_ASM' if the NON_MATCHING flag changes.
|
||||
$(GLOBAL_ASM_O_FILES): $(GLOBAL_ASM_DEP).$(NON_MATCHING)
|
||||
|
|
12
README.md
12
README.md
|
@ -2,7 +2,12 @@
|
|||
OpenGL adaptation of [n64decomp/sm64](https://github.com/n64decomp/sm64).
|
||||
|
||||
Feel free to report bugs and contribute, but remember, there must be **no upload of any copyrighted asset**.
|
||||
Run `./extract-assets.py --clean && make clean` or `make distclean` to remove ROM-originated content. This port has been made possible thanks to [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) by [Emill](https://github.com/Emill).
|
||||
Run `./extract_assets.py --clean && make clean` or `make distclean` to remove ROM-originated content. This port has been made possible mostly thanks to [Emill](https://github.com/Emill) and his [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) renderer.
|
||||
|
||||
|
||||
Please contribute **first** to the [nightly branch](https://github.com/sm64pc/sm64pc/tree/nightly/). New functionality will be merged to master once they're considered to be well-tested.
|
||||
|
||||
*Read this in other languages: [Español](README_es_ES.md) [简体中文](README_zh_CN.md).*
|
||||
|
||||
## Features
|
||||
|
||||
|
@ -10,8 +15,11 @@ Run `./extract-assets.py --clean && make clean` or `make distclean` to remove RO
|
|||
* Variable aspect ratio and resolution. The game can now correctly render at basically any window size.
|
||||
* Native xinput controller support. On Linux, DualShock 4 has been confirmed to work plug-and-play.
|
||||
* Analog camera control and mouse look. (Activate with `make BETTERCAMERA=1`.)
|
||||
* An option to disable drawing distances. (Activate with `make NODRAWINGDISTANCE=1`.)
|
||||
* In-game control binding, currently available on the `testing` branch.
|
||||
* Skip introductory Peach & Lakitu cutscenes with the `--skip-intro` CLI option
|
||||
|
||||
## Building
|
||||
For building instructions, please refer to the [wiki](https://github.com/sm64pc/sm64pc/wiki).
|
||||
|
||||
**Do NOT attempt to compile Windows executables with `WINDOWS_BUILD=1` under Linux or WSL. It will NOT work. Follow the guide on the wiki.**
|
||||
**Make sure you have MXE first before attempting to compile for Windows on Linux and WSL. Follow the guide on the wiki.**
|
||||
|
|
204
README_es_ES.md
Normal file
204
README_es_ES.md
Normal file
|
@ -0,0 +1,204 @@
|
|||
# sm64pc
|
||||
Adaptación a OpenGL de [n64decomp/sm64](https://github.com/n64decomp/sm64).
|
||||
|
||||
No dudes en contribuir o reportar bugs, pero recuerda: **no se debe subir nada con copyright**.
|
||||
Ejecuta `./extract_assets.py --clean && make clean` o `make distclean` para borrar todo el contenido proveniente de la ROM. Este port es posible gracias a [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) creado por [Emill](https://github.com/Emill).
|
||||
|
||||
## Funcionalidades
|
||||
|
||||
* Renderizado nativo. Podrás jugar a Super Mario 64 sin necesidad de un emulador.
|
||||
* Resolución y relación de aspecto variables. Puedes jugar a Super Mario 64 a básicamente cualquier resolución o tamaño de ventana.
|
||||
* Soporte nativo para mandos XInput. En Linux, se ha confirmado que el DualShock 4 funciona sin más.
|
||||
* Cámara analógica y cámara controlada con el ratón. (Se activa con `make BETTERCAMERA=1`.)
|
||||
* Opción para desactivar el límite de distancia de renderizado. (Se activa con `make NODRAWINGDISTANCE=1`.)
|
||||
* Configurar los controles desde el juego, actualmente solo en la rama `testing`.
|
||||
* Posibilidad de saltarte la intro con la opción de línea de comandos `--skip-intro`, actualmente solo en las ramas `testing` y `skip-intro`.
|
||||
|
||||
## Compilar en Windows
|
||||
**No intentes compilar ejecutables para Windows bajo Linux usando `WINDOWS_BUILD=1`. No va a funcionar. Sigue la guía.**
|
||||
#### 1. Instalación y configuración de MSYS2.
|
||||
|
||||
1. Descarga [msys2-x86_64-latest.exe](http://repo.msys2.org/distrib/msys2-x86_64-latest.exe) y ejecútalo. Si tu sistema operativo es de 32 bits (¿por qué?) descarga [msys2-i686-latest.exe](http://repo.msys2.org/distrib/msys2-i686-latest.exe) en su lugar. Asegúrate de que lo instalas en `C:\dev\msys64` (o `C:\dev\msys32` para 32 bits...). Ejecuta MSYS2.
|
||||
|
||||
2. En la ventana de comandos de MSYS2, ejecuta el siguiente comando:
|
||||
```
|
||||
pacman -Syuu
|
||||
```
|
||||
3. Abre "MSYS2 MinGW 64-Bit". Ejecuta este comando __repetidamente__ hasta que MSYS diga que ya no hay más actualizaciones. Es posible que tengas que volver a cerrar y abrir MSYS2.
|
||||
|
||||
```
|
||||
pacman -Syuu
|
||||
```
|
||||
|
||||
5. Ejecuta este comando y cuando te pida confirmación pulsa intro:
|
||||
|
||||
```
|
||||
pacman -S --needed base-devel mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain \
|
||||
git subversion mercurial \
|
||||
mingw-w64-i686-cmake mingw-w64-x86_64-cmake
|
||||
```
|
||||
6. Listo.
|
||||
#### Instala las dependencias
|
||||
```
|
||||
pacman -S mingw-w64-i686-glew mingw-w64-x86_64-glew mingw-w64-i686-SDL2 mingw-w64-x86_64-SDL2 python3
|
||||
```
|
||||
### Crea el directorio en el que preparar todo
|
||||
Desde el explorador de Windows, navega a `C:\msys64\home\(nombre de usuario)\` y crea una carpeta con el nombre que te apetezca. Aquí es donde vamos a preparar todo.
|
||||
### Clona el repositorio
|
||||
En MSYS2, introduce el siguiente comando:
|
||||
```
|
||||
git clone https://github.com/sm64pc/sm64pc/
|
||||
```
|
||||
(Si no funciona, prueba a escribirlo manualmente, en lugar de copiar y pegar)
|
||||
#### Copia la ROM base al directorio correspondiente
|
||||
El paso anterior tiene que haber creado una carpeta llamada sm64pc. Dentro de esa carpeta, y para cada version de la ROM (jp/us/eu) de la cual quieras compilar un ejecutable, coloca la ROM con el nombre `baserom.<version>.z64` para extraer sus assets. Por ejemplo, `baserom.us.z64` para la versión americana, o `baserom.eu.z64` para la versión europea.
|
||||
|
||||
#### En MSYS2, vamos a navegar a la carpeta `./tools/audiofile-0.3.6/` y ejecutar el `autoreconf-i`. Introduce los siguientes comandos, en orden, uno a uno:
|
||||
```
|
||||
cd sm64pc/tools/audiofile-0.3.6/
|
||||
autoreconf -i
|
||||
```
|
||||
No te vayas de este directorio hasta el paso 9.
|
||||
|
||||
#### Ejecuta el script `configure`
|
||||
```
|
||||
PATH=/mingw64/bin:/mingw32/bin:$PATH LIBS=-lstdc++ ./configure --disable-docs
|
||||
```
|
||||
#### Ejecuta el script `make`
|
||||
```
|
||||
PATH=/mingw64/bin:/mingw32/bin:$PATH make
|
||||
```
|
||||
#### Crea un directorio `lib` en `tools/`
|
||||
```
|
||||
mkdir ../lib
|
||||
```
|
||||
|
||||
#### Acabas de compilar `libaudiofile`. Ahora cópialo a `tools/lib/`
|
||||
```
|
||||
cp libaudiofile/.libs/libaudiofile.a ../lib/
|
||||
cp libaudiofile/.libs/libaudiofile.la ../lib/
|
||||
```
|
||||
#### Ahora toca hacer algo desde Windows.
|
||||
En el explorador de Windows, ve a sm64pc\tools y edita el archivo Makefile desde un editor de texto (es recomendable usar un editor decente como Notepad++ o Sublime Text, en lugar del bloc de notas, para asegurarte de que no rompes el formato del texto) Busca la línea que contiene esto:
|
||||
|
||||
```tabledesign_CFLAGS := -Wno-uninitialized -laudiofile```
|
||||
|
||||
Y añade ` -lstdc++` al final, de manera que quede así (¡no olvides el espacio!)
|
||||
|
||||
```tabledesign_CFLAGS := -Wno-uninitialized -laudiofile -lstdc++```
|
||||
|
||||
Guarda el archivo.
|
||||
#### Vuelve a la carpeta tools y ejecuta `make` con los siguientes comandos.
|
||||
```
|
||||
cd ..
|
||||
PATH=/mingw64/bin:/mingw32/bin:$PATH make
|
||||
```
|
||||
#### Vuelve al directorio sm64pc
|
||||
```
|
||||
cd ..
|
||||
```
|
||||
#### Finalmente, ejecuta ```make``` de nuevo.
|
||||
|
||||
(Ten en cuenta que mingw32 y mingw64 han sido intercambiados. Esto es para que puedas compilar la versión de 32 bits si quieres.)
|
||||
|
||||
Aquí pones las opciones que quieras según la versión que quieras compilar. Por ejemplo, si quieres activar la cámara analógica, añade al final BETTERCAMERA=1. Si quieres la opción de distancia de renderizado ilimitada, añade NODRAWINGDISTANCE=1.
|
||||
|
||||
Por ejemplo:
|
||||
```
|
||||
PATH=/mingw32/bin:/mingw64/bin:$PATH make BETTERCAMERA=1 NODRAWINGDISTANCE=1
|
||||
```
|
||||
Listo. El .exe estará en sm64pc\build\. Disfruta.
|
||||
## Compilar en Linux
|
||||
|
||||
### Nota para usuarios de Windows
|
||||
No intentes compilar un ejecutable para Windows desde Linux o WSL. No funciona. Sigue la guía para Windows.
|
||||
|
||||
#### Copia la(s) ROM(s) base para la extracción de assets.
|
||||
|
||||
Por cada versión de la cual quieras compilar un ejecutable, copia la ROM en `./baserom.<versión>.z64` para extraer los assets.
|
||||
|
||||
#### Instala las dependencias.
|
||||
|
||||
Para compilar necesitas las sigueintes dependencias.
|
||||
* python3 >= 3.6
|
||||
* libsdl2-dev
|
||||
* [audiofile](https://audiofile.68k.org/)
|
||||
* libglew-dev
|
||||
* git
|
||||
|
||||
Puedes instalarlas con este comando:
|
||||
|
||||
##### Debian / Ubuntu - (compilando para 32 bits)
|
||||
```
|
||||
sudo apt install build-essential git python3 libaudiofile-dev libglew-dev:i386 libsdl2-dev:i386
|
||||
```
|
||||
##### Debian / Ubuntu - (compilando para 64 bits)
|
||||
```
|
||||
sudo apt install build-essential git python3 libaudiofile-dev libglew-dev libsdl2-dev
|
||||
```
|
||||
##### Arch Linux
|
||||
Hay un paquete AUR (cortesía de @narukeh) disponible bajo el nombre [sm64pc-git](https://aur.archlinux.org/packages/sm64pc-git/). Instálalo con tu gestor de AURs preferido.
|
||||
|
||||
Si quieres compilarlo por tu cuenta:
|
||||
```
|
||||
sudo pacman -S base-devel python audiofile sdl2 glew
|
||||
```
|
||||
|
||||
##### Void Linux - (compilando para 64 bits)
|
||||
```
|
||||
sudo xbps-install -S base-devel python3 audiofile-devel SDL2-devel glew-devel
|
||||
```
|
||||
|
||||
##### Void Linux - (compilando para 32 bits)
|
||||
```
|
||||
sudo xbps-install -S base-devel python3 audiofile-devel-32bit SDL2-devel-32bit glew-devel-32bit
|
||||
```
|
||||
|
||||
#### Compila el ejecutable.
|
||||
|
||||
Ejecuta `make` para compilar (por defecto `VERSION=us`)
|
||||
|
||||
```
|
||||
make VERSION=jp -j6 # Compila la versión (J) usando 6 hilos
|
||||
make VERSION=us MARCH=i686 TARGET_BITS=32 # Compila un ejecutable de la versión (U) de 32 bits
|
||||
make TARGET_RPI=1 # Compila un ejecutable para Raspberry Pi
|
||||
```
|
||||
## Compilar para la web
|
||||
Puedes compilar el juego para navegadores que admitan WebGL usando [Emscripten](https://github.com/emscripten-core). Para hacerlo, instala [emsdk](https://github.com/emscripten-core/emsdk) y ejecuta `make TARGET_WEB=1`.
|
||||
|
||||
## Script para compilar para Raspberry Pi
|
||||
|
||||
[Hyenadae](https://github.com/Hyenadae/) ha creado un script que ayuda a compilar el juego para Raspberry Pi. Estos son los pasos que hace el script:
|
||||
|
||||
* Instala las dependencias;
|
||||
* Cambia VC4_DRM en la RPi de 0 a 3;
|
||||
* Cambia ajustes en la memoria de las RPis 0 y 1 para que se pueda completar la compilación;
|
||||
* Permite la instalación de un SDL2 con KMS, lo que elimina la necesidad de usar X11 y garantiza el máximo rendimiento de cualquier RPi que ejecute VC4;
|
||||
* Clona sm64pc si no encuentra los archivos necesarios;
|
||||
* Comprueba si existen los assets y la ROM base necesaria (baserom.*.z64);
|
||||
* Compila sm64pc.
|
||||
|
||||
El script está incluído en la rama master, pero también puede descargarse [aquí](https://raw.githubusercontent.com/sm64pc/sm64pc/master/pisetup.sh).
|
||||
# Problemas conocidos
|
||||
### Problemas ya conocidos:
|
||||
* La versión EU tiene bugs en los textos y no tiene audio.
|
||||
* El movimiento analógico horizontal de la cámara vuelve al estilo antiguo en el nivel Bowser in the Dark World (#72)
|
||||
* La cámara con el ratón falla cuando disparas a Mario hacia un árbol o un tubo. (#71)
|
||||
* "make: Nothing to be done for 'default'" al compilar para web. (#67)
|
||||
|
||||
### Estos problemas están marcados como solucionados. Por favor, contacta si sigues teniendo estos problemas.
|
||||
* El juego se llena de flags aleatorias en las builds de 64 bits para Windows
|
||||
* Hazy Maze Cave se cuelga en pantalla completa (#57)
|
||||
* La pantalla de título no tiene el cursor para manipular a Mario en pantalla completa. (#28)
|
||||
|
||||
## Parches
|
||||
En la carpeta `./enhancements` hay varios archivos `patch`, que pueden aplicarse de la siguiente manera:
|
||||
|
||||
```
|
||||
git apply fps.patch --ignore-whitespace --reject
|
||||
```
|
||||
Si ocurre un rechazo, puedes buscarlo con el comando `find | grep .rej`.
|
||||
Intenta resolver los rechazos a través de [wiggle](https://github.com/neilbrown/wiggle).
|
||||
```
|
||||
wiggle rejection.rej --replace
|
||||
```
|
21
README_zh_CN.md
Normal file
21
README_zh_CN.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
# sm64pc
|
||||
本项目是 [n64decomp/sm64](https://github.com/n64decomp/sm64) 的 OpenGL 移植版本。
|
||||
|
||||
我们欢迎贡献代码与 bug 报告,但请切记,**不得上传任何被版权保护(来自 ROM 文件)的资源**。
|
||||
提交前请运行 `./extract_assets.py --clean && make clean` 或 `make distclean` 来清除所有从 ROM 文件中提取的内容。
|
||||
本移植是基于 [Emill](https://github.com/Emill) 的工作 [n64-fast32-engine](https://github.com/Emill/n64-fast3d-engine/) 才得以实现的。
|
||||
|
||||
## 主要功能
|
||||
|
||||
* 原生渲染。现在不用任何模拟器就可以运行 马力欧64 了。
|
||||
* 长宽比和分辨率可以自由改变。本游戏目前可以在几乎任何窗口尺寸下正确渲染。
|
||||
* 原生 xinput 手柄支持。在 Linux 下,已经确认 PS4 手柄可以即插即用。
|
||||
* 支持模拟量视点控制、鼠标控制视点。(请使用 `make BETTERCAMERA=1` 编译)
|
||||
* 可取消可视距离限制。(请使用 `make NODRAWINGDISTANCE=1` 编译)
|
||||
* 游戏内操作设定功能,目前在 `testing` 分支下可用。
|
||||
* 使用 `--skip-intro` 命令行选项跳过碧奇公主与 Lakitu 的片头剧情。目前在 `testing` 及 `skip-intro` 分支下可用。
|
||||
|
||||
## 编译方法
|
||||
关于如何编译,请参考 [wiki](https://github.com/sm64pc/sm64pc/wiki)。
|
||||
|
||||
**请勿在 Linux 或者 WSL 下使用 `WINDOWS_BUILD=1` 参数尝试编译 Windows 版本,这样无法编译成功。请参考 Wiki。
|
|
@ -11,6 +11,9 @@ static const Vtx burn_smoke_seg4_vertex_040217C0[] = {
|
|||
// //! Wrong texture format. Called as rgba16, which makes the burn smoke appear
|
||||
// as a transparent black burn smoke. Probably meant to show up as white-ish
|
||||
// burn smoke, but mistakened for being intended as black smoke.
|
||||
// Due to debate in the Koopa shorts PR surrounding the fix to a similar bug,
|
||||
// said fix is on a compile-time variable. Use TEXTURE_FIX=1 at compile time
|
||||
// to fix this.
|
||||
// 0x04021800
|
||||
ALIGNED8 static const u8 burn_smoke_seg4_texture_04021800[] = {
|
||||
#include "actors/burn_smoke/burn_smoke.ia16.inc.c"
|
||||
|
@ -44,7 +47,11 @@ const Gfx burn_smoke_seg4_dl_04022048[] = {
|
|||
// 0x04022070 - 0x040220C8
|
||||
const Gfx burn_smoke_seg4_dl_04022070[] = {
|
||||
gsSPDisplayList(burn_smoke_seg4_dl_04022000),
|
||||
#ifdef TEXTURE_FIX
|
||||
gsDPLoadTextureBlock(burn_smoke_seg4_texture_04021800, G_IM_FMT_IA, G_IM_SIZ_16b, 32, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 5, 5, G_TX_NOLOD, G_TX_NOLOD),
|
||||
#else
|
||||
gsDPLoadTextureBlock(burn_smoke_seg4_texture_04021800, G_IM_FMT_RGBA, G_IM_SIZ_16b, 32, 32, 0, G_TX_CLAMP, G_TX_CLAMP, 5, 5, G_TX_NOLOD, G_TX_NOLOD),
|
||||
#endif
|
||||
gsSPDisplayList(burn_smoke_seg4_dl_04022028),
|
||||
gsSPDisplayList(burn_smoke_seg4_dl_04022048),
|
||||
gsSPEndDisplayList(),
|
||||
|
|
|
@ -54,6 +54,8 @@ static const Lights1 koopa_seg6_lights_06002630 = gdSPDefLights1(
|
|||
// beneath its shell, despite the fact it was intended to be white like
|
||||
// the rest of its body. This is evident because once the mistake is corrected
|
||||
// it turns back to being white like the other polygons.
|
||||
// Due to debate in the PR surrounding the fix to this, said fix is on
|
||||
// a compile-time variable. Use TEXTURE_FIX=1 at compile time to fix this.
|
||||
// 0x06002648
|
||||
ALIGNED8 static const u8 koopa_seg6_texture_06002648[] = {
|
||||
#include "actors/koopa/koopa_shell_front.rgba16.inc.c"
|
||||
|
@ -2077,8 +2079,13 @@ const Gfx koopa_seg6_dl_0600C498[] = {
|
|||
gsSPVertex(koopa_seg6_vertex_0600B560, 9, 0),
|
||||
gsSP2Triangles( 0, 1, 2, 0x0, 3, 4, 5, 0x0),
|
||||
gsSP1Triangle( 6, 7, 8, 0x0),
|
||||
#ifdef TEXTURE_FIX
|
||||
gsSPLight(&koopa_seg6_lights_06002630.l, 1),
|
||||
gsSPLight(&koopa_seg6_lights_06002630.a, 2),
|
||||
#else
|
||||
gsSPLight(koopa_seg6_texture_06002648 + 0x20, 1), // this malformed light results in a
|
||||
gsSPLight(koopa_seg6_texture_06002648 + 0x18, 2), // koopa appearing to wear pink shorts.
|
||||
#endif
|
||||
gsSPVertex(koopa_seg6_vertex_0600B5F0, 15, 0),
|
||||
gsSP2Triangles( 0, 1, 2, 0x0, 3, 4, 5, 0x0),
|
||||
gsSP2Triangles( 6, 7, 0, 0x0, 8, 5, 9, 0x0),
|
||||
|
|
|
@ -2499,41 +2499,23 @@ static const Lights1 segment2_lights_unused = gdSPDefLights1(
|
|||
|
||||
// 0x02014470 - 0x020144B0
|
||||
static const Mtx matrix_identity = {
|
||||
#ifdef TARGET_N64
|
||||
{{0x00010000, 0x00000000,
|
||||
0x00000001, 0x00000000},
|
||||
{0x00000000, 0x00010000,
|
||||
0x00000000, 0x00000001},
|
||||
{0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000},
|
||||
{0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000}}
|
||||
#else
|
||||
|
||||
{{1.0f, 0.0f, 0.0f, 0.0f},
|
||||
{0.0f, 1.0f, 0.0f, 0.0f},
|
||||
{0.0f, 0.0f, 1.0f, 0.0f},
|
||||
{0.0f, 0.0f, 0.0f, 1.0f}}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
// 0x020144B0 - 0x020144F0
|
||||
static const Mtx matrix_fullscreen = {
|
||||
#if TARGET_N64
|
||||
{{0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000},
|
||||
{0x00000000, 0xffff0000,
|
||||
0xffffffff, 0xffff0001},
|
||||
{((65536 * 2 / SCREEN_WIDTH) << 16) | 0, 0x00000000,
|
||||
(0 << 16) | (65536 * 2 / SCREEN_HEIGHT), 0x00000000},
|
||||
{0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000}}
|
||||
#else
|
||||
|
||||
{{2.0f / SCREEN_WIDTH, 0.0f, 0.0f, 0.0f},
|
||||
{0.0f, 2.0f / SCREEN_HEIGHT, 0.0f, 0.0f},
|
||||
{0.0f, 0.0f, -1.0f, 0.0f},
|
||||
{-1.0f, -1.0f, -1.0f, 1.0f}}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
141
c2obj.py
Normal file
141
c2obj.py
Normal file
|
@ -0,0 +1,141 @@
|
|||
"""
|
||||
This module attempts to parse the ``model.inc.c`` files and extract the
|
||||
3D models within as standard Wavefront OBJ files.
|
||||
|
||||
Example:
|
||||
Specify the path to the ``.inc.c`` file and a directory where to save
|
||||
the extracted ``.obj`` files.
|
||||
|
||||
$ python c2obj.py ./actors/mario/model.inc.c ./actors/mario/obj/
|
||||
|
||||
This is a work in progress and it currently has some serious limitations:
|
||||
* It only extracts geometry information, so no textures or any other info
|
||||
* It makes assumptions about the layout of the code in the C source
|
||||
* It hasn't been properly tested.
|
||||
|
||||
"""
|
||||
|
||||
def parse(filename, output_directory):
|
||||
from os import path, mkdir
|
||||
|
||||
if not path.isdir(output_directory):
|
||||
try:
|
||||
mkdir(output_directory)
|
||||
except OSError:
|
||||
print(f'Could not use output directory {output_directory}.')
|
||||
|
||||
vtx_def = 'static const Vtx '
|
||||
vtx_data = {}
|
||||
reading_vtx = False
|
||||
current_vtx_name = ''
|
||||
current_vtx_data = []
|
||||
current_vtx_vertices = 0
|
||||
|
||||
gfx_def = 'const Gfx '
|
||||
reading_gfx = False
|
||||
current_gfx_vertices = 0
|
||||
current_gfx_faces = 0
|
||||
insert_vert_call = 'gsSPVertex('
|
||||
insert_1tri_call = 'gsSP1Triangle('
|
||||
insert_2tri_call = 'gsSP2Triangles('
|
||||
gfx_count = 0
|
||||
|
||||
end_of_block = '};'
|
||||
|
||||
with open(filename, 'r') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
|
||||
if line.startswith(vtx_def):
|
||||
vtx_name = line.split(' ')[3][:-2]
|
||||
current_vtx_name = vtx_name
|
||||
current_vtx_data = []
|
||||
reading_vtx = True
|
||||
continue
|
||||
|
||||
if line.startswith(gfx_def):
|
||||
from datetime import datetime
|
||||
|
||||
current_gfx_name = line.split(' ')[2][:-2]
|
||||
current_gfx_file = open(path.join(output_directory, current_gfx_name + '.obj'), 'w')
|
||||
current_gfx_file.write("# Armando Arredondo's SM64 Wavefront OBJ Geometry Converter\n")
|
||||
current_gfx_file.write('# File Created: {}\n\n'.format(datetime.now()))
|
||||
reading_gfx = True
|
||||
continue
|
||||
|
||||
if line == end_of_block:
|
||||
if reading_vtx:
|
||||
vtx_data[current_vtx_name] = current_vtx_data
|
||||
reading_vtx = False
|
||||
|
||||
elif reading_gfx:
|
||||
current_gfx_file.write(f'# {current_gfx_faces} faces\n\n')
|
||||
current_gfx_file.close()
|
||||
current_gfx_vertices = 0
|
||||
reading_gfx = False
|
||||
gfx_count += 1
|
||||
|
||||
continue
|
||||
|
||||
if reading_vtx:
|
||||
line = line.replace('{', '[').replace('}', ']')
|
||||
tri = eval(line[:-1])[0]
|
||||
current_vtx_data.append(tri)
|
||||
continue
|
||||
|
||||
if reading_gfx:
|
||||
if line.startswith(insert_vert_call):
|
||||
args = line[len(insert_vert_call):].split(',')
|
||||
current_vtx_name = args[0]
|
||||
|
||||
if current_gfx_vertices > 0:
|
||||
current_gfx_file.write(f'# {current_gfx_faces} faces\n\n')
|
||||
|
||||
current_gfx_faces = 0
|
||||
current_vtx_vertices = len(vtx_data[current_vtx_name])
|
||||
current_gfx_vertices += current_vtx_vertices
|
||||
|
||||
current_gfx_file.write(f'#\n# object {current_vtx_name}\n#\n\n')
|
||||
current_vtx_data = vtx_data[current_vtx_name]
|
||||
for tri in current_vtx_data:
|
||||
v = tri[0]
|
||||
current_gfx_file.write('v {:.3f} {:.3f} {:.3f}\n'.format(*v))
|
||||
current_gfx_file.write(f'# {current_vtx_vertices} vertices\n\n')
|
||||
|
||||
for tri in current_vtx_data:
|
||||
n = [_decode_normal(u) for u in tri[3][:3]]
|
||||
current_gfx_file.write('vn {:.3f} {:.3f} {:.3f}\n'.format(*n))
|
||||
current_gfx_file.write(f'# {current_vtx_vertices} vertex normals\n\n')
|
||||
|
||||
current_gfx_file.write(f'g {current_vtx_name}\n\n')
|
||||
|
||||
elif line.startswith(insert_2tri_call):
|
||||
args = line[len(insert_2tri_call):].split(',')
|
||||
correction = current_gfx_vertices - current_vtx_vertices + 1
|
||||
indexes = [eval(args[i]) + correction for i in [0, 1, 2, 4, 5, 6]]
|
||||
current_gfx_file.write('f {0}//{0} {1}//{1} {2}//{2}\n'.format(*indexes[:3]))
|
||||
current_gfx_file.write('f {0}//{0} {1}//{1} {2}//{2}\n'.format(*indexes[3:]))
|
||||
current_gfx_faces += 2
|
||||
|
||||
elif line.startswith(insert_1tri_call):
|
||||
args = line[len(insert_1tri_call):].split(',')
|
||||
correction = current_gfx_vertices - current_vtx_vertices + 1
|
||||
indexes = [eval(args[i]) + correction for i in [0, 1, 2]]
|
||||
current_gfx_file.write('f {0}//{0} {1}//{1} {2}//{2}\n'.format(*indexes))
|
||||
current_gfx_faces += 1
|
||||
|
||||
continue
|
||||
|
||||
print(f'{gfx_count} models extracted.')
|
||||
|
||||
def _decode_normal(x):
|
||||
y = x if x <= 127 else x - 255
|
||||
return y / 127
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('filename', help = 'filename of the .inc.c source file')
|
||||
parser.add_argument('output_directory', help = 'directory where to put the extracted .obj files')
|
||||
args = parser.parse_args()
|
||||
parse(args.filename, args.output_directory)
|
|
@ -114,7 +114,7 @@
|
|||
// Often used to end behavior scripts that do not contain an infinite loop.
|
||||
#define BREAK() \
|
||||
BC_B(0x0A)
|
||||
|
||||
|
||||
// Exits the behavior script, unused.
|
||||
#define BREAK_UNUSED() \
|
||||
BC_B(0x0B)
|
||||
|
@ -175,15 +175,15 @@
|
|||
#define ADD_INT_RAND_RSHIFT(field, min, rshift) \
|
||||
BC_BBH(0x17, field, min), \
|
||||
BC_H(rshift)
|
||||
|
||||
|
||||
// No operation. Unused.
|
||||
#define CMD_NOP_1(field) \
|
||||
BC_BB(0x18, field)
|
||||
|
||||
|
||||
// No operation. Unused.
|
||||
#define CMD_NOP_2(field) \
|
||||
BC_BB(0x19, field)
|
||||
|
||||
|
||||
// No operation. Unused.
|
||||
#define CMD_NOP_3(field) \
|
||||
BC_BB(0x1A, field)
|
||||
|
@ -219,6 +219,9 @@
|
|||
#define BILLBOARD() \
|
||||
BC_B(0x21)
|
||||
|
||||
#define CYLBOARD() \
|
||||
BC_B(0x38)
|
||||
|
||||
// Hides the current object.
|
||||
#define HIDE() \
|
||||
BC_B(0x22)
|
||||
|
@ -3180,7 +3183,7 @@ const BehaviorScript bhvFloorTrapInCastle[] = {
|
|||
|
||||
const BehaviorScript bhvTree[] = {
|
||||
BEGIN(OBJ_LIST_POLELIKE),
|
||||
BILLBOARD(),
|
||||
CYLBOARD(),
|
||||
OR_INT(oFlags, OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE),
|
||||
SET_INT(oInteractType, INTERACT_POLE),
|
||||
SET_HITBOX(/*Radius*/ 80, /*Height*/ 500),
|
||||
|
@ -6105,5 +6108,3 @@ const BehaviorScript bhvIntroScene[] = {
|
|||
CALL_NATIVE(bhv_intro_scene_loop),
|
||||
END_LOOP(),
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
# No Draw Distances
|
||||
|
||||
This is a work-in-progress by [wabberz](https://github.com/wabberz) that disables the drawing distance for most objects and enemies.
|
||||
|
||||
**This will crash some levels in the 32-bit version**.
|
||||
|
||||
[Related Push Request](https://github.com/sm64pc/sm64pc/pull/75).
|
||||
|
||||
For instructions on how to apply patches, please refer to [the Wiki](https://github.com/sm64pc/sm64pc/wiki/Patches).
|
||||
|
|
@ -1,406 +0,0 @@
|
|||
From c98a263cf40520bf0d131eb2d1a2f90240787c98 Mon Sep 17 00:00:00 2001
|
||||
From: uwabami <uwabami@localhost>
|
||||
Date: Tue, 12 May 2020 09:26:16 +0200
|
||||
Subject: [PATCH] adding option to disable draw distance
|
||||
|
||||
---
|
||||
Makefile | 8 ++++++++
|
||||
src/engine/behavior_script.c | 4 ++++
|
||||
src/engine/surface_load.c | 4 ++++
|
||||
src/game/behaviors/butterfly.inc.c | 3 ++-
|
||||
src/game/behaviors/chain_chomp.inc.c | 8 ++++++++
|
||||
src/game/behaviors/coin.inc.c | 6 ++++++
|
||||
src/game/behaviors/fish.inc.c | 4 ++++
|
||||
src/game/behaviors/goomba.inc.c | 4 ++++
|
||||
src/game/behaviors/heave_ho.inc.c | 4 ++++
|
||||
src/game/behaviors/king_bobomb.inc.c | 4 ++++
|
||||
src/game/behaviors/pokey.inc.c | 6 ++++++
|
||||
src/game/behaviors/snufit.inc.c | 4 ++++
|
||||
src/game/behaviors/triplet_butterfly.inc.c | 4 ++++
|
||||
src/game/behaviors/water_bomb_cannon.inc.c | 8 ++++++++
|
||||
src/game/behaviors/whirlpool.inc.c | 4 ++++
|
||||
15 files changed, 74 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index d4bd284..efeb63e 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -27,6 +27,8 @@ COMPILER ?= ido
|
||||
|
||||
# Disable better camera by default
|
||||
BETTERCAMERA ?= 0
|
||||
+# Disable no drawing distance by default
|
||||
+NODRAWINGDISTANCE ?= 0
|
||||
|
||||
# Build for Emscripten/WebGL
|
||||
TARGET_WEB ?= 0
|
||||
@@ -449,6 +451,12 @@ CC_CHECK += -DBETTERCAMERA
|
||||
CFLAGS += -DBETTERCAMERA
|
||||
endif
|
||||
|
||||
+# Check for no drawing distance option
|
||||
+ifeq ($(NODRAWINGDISTANCE),1)
|
||||
+CC_CHECK += -DNODRAWINGDISTANCE
|
||||
+CFLAGS += -DNODRAWINGDISTANCE
|
||||
+endif
|
||||
+
|
||||
ASFLAGS := -I include -I $(BUILD_DIR) $(VERSION_ASFLAGS)
|
||||
|
||||
ifeq ($(TARGET_WEB),1)
|
||||
diff --git a/src/engine/behavior_script.c b/src/engine/behavior_script.c
|
||||
index edd5247..feb6fef 100644
|
||||
--- a/src/engine/behavior_script.c
|
||||
+++ b/src/engine/behavior_script.c
|
||||
@@ -987,11 +987,15 @@ void cur_obj_update(void) {
|
||||
} else if ((objFlags & OBJ_FLAG_COMPUTE_DIST_TO_MARIO) && gCurrentObject->collisionData == NULL) {
|
||||
if (!(objFlags & OBJ_FLAG_ACTIVE_FROM_AFAR)) {
|
||||
// If the object has a render distance, check if it should be shown.
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (distanceFromMario > gCurrentObject->oDrawingDistance) {
|
||||
// Out of render distance, hide the object.
|
||||
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
|
||||
gCurrentObject->activeFlags |= ACTIVE_FLAG_FAR_AWAY;
|
||||
} else if (gCurrentObject->oHeldState == HELD_FREE) {
|
||||
+#else
|
||||
+ if (distanceFromMario <= gCurrentObject->oDrawingDistance && gCurrentObject->oHeldState == HELD_FREE) {
|
||||
+#endif
|
||||
// In render distance (and not being held), show the object.
|
||||
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
|
||||
gCurrentObject->activeFlags &= ~ACTIVE_FLAG_FAR_AWAY;
|
||||
diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c
|
||||
index 363f9af..498fae0 100644
|
||||
--- a/src/engine/surface_load.c
|
||||
+++ b/src/engine/surface_load.c
|
||||
@@ -789,9 +789,13 @@ void load_object_collision_model(void) {
|
||||
}
|
||||
}
|
||||
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (marioDist < gCurrentObject->oDrawingDistance) {
|
||||
+#endif
|
||||
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
} else {
|
||||
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
diff --git a/src/game/behaviors/butterfly.inc.c b/src/game/behaviors/butterfly.inc.c
|
||||
index d435d8d..9296ed5 100644
|
||||
--- a/src/game/behaviors/butterfly.inc.c
|
||||
+++ b/src/game/behaviors/butterfly.inc.c
|
||||
@@ -107,6 +107,7 @@ void bhv_butterfly_loop(void) {
|
||||
butterfly_act_return_home();
|
||||
break;
|
||||
}
|
||||
-
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
set_object_visibility(o, 3000);
|
||||
+#endif
|
||||
}
|
||||
diff --git a/src/game/behaviors/chain_chomp.inc.c b/src/game/behaviors/chain_chomp.inc.c
|
||||
index a77c5d5..9b9c342 100644
|
||||
--- a/src/game/behaviors/chain_chomp.inc.c
|
||||
+++ b/src/game/behaviors/chain_chomp.inc.c
|
||||
@@ -53,7 +53,9 @@ static void chain_chomp_act_uninitialized(void) {
|
||||
struct ChainSegment *segments;
|
||||
s32 i;
|
||||
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 3000.0f) {
|
||||
+#endif
|
||||
segments = mem_pool_alloc(gObjectMemoryPool, 5 * sizeof(struct ChainSegment));
|
||||
if (segments != NULL) {
|
||||
// Each segment represents the offset of a chain part to the pivot.
|
||||
@@ -81,7 +83,9 @@ static void chain_chomp_act_uninitialized(void) {
|
||||
cur_obj_unhide();
|
||||
}
|
||||
}
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -359,10 +363,12 @@ static void chain_chomp_act_move(void) {
|
||||
f32 maxDistToPivot;
|
||||
|
||||
// Unload chain if mario is far enough
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (o->oChainChompReleaseStatus == CHAIN_CHOMP_NOT_RELEASED && o->oDistanceToMario > 4000.0f) {
|
||||
o->oAction = CHAIN_CHOMP_ACT_UNLOAD_CHAIN;
|
||||
o->oForwardVel = o->oVelY = 0.0f;
|
||||
} else {
|
||||
+#endif
|
||||
cur_obj_update_floor_and_walls();
|
||||
|
||||
switch (o->oChainChompReleaseStatus) {
|
||||
@@ -446,7 +452,9 @@ static void chain_chomp_act_move(void) {
|
||||
o->oGravity = -4.0f;
|
||||
o->oChainChompTargetPitch = -0x3000;
|
||||
}
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/game/behaviors/coin.inc.c b/src/game/behaviors/coin.inc.c
|
||||
index 913c583..05619b9 100644
|
||||
--- a/src/game/behaviors/coin.inc.c
|
||||
+++ b/src/game/behaviors/coin.inc.c
|
||||
@@ -184,17 +184,23 @@ void bhv_coin_formation_loop(void) {
|
||||
s32 bitIndex;
|
||||
switch (o->oAction) {
|
||||
case 0:
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
+#endif
|
||||
for (bitIndex = 0; bitIndex < 8; bitIndex++) {
|
||||
if (!(o->oCoinUnkF4 & (1 << bitIndex)))
|
||||
spawn_coin_in_formation(bitIndex, o->oBehParams2ndByte);
|
||||
}
|
||||
o->oAction++;
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
+#endif
|
||||
break;
|
||||
case 1:
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario > 2100.0f)
|
||||
o->oAction++;
|
||||
+#endif
|
||||
break;
|
||||
case 2:
|
||||
o->oAction = 0;
|
||||
diff --git a/src/game/behaviors/fish.inc.c b/src/game/behaviors/fish.inc.c
|
||||
index 839ab8d..f652ef4 100644
|
||||
--- a/src/game/behaviors/fish.inc.c
|
||||
+++ b/src/game/behaviors/fish.inc.c
|
||||
@@ -42,7 +42,9 @@ void fish_act_spawn(void) {
|
||||
* If the current level is Secret Aquarium, ignore this requirement.
|
||||
* Fish moves at random with a max-range of 700.0f.
|
||||
*/
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < minDistToMario || gCurrLevelNum == LEVEL_SA) {
|
||||
+#endif
|
||||
for (i = 0; i < schoolQuantity; i++) {
|
||||
fishObject = spawn_object(o, model, bhvFish);
|
||||
fishObject->oBehParams2ndByte = o->oBehParams2ndByte;
|
||||
@@ -50,7 +52,9 @@ void fish_act_spawn(void) {
|
||||
obj_translate_xyz_random(fishObject, 700.0f);
|
||||
}
|
||||
o->oAction = FISH_ACT_ACTIVE;
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/game/behaviors/goomba.inc.c b/src/game/behaviors/goomba.inc.c
|
||||
index 2dab2fe..bf47dda 100644
|
||||
--- a/src/game/behaviors/goomba.inc.c
|
||||
+++ b/src/game/behaviors/goomba.inc.c
|
||||
@@ -78,7 +78,9 @@ void bhv_goomba_triplet_spawner_update(void) {
|
||||
// If mario is close enough and the goombas aren't currently loaded, then
|
||||
// spawn them
|
||||
if (o->oAction == GOOMBA_TRIPLET_SPAWNER_ACT_UNLOADED) {
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 3000.0f) {
|
||||
+#endif
|
||||
// The spawner is capable of spawning more than 3 goombas, but this
|
||||
// is not used in the game
|
||||
dAngle =
|
||||
@@ -98,11 +100,13 @@ void bhv_goomba_triplet_spawner_update(void) {
|
||||
}
|
||||
|
||||
o->oAction += 1;
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
} else if (o->oDistanceToMario > 4000.0f) {
|
||||
// If mario is too far away, enter the unloaded action. The goombas
|
||||
// will detect this and unload themselves
|
||||
o->oAction = GOOMBA_TRIPLET_SPAWNER_ACT_UNLOADED;
|
||||
+#endif
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/game/behaviors/heave_ho.inc.c b/src/game/behaviors/heave_ho.inc.c
|
||||
index 662bb0b..2f9da86 100644
|
||||
--- a/src/game/behaviors/heave_ho.inc.c
|
||||
+++ b/src/game/behaviors/heave_ho.inc.c
|
||||
@@ -73,14 +73,18 @@ void heave_ho_act_3(void) {
|
||||
|
||||
void heave_ho_act_0(void) {
|
||||
cur_obj_set_pos_to_home();
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (find_water_level(o->oPosX, o->oPosZ) < o->oPosY && o->oDistanceToMario < 4000.0f) {
|
||||
+#endif
|
||||
cur_obj_become_tangible();
|
||||
cur_obj_unhide();
|
||||
o->oAction = 1;
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
} else {
|
||||
cur_obj_become_intangible();
|
||||
cur_obj_hide();
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
void (*sHeaveHoActions[])(void) = { heave_ho_act_0, heave_ho_act_1, heave_ho_act_2, heave_ho_act_3 };
|
||||
diff --git a/src/game/behaviors/king_bobomb.inc.c b/src/game/behaviors/king_bobomb.inc.c
|
||||
index 63a7575..af1cb0a 100644
|
||||
--- a/src/game/behaviors/king_bobomb.inc.c
|
||||
+++ b/src/game/behaviors/king_bobomb.inc.c
|
||||
@@ -295,10 +295,14 @@ void king_bobomb_move(void) {
|
||||
cur_obj_move_using_fvel_and_gravity();
|
||||
cur_obj_call_action_function(sKingBobombActions);
|
||||
exec_anim_sound_state(sKingBobombSoundStates);
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 5000.0f)
|
||||
+#endif
|
||||
cur_obj_enable_rendering();
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
else
|
||||
cur_obj_disable_rendering();
|
||||
+#endif
|
||||
}
|
||||
|
||||
void bhv_king_bobomb_loop(void) {
|
||||
diff --git a/src/game/behaviors/pokey.inc.c b/src/game/behaviors/pokey.inc.c
|
||||
index df5d11f..cfcc92c 100644
|
||||
--- a/src/game/behaviors/pokey.inc.c
|
||||
+++ b/src/game/behaviors/pokey.inc.c
|
||||
@@ -151,7 +151,9 @@ static void pokey_act_uninitialized(void) {
|
||||
s32 i;
|
||||
s16 partModel;
|
||||
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
+#endif
|
||||
partModel = MODEL_POKEY_HEAD;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
@@ -170,7 +172,9 @@ static void pokey_act_uninitialized(void) {
|
||||
o->oPokeyNumAliveBodyParts = 5;
|
||||
o->oPokeyBottomBodyPartSize = 1.0f;
|
||||
o->oAction = POKEY_ACT_WANDER;
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,9 +189,11 @@ static void pokey_act_wander(void) {
|
||||
|
||||
if (o->oPokeyNumAliveBodyParts == 0) {
|
||||
obj_mark_for_deletion(o);
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
} else if (o->oDistanceToMario > 2500.0f) {
|
||||
o->oAction = POKEY_ACT_UNLOAD_PARTS;
|
||||
o->oForwardVel = 0.0f;
|
||||
+#endif
|
||||
} else {
|
||||
treat_far_home_as_mario(1000.0f);
|
||||
cur_obj_update_floor_and_walls();
|
||||
diff --git a/src/game/behaviors/snufit.inc.c b/src/game/behaviors/snufit.inc.c
|
||||
index f3a0c9e..76e78c0 100644
|
||||
--- a/src/game/behaviors/snufit.inc.c
|
||||
+++ b/src/game/behaviors/snufit.inc.c
|
||||
@@ -180,7 +180,11 @@ void bhv_snufit_loop(void) {
|
||||
void bhv_snufit_balls_loop(void) {
|
||||
// If far from Mario or in a different room, despawn.
|
||||
if ((o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
|| (o->oTimer != 0 && o->oDistanceToMario > 1500.0f)) {
|
||||
+#else
|
||||
+ || (o->oTimer != 0)) {
|
||||
+#endif
|
||||
obj_mark_for_deletion(o);
|
||||
}
|
||||
|
||||
diff --git a/src/game/behaviors/triplet_butterfly.inc.c b/src/game/behaviors/triplet_butterfly.inc.c
|
||||
index 1c2b926..3d16a9d 100644
|
||||
--- a/src/game/behaviors/triplet_butterfly.inc.c
|
||||
+++ b/src/game/behaviors/triplet_butterfly.inc.c
|
||||
@@ -54,9 +54,11 @@ static void triplet_butterfly_act_init(void) {
|
||||
}
|
||||
|
||||
static void triplet_butterfly_act_wander(void) {
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario > 1500.0f) {
|
||||
obj_mark_for_deletion(o);
|
||||
} else {
|
||||
+#endif
|
||||
approach_f32_ptr(&o->oTripletButterflySpeed, 8.0f, 0.5f);
|
||||
if (o->oTimer < 60) {
|
||||
o->oTripletButterflyTargetYaw = cur_obj_angle_to_home();
|
||||
@@ -82,7 +84,9 @@ static void triplet_butterfly_act_wander(void) {
|
||||
|
||||
obj_move_pitch_approach(o->oTripletButterflyTargetPitch, 400);
|
||||
cur_obj_rotate_yaw_toward(o->oTripletButterflyTargetYaw, random_linear_offset(400, 800));
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
static void triplet_butterfly_act_activate(void) {
|
||||
diff --git a/src/game/behaviors/water_bomb_cannon.inc.c b/src/game/behaviors/water_bomb_cannon.inc.c
|
||||
index 8e9ba33..fb82e43 100644
|
||||
--- a/src/game/behaviors/water_bomb_cannon.inc.c
|
||||
+++ b/src/game/behaviors/water_bomb_cannon.inc.c
|
||||
@@ -38,19 +38,27 @@ void bhv_bubble_cannon_barrel_loop(void) {
|
||||
}
|
||||
|
||||
void water_bomb_cannon_act_0(void) {
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
+#endif
|
||||
spawn_object(o, MODEL_CANNON_BARREL, bhvCannonBarrelBubbles);
|
||||
cur_obj_unhide();
|
||||
|
||||
o->oAction = 1;
|
||||
o->oMoveAnglePitch = o->oWaterCannonUnkFC = 0x1C00;
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
void water_bomb_cannon_act_1(void) {
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario > 2500.0f) {
|
||||
o->oAction = 2;
|
||||
} else if (o->oBehParams2ndByte == 0) {
|
||||
+#else
|
||||
+ if (o->oBehParams2ndByte == 0) {
|
||||
+#endif
|
||||
if (o->oWaterCannonUnkF4 != 0) {
|
||||
o->oWaterCannonUnkF4 -= 1;
|
||||
} else {
|
||||
diff --git a/src/game/behaviors/whirlpool.inc.c b/src/game/behaviors/whirlpool.inc.c
|
||||
index 405e051..5aebebd 100644
|
||||
--- a/src/game/behaviors/whirlpool.inc.c
|
||||
+++ b/src/game/behaviors/whirlpool.inc.c
|
||||
@@ -35,7 +35,9 @@ void whirpool_orient_graph(void) {
|
||||
}
|
||||
|
||||
void bhv_whirlpool_loop(void) {
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 5000.0f) {
|
||||
+#endif
|
||||
o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
|
||||
// not sure if actually an array
|
||||
@@ -52,10 +54,12 @@ void bhv_whirlpool_loop(void) {
|
||||
whirpool_orient_graph();
|
||||
|
||||
o->oFaceAngleYaw += 0x1F40;
|
||||
+#ifndef NODRAWINGDISTANCE
|
||||
} else {
|
||||
o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
|
||||
gEnvFxBubbleConfig[ENVFX_STATE_PARTICLECOUNT] = 0;
|
||||
}
|
||||
+#endif
|
||||
|
||||
cur_obj_play_sound_1(SOUND_ENV_WATER);
|
||||
|
|
@ -1109,11 +1109,7 @@
|
|||
* Vertex (set up for use with colors)
|
||||
*/
|
||||
typedef struct {
|
||||
#ifdef TARGET_N64
|
||||
short ob[3]; /* x, y, z */
|
||||
#else
|
||||
float ob[3]; /* x, y, z */
|
||||
#endif
|
||||
unsigned short flag;
|
||||
short tc[2]; /* texture coord */
|
||||
unsigned char cn[4]; /* color & alpha */
|
||||
|
@ -1123,11 +1119,7 @@ typedef struct {
|
|||
* Vertex (set up for use with normals)
|
||||
*/
|
||||
typedef struct {
|
||||
#ifdef TARGET_N64
|
||||
short ob[3]; /* x, y, z */
|
||||
#else
|
||||
float ob[3]; /* x, y, z */
|
||||
#endif
|
||||
unsigned short flag;
|
||||
short tc[2]; /* texture coord */
|
||||
signed char n[3]; /* normal */
|
||||
|
@ -1176,23 +1168,9 @@ typedef struct {
|
|||
unsigned char v[3];
|
||||
} Tri;
|
||||
|
||||
#ifdef TARGET_N64
|
||||
/*
|
||||
* 4x4 matrix, fixed point s15.16 format.
|
||||
* First 8 words are integer portion of the 4x4 matrix
|
||||
* Last 8 words are the fraction portion of the 4x4 matrix
|
||||
*/
|
||||
typedef s32 Mtx_t[4][4];
|
||||
|
||||
typedef union {
|
||||
Mtx_t m;
|
||||
long long int force_structure_alignment;
|
||||
} Mtx;
|
||||
#else
|
||||
typedef struct {
|
||||
float m[4][4];
|
||||
} Mtx;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Viewport
|
||||
|
|
|
@ -3,8 +3,28 @@
|
|||
|
||||
#include "ultratypes.h"
|
||||
|
||||
// Old deprecated functions from strings.h, replaced by memcpy/memset.
|
||||
// old bstring functions that aren't present on some platforms
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
// macOS libc has them
|
||||
#include <strings.h>
|
||||
|
||||
#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
|
||||
|
||||
// there's no way that shit's defined, use memcpy/memset
|
||||
#include <string.h>
|
||||
#undef bzero
|
||||
#undef bcopy
|
||||
#define bzero(buf, len) memset((buf), 0, (len))
|
||||
#define bcopy(src, dst, len) memcpy((dst), (src), (len))
|
||||
|
||||
#else
|
||||
|
||||
// hope for the best
|
||||
extern void bcopy(const void *, void *, size_t);
|
||||
extern void bzero(void *, size_t);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !_OS_LIBC_H_ */
|
||||
|
|
|
@ -29,13 +29,6 @@ typedef volatile s64 vs64;
|
|||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
#ifdef TARGET_N64
|
||||
typedef u32 size_t;
|
||||
typedef s32 ssize_t;
|
||||
typedef u32 uintptr_t;
|
||||
typedef s32 intptr_t;
|
||||
typedef s32 ptrdiff_t;
|
||||
#else
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#if defined(__MINGW32__)
|
||||
|
@ -47,5 +40,3 @@ typedef ptrdiff_t ssize_t;
|
|||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#ifndef CONFIG_H
|
||||
|
||||
#define CONFIG_H
|
||||
|
||||
/**
|
||||
|
@ -27,16 +28,7 @@
|
|||
#define SCREEN_WIDTH 320
|
||||
#define SCREEN_HEIGHT 240
|
||||
|
||||
// Border Height Define for NTSC Versions
|
||||
#ifdef TARGET_N64
|
||||
#ifndef VERSION_EU
|
||||
#define BORDER_HEIGHT 8
|
||||
#else
|
||||
#define BORDER_HEIGHT 1
|
||||
#endif
|
||||
#else
|
||||
// What's the point of having a border?
|
||||
#define BORDER_HEIGHT 0
|
||||
#endif
|
||||
// What's the point of having a border if we're not an N64?
|
||||
#define BORDER_HEIGHT 0 // Never use a border as not-N64
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef GFX_DIMENSIONS_H
|
||||
#define GFX_DIMENSIONS_H
|
||||
|
||||
#ifndef TARGET_N64
|
||||
#include <math.h>
|
||||
#include "pc/gfx/gfx_pc.h"
|
||||
#define GFX_DIMENSIONS_FROM_LEFT_EDGE(v) (SCREEN_WIDTH / 2 - SCREEN_HEIGHT / 2 * gfx_current_dimensions.aspect_ratio + (v))
|
||||
|
@ -9,12 +8,5 @@
|
|||
#define GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(v) ((int)floorf(GFX_DIMENSIONS_FROM_LEFT_EDGE(v)))
|
||||
#define GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(v) ((int)ceilf(GFX_DIMENSIONS_FROM_RIGHT_EDGE(v)))
|
||||
#define GFX_DIMENSIONS_ASPECT_RATIO (gfx_current_dimensions.aspect_ratio)
|
||||
#else
|
||||
#define GFX_DIMENSIONS_FROM_LEFT_EDGE(v) (v)
|
||||
#define GFX_DIMENSIONS_FROM_RIGHT_EDGE(v) (SCREEN_WIDTH - (v))
|
||||
#define GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(v) (v)
|
||||
#define GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(v) (SCREEN_WIDTH - (v))
|
||||
#define GFX_DIMENSIONS_ASPECT_RATIO (4.0f / 3.0f)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -46,20 +46,9 @@
|
|||
#define ALIGNED16
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_N64
|
||||
// convert a virtual address to physical.
|
||||
#define VIRTUAL_TO_PHYSICAL(addr) ((uintptr_t)(addr) & 0x1FFFFFFF)
|
||||
|
||||
// convert a physical address to virtual.
|
||||
#define PHYSICAL_TO_VIRTUAL(addr) ((uintptr_t)(addr) | 0x80000000)
|
||||
|
||||
// another way of converting virtual to physical
|
||||
#define VIRTUAL_TO_PHYSICAL2(addr) ((u8 *)(addr) - 0x80000000U)
|
||||
#else
|
||||
// no conversion for pc port other than cast
|
||||
#define VIRTUAL_TO_PHYSICAL(addr) ((uintptr_t)(addr))
|
||||
#define PHYSICAL_TO_VIRTUAL(addr) ((uintptr_t)(addr))
|
||||
#define VIRTUAL_TO_PHYSICAL2(addr) ((void *)(addr))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
#ifndef MAKE_CONST_NONCONST_H
|
||||
#define MAKE_CONST_NONCONST_H
|
||||
|
||||
#ifdef TARGET_N64
|
||||
// IDO sometimes puts const variables in .rodata and sometimes in .data, which breaks ordering.
|
||||
// This makes sure all variables are put into the same section (.data). We need to do this for
|
||||
// both IDO and gcc for TARGET_N64.
|
||||
#define const
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#ifndef PLATFORM_INFO_H
|
||||
#define PLATFORM_INFO_H
|
||||
|
||||
#ifdef TARGET_N64
|
||||
#define IS_64_BIT 0
|
||||
#define IS_BIG_ENDIAN 1
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#define IS_64_BIT (UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFU)
|
||||
#define IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
#endif
|
||||
|
||||
#define DOUBLE_SIZE_ON_64_BIT(size) ((size) * (sizeof(void *) / 4))
|
||||
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
#ifndef SEGMENT_SYMBOLS_H
|
||||
#define SEGMENT_SYMBOLS_H
|
||||
|
||||
#ifdef TARGET_N64
|
||||
#define DECLARE_SEGMENT(name) \
|
||||
extern u8 _##name##SegmentRomStart[]; \
|
||||
extern u8 _##name##SegmentRomEnd[];
|
||||
#else
|
||||
#define DECLARE_SEGMENT(name) \
|
||||
static u8 _##name##SegmentRomStart[1]; \
|
||||
static u8 _##name##SegmentRomEnd[1];
|
||||
#endif
|
||||
|
||||
#define DECLARE_ACTOR_SEGMENT(name) \
|
||||
DECLARE_SEGMENT(name##_mio0) \
|
||||
|
@ -43,11 +37,7 @@ DECLARE_ACTOR_SEGMENT(group17)
|
|||
DECLARE_SEGMENT(behavior)
|
||||
DECLARE_SEGMENT(scripts)
|
||||
DECLARE_SEGMENT(goddard)
|
||||
#ifdef TARGET_N64
|
||||
extern u8 _goddardSegmentStart[];
|
||||
#else
|
||||
static u8 _goddardSegmentStart[1];
|
||||
#endif
|
||||
|
||||
DECLARE_LEVEL_SEGMENT(menu)
|
||||
DECLARE_LEVEL_SEGMENT(intro)
|
||||
|
|
|
@ -3,20 +3,47 @@
|
|||
|
||||
#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")
|
||||
#define TEXT_OPT_CAMX _("Camera X Sensitivity")
|
||||
#define TEXT_OPT_CAMY _("Camera Y Sensitivity")
|
||||
#define TEXT_OPT_INVERTX _("Invert X Axis")
|
||||
#define TEXT_OPT_INVERTY _("Invert Y Axis")
|
||||
#define TEXT_OPT_CAMC _("Camera Centre Aggression")
|
||||
#define TEXT_OPT_CAMP _("Camera Pan Level")
|
||||
#define TEXT_OPT_CAMD _("Camera Deceleration")
|
||||
#define TEXT_OPT_ENABLED _("Enabled")
|
||||
#define TEXT_OPT_DISABLED _("Disabled")
|
||||
#define TEXT_OPT_BUTTON1 _("[R]: Options")
|
||||
#define TEXT_OPT_BUTTON2 _("[R]: Return")
|
||||
#define TEXT_OPT_OPTIONS _("OPTIONS")
|
||||
#define TEXT_OPT_CAMERA _("CAMERA")
|
||||
#define TEXT_OPT_CONTROLS _("CONTROLS")
|
||||
#define TEXT_OPT_VIDEO _("DISPLAY")
|
||||
#define TEXT_OPT_AUDIO _("SOUND")
|
||||
#define TEXT_OPT_HIGHLIGHT _("O")
|
||||
#define TEXT_OPT_ANALOGUE _("Analogue Camera")
|
||||
#define TEXT_OPT_MOUSE _("Mouse Look")
|
||||
#define TEXT_OPT_TEXFILTER _("Texture Filtering")
|
||||
#define TEXT_OPT_FSCREEN _("Fullscreen")
|
||||
#define TEXT_OPT_NEAREST _("Nearest")
|
||||
#define TEXT_OPT_LINEAR _("Linear")
|
||||
#define TEXT_OPT_MVOLUME _("Master Volume")
|
||||
|
||||
#define TEXT_OPT_UNBOUND _("NONE")
|
||||
#define TEXT_OPT_PRESSKEY _("...")
|
||||
#define TEXT_BIND_A _("A Button")
|
||||
#define TEXT_BIND_B _("B Button")
|
||||
#define TEXT_BIND_START _("Start Button")
|
||||
#define TEXT_BIND_L _("L Trigger")
|
||||
#define TEXT_BIND_R _("R Trigger")
|
||||
#define TEXT_BIND_Z _("Z Trigger")
|
||||
#define TEXT_BIND_C_UP _("C-Up")
|
||||
#define TEXT_BIND_C_DOWN _("C-Down")
|
||||
#define TEXT_BIND_C_LEFT _("C-Left")
|
||||
#define TEXT_BIND_C_RIGHT _("C-Right")
|
||||
#define TEXT_BIND_UP _("Stick Up")
|
||||
#define TEXT_BIND_DOWN _("Stick Down")
|
||||
#define TEXT_BIND_LEFT _("Stick Left")
|
||||
#define TEXT_BIND_RIGHT _("Stick Right")
|
||||
|
||||
/**
|
||||
* Global Symbols
|
||||
|
|
|
@ -72,19 +72,16 @@ const LevelScript level_main_menu_entry_2[] = {
|
|||
|
||||
/*25*/ FREE_LEVEL_POOL(),
|
||||
/*26*/ LOAD_AREA(/*area*/ 2),
|
||||
#ifndef TARGET_N64
|
||||
|
||||
// sVisibleStars is set to 0 during FIXED_LOAD above on N64, but not on PC-port.
|
||||
// lvl_init_act_selector_values_and_stars must be called here otherwise the
|
||||
// previous value is retained and causes incorrect drawing during the 16 transition
|
||||
// frames.
|
||||
CALL(/*arg*/ 0, /*func*/ lvl_init_act_selector_values_and_stars),
|
||||
#endif
|
||||
|
||||
/*27*/ TRANSITION(/*transType*/ WARP_TRANSITION_FADE_FROM_COLOR, /*time*/ 16, /*color*/ 0xFF, 0xFF, 0xFF),
|
||||
/*29*/ SLEEP(/*frames*/ 16),
|
||||
/*30*/ SET_MENU_MUSIC(/*seq*/ 0x000D),
|
||||
#ifdef TARGET_N64
|
||||
/*31*/ CALL(/*arg*/ 0, /*func*/ lvl_init_act_selector_values_and_stars),
|
||||
#endif
|
||||
/*33*/ CALL_LOOP(/*arg*/ 0, /*func*/ lvl_update_obj_and_load_act_button_actions),
|
||||
/*35*/ GET_OR_SET(/*op*/ OP_SET, /*var*/ VAR_CURR_ACT_NUM),
|
||||
/*36*/ STOP_MUSIC(/*fadeOutTime*/ 0x00BE),
|
||||
|
|
|
@ -1,49 +1,9 @@
|
|||
#include "libultra_internal.h"
|
||||
#ifndef TARGET_N64
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_N64
|
||||
void guMtxF2L(float mf[4][4], Mtx *m) {
|
||||
int r, c;
|
||||
s32 tmp1;
|
||||
s32 tmp2;
|
||||
s32 *m1 = &m->m[0][0];
|
||||
s32 *m2 = &m->m[2][0];
|
||||
for (r = 0; r < 4; r++) {
|
||||
for (c = 0; c < 2; c++) {
|
||||
tmp1 = mf[r][2 * c] * 65536.0f;
|
||||
tmp2 = mf[r][2 * c + 1] * 65536.0f;
|
||||
*m1++ = (tmp1 & 0xffff0000) | ((tmp2 >> 0x10) & 0xffff);
|
||||
*m2++ = ((tmp1 << 0x10) & 0xffff0000) | (tmp2 & 0xffff);
|
||||
}
|
||||
}
|
||||
}
|
||||
void guMtxL2F(float mf[4][4], Mtx *m) {
|
||||
int r, c;
|
||||
u32 tmp1;
|
||||
u32 tmp2;
|
||||
u32 *m1;
|
||||
u32 *m2;
|
||||
s32 stmp1, stmp2;
|
||||
m1 = (u32 *) &m->m[0][0];
|
||||
m2 = (u32 *) &m->m[2][0];
|
||||
for (r = 0; r < 4; r++) {
|
||||
for (c = 0; c < 2; c++) {
|
||||
tmp1 = (*m1 & 0xffff0000) | ((*m2 >> 0x10) & 0xffff);
|
||||
tmp2 = ((*m1++ << 0x10) & 0xffff0000) | (*m2++ & 0xffff);
|
||||
stmp1 = *(s32 *) &tmp1;
|
||||
stmp2 = *(s32 *) &tmp2;
|
||||
mf[r][c * 2 + 0] = stmp1 / 65536.0f;
|
||||
mf[r][c * 2 + 1] = stmp2 / 65536.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
void guMtxF2L(float mf[4][4], Mtx *m) {
|
||||
memcpy(m, mf, sizeof(Mtx));
|
||||
}
|
||||
#endif
|
||||
|
||||
void guMtxIdentF(float mf[4][4]) {
|
||||
int r, c;
|
||||
|
@ -58,11 +18,8 @@ void guMtxIdentF(float mf[4][4]) {
|
|||
}
|
||||
}
|
||||
void guMtxIdent(Mtx *m) {
|
||||
#ifdef TARGET_N64
|
||||
float mf[4][4];
|
||||
guMtxIdentF(mf);
|
||||
guMtxF2L(mf, m);
|
||||
#else
|
||||
|
||||
guMtxIdentF(m->m);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "libultra_internal.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef OSX_BUILD
|
||||
lldiv_t lldiv(long long num, long long denom) {
|
||||
lldiv_t ret;
|
||||
|
||||
|
@ -13,6 +14,7 @@ lldiv_t lldiv(long long num, long long denom) {
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif // OSX_BUILD cannot use this
|
||||
|
||||
ldiv_t ldiv(long num, long denom) {
|
||||
ldiv_t ret;
|
||||
|
|
|
@ -33,6 +33,7 @@ static const du pilo = {
|
|||
static const fu zero = {0.0};
|
||||
extern const fu NAN;
|
||||
|
||||
#ifndef OSX_BUILD
|
||||
float cosf(float x)
|
||||
{
|
||||
double dx; // double x
|
||||
|
@ -92,3 +93,5 @@ float cosf(float x)
|
|||
|
||||
return zero.f;
|
||||
}
|
||||
#endif // OSX_BUILD cannot use this
|
||||
|
||||
|
|
107
obj2c.py
Normal file
107
obj2c.py
Normal file
|
@ -0,0 +1,107 @@
|
|||
"""
|
||||
This module generates a fragment of C code, in the style of that found in
|
||||
the ``model.inc.c`` files, that encodes the geometry of the model specified
|
||||
by the Wavefront OBJ file.
|
||||
|
||||
Example:
|
||||
Specify the path to the ``.obj`` file and pipe the output of the script
|
||||
into the desired destination ``.c`` file.
|
||||
|
||||
$ python obj2c.py left_hand_closed.obj > left_hand_closed.inc.c
|
||||
|
||||
This is a work in progress and it currently has some serious limitations:
|
||||
* It only encodes the geometry information of the OBJ file, so no
|
||||
texture mapping or any other info.
|
||||
* The generated fragment of C code has to be manually pasted into the
|
||||
desired source file. Make sure that the name of the Gfx structure
|
||||
you're pasting matches the one you're replacing.
|
||||
* It hasn't been properly tested.
|
||||
|
||||
"""
|
||||
|
||||
def parse(filename):
|
||||
from os.path import basename, splitext
|
||||
from re import sub
|
||||
|
||||
# WARNIGN!
|
||||
# `gfx_name` is just a guess. You have to manually check that the name
|
||||
# of the Gfx structure you're pasting matches the one you're replacing.
|
||||
clean = lambda fn: sub('\W|^(?=\d)','_', fn)
|
||||
gfx_name = clean(splitext(basename(filename))[0])
|
||||
gfx_vertices = []
|
||||
gfx_normals = []
|
||||
vertex_to_normal = {}
|
||||
gfx_v_count = 0
|
||||
|
||||
vtx_name = ''
|
||||
vtx_faces = []
|
||||
vtx_v_count = 0
|
||||
|
||||
output_upper = []
|
||||
output_lower = [f'const Gfx {gfx_name}[] = {{']
|
||||
|
||||
with open(filename, 'r') as obj:
|
||||
for line in obj:
|
||||
line = line.strip()
|
||||
|
||||
if line.startswith('v '):
|
||||
coordinates = [eval(x) for x in line.split()[1:4]]
|
||||
gfx_vertices.append(coordinates)
|
||||
vtx_v_count += 1
|
||||
gfx_v_count += 1
|
||||
|
||||
if line.startswith('vn '):
|
||||
coordinates = [eval(x) for x in line.split()[1:4]]
|
||||
gfx_normals.append([_encode_normal(x) for x in coordinates])
|
||||
|
||||
if line.startswith('g '):
|
||||
vtx_name = line.split()[1]
|
||||
|
||||
if line.startswith('f '):
|
||||
pairs = [pair.split('//') for pair in line.split()[1:4]]
|
||||
vtx_faces.append([int(pair[0]) for pair in pairs])
|
||||
for (x, y) in pairs:
|
||||
vertex_to_normal[int(x) - 1] = int(y) - 1
|
||||
|
||||
if line.startswith('# ') and line.endswith('faces'):
|
||||
output_upper.append(f'static const Vtx {vtx_name}[] = {{')
|
||||
for i in range(gfx_v_count - vtx_v_count, gfx_v_count):
|
||||
v_string = '[{}, {}, {}]'.format(*gfx_vertices[i])
|
||||
n_string = '[{}, {}, {}, 0x00]'.format(*gfx_normals[vertex_to_normal[i]])
|
||||
combined = f' [[{v_string}, 0, [0, 0], {n_string}]],'
|
||||
output_upper.append(combined.replace('[', '{').replace(']', '}'))
|
||||
|
||||
output_upper.append('};\n')
|
||||
output_lower.append(f' gsSPVertex({vtx_name}, {vtx_v_count}, 0),')
|
||||
|
||||
n = len(vtx_faces)
|
||||
correction = vtx_v_count - gfx_v_count - 1
|
||||
for i in range(int(n / 2)):
|
||||
f1 = [vtx_faces[2 * i][j] + correction for j in range(3)]
|
||||
f2 = [vtx_faces[2 * i + 1][j] + correction for j in range(3)]
|
||||
output_lower.append(' gsSP2Triangles({}, {}, {}, 0x0, {}, {}, {}, 0x0),'.format(*f1, *f2))
|
||||
|
||||
if n % 2 != 0:
|
||||
f3 = [vtx_faces[-1][j] + correction for j in range(3)]
|
||||
output_lower.append(' gsSP1Triangle({}, {}, {}, 0x0),'.format(*f3))
|
||||
|
||||
vtx_v_count = 0
|
||||
vtx_faces = []
|
||||
|
||||
output_lower.append(' gsSPEndDisplayList(),')
|
||||
output_lower.append('};')
|
||||
|
||||
for line in output_upper + output_lower:
|
||||
print(line)
|
||||
|
||||
def _encode_normal(x):
|
||||
x *= 127
|
||||
if x <= 0: x += 255
|
||||
return hex(int(x))
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('filename', help = 'filename of the .obj file to parse')
|
||||
args = parser.parse_args()
|
||||
parse(args.filename)
|
|
@ -738,6 +738,7 @@ void func_8031D838(s32 player, FadeT fadeInTime, u8 targetVolume) {
|
|||
}
|
||||
seqPlayer->fadeVelocity =
|
||||
(((f32)(FLOAT_CAST(targetVolume) / EU_FLOAT(127.0)) - seqPlayer->fadeVolume) / (f32) fadeInTime);
|
||||
|
||||
#ifdef VERSION_EU
|
||||
seqPlayer->state = 0;
|
||||
#else
|
||||
|
@ -764,117 +765,15 @@ void func_eu_802e9bec(s32 player, s32 channel, s32 arg2) {
|
|||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef TARGET_N64
|
||||
struct SPTask *create_next_audio_frame_task(void) {
|
||||
u32 samplesRemainingInAI;
|
||||
s32 writtenCmds;
|
||||
s32 index;
|
||||
OSTask_t *task;
|
||||
s32 oldDmaCount;
|
||||
s32 flags;
|
||||
|
||||
gAudioFrameCount++;
|
||||
if (gAudioLoadLock != AUDIO_LOCK_NOT_LOADING) {
|
||||
stubbed_printf("DAC:Lost 1 Frame.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gAudioTaskIndex ^= 1;
|
||||
gCurrAiBufferIndex++;
|
||||
gCurrAiBufferIndex %= NUMAIBUFFERS;
|
||||
index = (gCurrAiBufferIndex - 2 + NUMAIBUFFERS) % NUMAIBUFFERS;
|
||||
samplesRemainingInAI = osAiGetLength() / 4;
|
||||
|
||||
// Audio is triple buffered; the audio interface reads from two buffers
|
||||
// while the third is being written by the RSP. More precisely, the
|
||||
// lifecycle is:
|
||||
// - this function computes an audio command list
|
||||
// - wait for vblank
|
||||
// - the command list is sent to the RSP (we could have sent it to the
|
||||
// RSP before the vblank, but that gives the RSP less time to finish)
|
||||
// - wait for vblank
|
||||
// - the RSP is now expected to be finished, and we can send its output
|
||||
// on to the AI
|
||||
// Here we thus send to the AI the sound that was generated two frames ago.
|
||||
if (gAiBufferLengths[index] != 0) {
|
||||
osAiSetNextBuffer(gAiBuffers[index], gAiBufferLengths[index] * 4);
|
||||
}
|
||||
|
||||
oldDmaCount = gCurrAudioFrameDmaCount;
|
||||
// There has to be some sort of no-op if here, but it's not exactly clear
|
||||
// how it should look... It's also very unclear why gCurrAudioFrameDmaQueue
|
||||
// isn't read from here, despite gCurrAudioFrameDmaCount being reset.
|
||||
if (oldDmaCount > AUDIO_FRAME_DMA_QUEUE_SIZE) {
|
||||
stubbed_printf("DMA: Request queue over.( %d )\n", oldDmaCount);
|
||||
}
|
||||
gCurrAudioFrameDmaCount = 0;
|
||||
|
||||
gAudioTask = &gAudioTasks[gAudioTaskIndex];
|
||||
gAudioCmd = gAudioCmdBuffers[gAudioTaskIndex];
|
||||
|
||||
index = gCurrAiBufferIndex;
|
||||
gCurrAiBuffer = gAiBuffers[index];
|
||||
gAiBufferLengths[index] = ((gSamplesPerFrameTarget - samplesRemainingInAI +
|
||||
EXTRA_BUFFERED_AI_SAMPLES_TARGET) & ~0xf) + SAMPLES_TO_OVERPRODUCE;
|
||||
if (gAiBufferLengths[index] < gMinAiBufferLength) {
|
||||
gAiBufferLengths[index] = gMinAiBufferLength;
|
||||
}
|
||||
if (gAiBufferLengths[index] > gSamplesPerFrameTarget + SAMPLES_TO_OVERPRODUCE) {
|
||||
gAiBufferLengths[index] = gSamplesPerFrameTarget + SAMPLES_TO_OVERPRODUCE;
|
||||
}
|
||||
|
||||
if (sGameLoopTicked != 0) {
|
||||
update_game_sound();
|
||||
sGameLoopTicked = 0;
|
||||
}
|
||||
|
||||
// For the function to match we have to preserve some arbitrary variable
|
||||
// across this function call.
|
||||
flags = 0;
|
||||
gAudioCmd = synthesis_execute(gAudioCmd, &writtenCmds, gCurrAiBuffer, gAiBufferLengths[index]);
|
||||
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
|
||||
|
||||
index = gAudioTaskIndex;
|
||||
gAudioTask->msgqueue = NULL;
|
||||
gAudioTask->msg = NULL;
|
||||
|
||||
task = &gAudioTask->task.t;
|
||||
task->type = M_AUDTASK;
|
||||
task->flags = flags;
|
||||
task->ucode_boot = rspF3DBootStart;
|
||||
task->ucode_boot_size = (u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart;
|
||||
task->ucode = rspAspMainStart;
|
||||
task->ucode_size = 0x800; // (this size is ignored)
|
||||
task->ucode_data = rspAspMainDataStart;
|
||||
task->ucode_data_size = (rspAspMainDataEnd - rspAspMainDataStart) * sizeof(u64);
|
||||
task->dram_stack = NULL;
|
||||
task->dram_stack_size = 0;
|
||||
task->output_buff = NULL;
|
||||
task->output_buff_size = NULL;
|
||||
task->data_ptr = gAudioCmdBuffers[index];
|
||||
task->data_size = writtenCmds * sizeof(u64);
|
||||
|
||||
// The audio task never yields, so having a yield buffer is pointless.
|
||||
// This wastefulness was fixed in US.
|
||||
#ifdef VERSION_JP
|
||||
task->yield_data_ptr = (u64 *) gAudioSPTaskYieldBuffer;
|
||||
task->yield_data_size = OS_YIELD_AUDIO_SIZE;
|
||||
#else
|
||||
task->yield_data_ptr = NULL;
|
||||
task->yield_data_size = 0;
|
||||
// Stubbed N64-US/JP audio code
|
||||
// continue;
|
||||
#endif
|
||||
|
||||
decrease_sample_dma_ttls();
|
||||
return gAudioTask;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_N64
|
||||
struct SPTask *create_next_audio_frame_task(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void create_next_audio_buffer(s16 *samples, u32 num_samples) {
|
||||
gAudioFrameCount++;
|
||||
if (sGameLoopTicked != 0) {
|
||||
|
@ -886,7 +785,6 @@ void create_next_audio_buffer(s16 *samples, u32 num_samples) {
|
|||
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
|
||||
decrease_sample_dma_ttls();
|
||||
}
|
||||
#endif
|
||||
|
||||
void play_sound(s32 soundBits, f32 *pos) {
|
||||
sSoundRequests[sSoundRequestCount].soundBits = soundBits;
|
||||
|
|
|
@ -651,12 +651,7 @@ s32 audio_shut_down_and_reset_step(void) {
|
|||
*/
|
||||
void wait_for_audio_frames(s32 frames) {
|
||||
gAudioFrameCount = 0;
|
||||
#ifdef TARGET_N64
|
||||
// Sound thread will update gAudioFrameCount
|
||||
while (gAudioFrameCount < frames) {
|
||||
// spin
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -507,9 +507,6 @@ struct Note
|
|||
/* U/J, EU */
|
||||
/*0xA4, 0x00*/ struct AudioListItem listItem;
|
||||
/* 0x10*/ struct NoteSynthesisState synthesisState;
|
||||
#ifdef TARGET_N64
|
||||
u8 pad0[12];
|
||||
#endif
|
||||
/*0x04, 0x30*/ u8 priority;
|
||||
/* 0x31*/ u8 waveId;
|
||||
/* 0x32*/ u8 sampleCountIndex;
|
||||
|
|
|
@ -34,107 +34,6 @@ void decrease_sample_dma_ttls(void);
|
|||
s32 audio_shut_down_and_reset_step(void);
|
||||
void func_802ad7ec(u32);
|
||||
|
||||
#ifdef TARGET_N64
|
||||
struct SPTask *create_next_audio_frame_task(void) {
|
||||
u32 samplesRemainingInAI;
|
||||
s32 writtenCmds;
|
||||
s32 index;
|
||||
OSTask_t *task;
|
||||
s32 flags;
|
||||
u16 *currAiBuffer;
|
||||
s32 oldDmaCount;
|
||||
OSMesg sp30;
|
||||
OSMesg sp2C;
|
||||
|
||||
gAudioFrameCount++;
|
||||
if (gAudioFrameCount % gAudioBufferParameters.presetUnk4 != 0) {
|
||||
stubbed_printf("DAC:Lost 1 Frame.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
osSendMesg(OSMesgQueues[0], (OSMesg) gAudioFrameCount, 0);
|
||||
|
||||
gAudioTaskIndex ^= 1;
|
||||
gCurrAiBufferIndex++;
|
||||
gCurrAiBufferIndex %= NUMAIBUFFERS;
|
||||
index = (gCurrAiBufferIndex - 2 + NUMAIBUFFERS) % NUMAIBUFFERS;
|
||||
samplesRemainingInAI = osAiGetLength() / 4;
|
||||
|
||||
if (gAiBufferLengths[index] != 0) {
|
||||
osAiSetNextBuffer(gAiBuffers[index], gAiBufferLengths[index] * 4);
|
||||
}
|
||||
|
||||
oldDmaCount = gCurrAudioFrameDmaCount;
|
||||
if (oldDmaCount > AUDIO_FRAME_DMA_QUEUE_SIZE) {
|
||||
stubbed_printf("DMA: Request queue over.( %d )\n", oldDmaCount);
|
||||
}
|
||||
gCurrAudioFrameDmaCount = 0;
|
||||
|
||||
decrease_sample_dma_ttls();
|
||||
if (osRecvMesg(OSMesgQueues[2], &sp30, 0) != -1) {
|
||||
gAudioResetPresetIdToLoad = (u8) (s32) sp30;
|
||||
gAudioResetStatus = 5;
|
||||
}
|
||||
|
||||
if (gAudioResetStatus != 0) {
|
||||
if (audio_shut_down_and_reset_step() == 0) {
|
||||
if (gAudioResetStatus == 0) {
|
||||
osSendMesg(OSMesgQueues[3], (OSMesg) (s32) gAudioResetPresetIdToLoad, OS_MESG_NOBLOCK);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gAudioTask = &gAudioTasks[gAudioTaskIndex];
|
||||
gAudioCmd = gAudioCmdBuffers[gAudioTaskIndex];
|
||||
index = gCurrAiBufferIndex;
|
||||
currAiBuffer = gAiBuffers[index];
|
||||
|
||||
gAiBufferLengths[index] = ((gAudioBufferParameters.samplesPerFrameTarget - samplesRemainingInAI +
|
||||
EXTRA_BUFFERED_AI_SAMPLES_TARGET) & ~0xf) + SAMPLES_TO_OVERPRODUCE;
|
||||
if (gAiBufferLengths[index] < gAudioBufferParameters.minAiBufferLength) {
|
||||
gAiBufferLengths[index] = gAudioBufferParameters.minAiBufferLength;
|
||||
}
|
||||
if (gAiBufferLengths[index] > gAudioBufferParameters.maxAiBufferLength) {
|
||||
gAiBufferLengths[index] = gAudioBufferParameters.maxAiBufferLength;
|
||||
}
|
||||
|
||||
if (osRecvMesg(OSMesgQueues[1], &sp2C, OS_MESG_NOBLOCK) != -1) {
|
||||
func_802ad7ec((u32) sp2C);
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
gAudioCmd = synthesis_execute(gAudioCmd, &writtenCmds, currAiBuffer, gAiBufferLengths[index]);
|
||||
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
|
||||
gAudioRandom = gAudioRandom + writtenCmds / 8;
|
||||
|
||||
index = gAudioTaskIndex;
|
||||
gAudioTask->msgqueue = NULL;
|
||||
gAudioTask->msg = NULL;
|
||||
|
||||
task = &gAudioTask->task.t;
|
||||
task->type = M_AUDTASK;
|
||||
task->flags = flags;
|
||||
#if TARGET_N64
|
||||
task->ucode_boot = rspF3DBootStart;
|
||||
task->ucode_boot_size = (u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart;
|
||||
task->ucode = rspAspMainStart;
|
||||
task->ucode_data = rspAspMainDataStart;
|
||||
task->ucode_size = 0x800; // (this size is ignored)
|
||||
task->ucode_data_size = (rspAspMainDataEnd - rspAspMainDataStart) * sizeof(u64);
|
||||
#endif
|
||||
task->dram_stack = NULL;
|
||||
task->dram_stack_size = 0;
|
||||
task->output_buff = NULL;
|
||||
task->output_buff_size = NULL;
|
||||
task->data_ptr = gAudioCmdBuffers[index];
|
||||
task->data_size = writtenCmds * sizeof(u64);
|
||||
task->yield_data_ptr = NULL;
|
||||
task->yield_data_size = 0;
|
||||
return gAudioTask;
|
||||
}
|
||||
#endif
|
||||
|
||||
void eu_process_audio_cmd(struct EuAudioCmd *cmd) {
|
||||
s32 i;
|
||||
|
||||
|
|
|
@ -8,10 +8,7 @@
|
|||
#include "seqplayer.h"
|
||||
#include "external.h"
|
||||
|
||||
|
||||
#ifndef TARGET_N64
|
||||
#include "../pc/mixer.h"
|
||||
#endif
|
||||
|
||||
#define DMEM_ADDR_TEMP 0x0
|
||||
#define DMEM_ADDR_UNCOMPRESSED_NOTE 0x180
|
||||
|
|
|
@ -27,11 +27,8 @@ extern struct SaveBuffer gSaveBuffer;
|
|||
|
||||
extern u8 gGfxSPTaskStack[];
|
||||
|
||||
#ifdef TARGET_N64
|
||||
#define GFX_NUM_POOLS 2
|
||||
#else
|
||||
#define GFX_NUM_POOLS 1
|
||||
#endif
|
||||
|
||||
extern struct GfxPool gGfxPools[GFX_NUM_POOLS];
|
||||
|
||||
#endif
|
||||
|
|
|
@ -98,10 +98,10 @@ static void cur_obj_bhv_stack_push(uintptr_t bhvAddr) {
|
|||
// Retrieve the last behavior command address from the object's behavior stack.
|
||||
static uintptr_t cur_obj_bhv_stack_pop(void) {
|
||||
uintptr_t bhvAddr;
|
||||
|
||||
|
||||
gCurrentObject->bhvStackIndex--;
|
||||
bhvAddr = gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex];
|
||||
|
||||
|
||||
return bhvAddr;
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ static void stub_behavior_script_1(void) {
|
|||
// Usage: HIDE()
|
||||
static s32 bhv_cmd_hide(void) {
|
||||
cur_obj_hide();
|
||||
|
||||
|
||||
gCurBhvCommand++;
|
||||
return BHV_PROC_CONTINUE;
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ static s32 bhv_cmd_hide(void) {
|
|||
// Usage: DISABLE_RENDERING()
|
||||
static s32 bhv_cmd_disable_rendering(void) {
|
||||
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
|
||||
|
||||
|
||||
gCurBhvCommand++;
|
||||
return BHV_PROC_CONTINUE;
|
||||
}
|
||||
|
@ -133,7 +133,15 @@ static s32 bhv_cmd_disable_rendering(void) {
|
|||
// Usage: BILLBOARD()
|
||||
static s32 bhv_cmd_billboard(void) {
|
||||
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_BILLBOARD;
|
||||
|
||||
|
||||
gCurBhvCommand++;
|
||||
return BHV_PROC_CONTINUE;
|
||||
}
|
||||
|
||||
// Command 0x
|
||||
static s32 bhv_cmd_cylboard(void) {
|
||||
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_CYLBOARD;
|
||||
|
||||
gCurBhvCommand++;
|
||||
return BHV_PROC_CONTINUE;
|
||||
}
|
||||
|
@ -142,9 +150,9 @@ static s32 bhv_cmd_billboard(void) {
|
|||
// Usage: SET_MODEL(modelID)
|
||||
static s32 bhv_cmd_set_model(void) {
|
||||
s32 modelID = BHV_CMD_GET_2ND_S16(0);
|
||||
|
||||
|
||||
gCurrentObject->header.gfx.sharedChild = gLoadedGraphNodes[modelID];
|
||||
|
||||
|
||||
gCurBhvCommand++;
|
||||
return BHV_PROC_CONTINUE;
|
||||
}
|
||||
|
@ -216,7 +224,7 @@ static s32 bhv_cmd_break_unused(void) {
|
|||
static s32 bhv_cmd_call(void) {
|
||||
const BehaviorScript *jumpAddress;
|
||||
gCurBhvCommand++;
|
||||
|
||||
|
||||
cur_obj_bhv_stack_push(BHV_CMD_GET_ADDR_OF_CMD(1)); // Store address of the next bhv command in the stack.
|
||||
jumpAddress = segmented_to_virtual(BHV_CMD_GET_VPTR(0));
|
||||
gCurBhvCommand = jumpAddress; // Jump to the new address.
|
||||
|
@ -300,7 +308,7 @@ static s32 bhv_cmd_begin_repeat(void) {
|
|||
static s32 bhv_cmd_end_repeat(void) {
|
||||
u32 count = cur_obj_bhv_stack_pop(); // Retrieve loop count from the stack.
|
||||
count--;
|
||||
|
||||
|
||||
if (count != 0) {
|
||||
gCurBhvCommand = (const BehaviorScript *) cur_obj_bhv_stack_pop(); // Jump back to the first command in the loop
|
||||
// Save address and count to the stack again
|
||||
|
@ -320,7 +328,7 @@ static s32 bhv_cmd_end_repeat(void) {
|
|||
static s32 bhv_cmd_end_repeat_continue(void) {
|
||||
u32 count = cur_obj_bhv_stack_pop();
|
||||
count--;
|
||||
|
||||
|
||||
if (count != 0) {
|
||||
gCurBhvCommand = (const BehaviorScript *) cur_obj_bhv_stack_pop(); // Jump back to the first command in the loop
|
||||
// Save address and count to the stack again
|
||||
|
@ -546,7 +554,7 @@ static s32 bhv_cmd_drop_to_floor(void) {
|
|||
f32 x = gCurrentObject->oPosX;
|
||||
f32 y = gCurrentObject->oPosY;
|
||||
f32 z = gCurrentObject->oPosZ;
|
||||
|
||||
|
||||
f32 floor = find_floor_height(x, y + 200.0f, z);
|
||||
gCurrentObject->oPosY = floor;
|
||||
gCurrentObject->oMoveFlags |= OBJ_MOVE_ON_GROUND;
|
||||
|
@ -665,7 +673,7 @@ static s32 bhv_cmd_nop_4(void) {
|
|||
static s32 bhv_cmd_begin(void) {
|
||||
// These objects were likely very early objects, which is why this code is here
|
||||
// instead of in the respective behavior scripts.
|
||||
|
||||
|
||||
// Initiate the room if the object is a haunted chair or the mad piano.
|
||||
if (cur_obj_has_behavior(bhvHauntedChair)) {
|
||||
bhv_init_room();
|
||||
|
@ -696,7 +704,7 @@ static void bhv_cmd_set_int_random_from_table(s32 tableSize) {
|
|||
}
|
||||
|
||||
cur_obj_set_int(field, table[(s32)(tableSize * random_float())]);
|
||||
|
||||
|
||||
// Does not increment gCurBhvCommand or return a bhv status
|
||||
}
|
||||
|
||||
|
@ -719,7 +727,7 @@ static s32 bhv_cmd_set_int_random_from_table(void) {
|
|||
|
||||
// Set the field to a random entry of the table.
|
||||
cur_obj_set_int(field, table[(s32)(tableSize * random_float())]);
|
||||
|
||||
|
||||
gCurBhvCommand += (tableSize / 2) + 1;
|
||||
return BHV_PROC_CONTINUE;
|
||||
}
|
||||
|
@ -729,9 +737,9 @@ static s32 bhv_cmd_set_int_random_from_table(void) {
|
|||
// Usage: LOAD_COLLISION_DATA(collisionData)
|
||||
static s32 bhv_cmd_load_collision_data(void) {
|
||||
u32 *collisionData = segmented_to_virtual(BHV_CMD_GET_VPTR(1));
|
||||
|
||||
|
||||
gCurrentObject->collisionData = collisionData;
|
||||
|
||||
|
||||
gCurBhvCommand += 2;
|
||||
return BHV_PROC_CONTINUE;
|
||||
}
|
||||
|
@ -742,7 +750,7 @@ static s32 bhv_cmd_set_home(void) {
|
|||
gCurrentObject->oHomeX = gCurrentObject->oPosX;
|
||||
gCurrentObject->oHomeY = gCurrentObject->oPosY;
|
||||
gCurrentObject->oHomeZ = gCurrentObject->oPosZ;
|
||||
|
||||
|
||||
gCurBhvCommand++;
|
||||
return BHV_PROC_CONTINUE;
|
||||
}
|
||||
|
@ -815,9 +823,9 @@ static s32 bhv_cmd_parent_bit_clear(void) {
|
|||
// Usage: SPAWN_WATER_DROPLET(dropletParams)
|
||||
static s32 bhv_cmd_spawn_water_droplet(void) {
|
||||
struct WaterDropletParams *dropletParams = BHV_CMD_GET_VPTR(1);
|
||||
|
||||
|
||||
spawn_water_droplet(gCurrentObject, dropletParams);
|
||||
|
||||
|
||||
gCurBhvCommand += 2;
|
||||
return BHV_PROC_CONTINUE;
|
||||
}
|
||||
|
@ -842,62 +850,63 @@ void stub_behavior_script_2(void) {
|
|||
|
||||
typedef s32 (*BhvCommandProc)(void);
|
||||
static BhvCommandProc BehaviorCmdTable[] = {
|
||||
bhv_cmd_begin,
|
||||
bhv_cmd_delay,
|
||||
bhv_cmd_call,
|
||||
bhv_cmd_return,
|
||||
bhv_cmd_goto,
|
||||
bhv_cmd_begin_repeat,
|
||||
bhv_cmd_end_repeat,
|
||||
bhv_cmd_end_repeat_continue,
|
||||
bhv_cmd_begin_loop,
|
||||
bhv_cmd_end_loop,
|
||||
bhv_cmd_break,
|
||||
bhv_cmd_break_unused,
|
||||
bhv_cmd_call_native,
|
||||
bhv_cmd_add_float,
|
||||
bhv_cmd_set_float,
|
||||
bhv_cmd_add_int,
|
||||
bhv_cmd_set_int,
|
||||
bhv_cmd_or_int,
|
||||
bhv_cmd_bit_clear,
|
||||
bhv_cmd_set_int_rand_rshift,
|
||||
bhv_cmd_set_random_float,
|
||||
bhv_cmd_set_random_int,
|
||||
bhv_cmd_add_random_float,
|
||||
bhv_cmd_add_int_rand_rshift,
|
||||
bhv_cmd_nop_1,
|
||||
bhv_cmd_nop_2,
|
||||
bhv_cmd_nop_3,
|
||||
bhv_cmd_set_model,
|
||||
bhv_cmd_spawn_child,
|
||||
bhv_cmd_deactivate,
|
||||
bhv_cmd_drop_to_floor,
|
||||
bhv_cmd_sum_float,
|
||||
bhv_cmd_sum_int,
|
||||
bhv_cmd_billboard,
|
||||
bhv_cmd_hide,
|
||||
bhv_cmd_set_hitbox,
|
||||
bhv_cmd_nop_4,
|
||||
bhv_cmd_delay_var,
|
||||
bhv_cmd_begin_repeat_unused,
|
||||
bhv_cmd_load_animations,
|
||||
bhv_cmd_animate,
|
||||
bhv_cmd_spawn_child_with_param,
|
||||
bhv_cmd_load_collision_data,
|
||||
bhv_cmd_set_hitbox_with_offset,
|
||||
bhv_cmd_spawn_obj,
|
||||
bhv_cmd_set_home,
|
||||
bhv_cmd_set_hurtbox,
|
||||
bhv_cmd_set_interact_type,
|
||||
bhv_cmd_set_obj_physics,
|
||||
bhv_cmd_set_interact_subtype,
|
||||
bhv_cmd_scale,
|
||||
bhv_cmd_parent_bit_clear,
|
||||
bhv_cmd_animate_texture,
|
||||
bhv_cmd_disable_rendering,
|
||||
bhv_cmd_set_int_unused,
|
||||
bhv_cmd_spawn_water_droplet,
|
||||
bhv_cmd_begin, //00
|
||||
bhv_cmd_delay, //01
|
||||
bhv_cmd_call, //02
|
||||
bhv_cmd_return, //03
|
||||
bhv_cmd_goto, //04
|
||||
bhv_cmd_begin_repeat, //05
|
||||
bhv_cmd_end_repeat, //06
|
||||
bhv_cmd_end_repeat_continue, //07
|
||||
bhv_cmd_begin_loop, //08
|
||||
bhv_cmd_end_loop, //09
|
||||
bhv_cmd_break, //0A
|
||||
bhv_cmd_break_unused, //0B
|
||||
bhv_cmd_call_native, //0C
|
||||
bhv_cmd_add_float, //0D
|
||||
bhv_cmd_set_float, //0E
|
||||
bhv_cmd_add_int, //0F
|
||||
bhv_cmd_set_int, //10
|
||||
bhv_cmd_or_int, //11
|
||||
bhv_cmd_bit_clear, //12
|
||||
bhv_cmd_set_int_rand_rshift, //13
|
||||
bhv_cmd_set_random_float, //14
|
||||
bhv_cmd_set_random_int, //15
|
||||
bhv_cmd_add_random_float, //16
|
||||
bhv_cmd_add_int_rand_rshift, //17
|
||||
bhv_cmd_nop_1, //18
|
||||
bhv_cmd_nop_2, //19
|
||||
bhv_cmd_nop_3, //1A
|
||||
bhv_cmd_set_model, //1B
|
||||
bhv_cmd_spawn_child, //1C
|
||||
bhv_cmd_deactivate, //1D
|
||||
bhv_cmd_drop_to_floor, //1E
|
||||
bhv_cmd_sum_float, //1F
|
||||
bhv_cmd_sum_int, //20
|
||||
bhv_cmd_billboard, //21
|
||||
bhv_cmd_hide, //22
|
||||
bhv_cmd_set_hitbox, //23
|
||||
bhv_cmd_nop_4, //24
|
||||
bhv_cmd_delay_var, //25
|
||||
bhv_cmd_begin_repeat_unused, //26
|
||||
bhv_cmd_load_animations, //27
|
||||
bhv_cmd_animate, //28
|
||||
bhv_cmd_spawn_child_with_param, //29
|
||||
bhv_cmd_load_collision_data, //2A
|
||||
bhv_cmd_set_hitbox_with_offset, //2B
|
||||
bhv_cmd_spawn_obj, //2C
|
||||
bhv_cmd_set_home, //2D
|
||||
bhv_cmd_set_hurtbox, //2E
|
||||
bhv_cmd_set_interact_type, //2F
|
||||
bhv_cmd_set_obj_physics, //30
|
||||
bhv_cmd_set_interact_subtype, //31
|
||||
bhv_cmd_scale, //32
|
||||
bhv_cmd_parent_bit_clear, //33
|
||||
bhv_cmd_animate_texture, //34
|
||||
bhv_cmd_disable_rendering, //35
|
||||
bhv_cmd_set_int_unused, //36
|
||||
bhv_cmd_spawn_water_droplet, //37
|
||||
bhv_cmd_cylboard //38
|
||||
};
|
||||
|
||||
// Execute the behavior script of the current object, process the object flags, and other miscellaneous code for updating objects.
|
||||
|
@ -987,11 +996,15 @@ void cur_obj_update(void) {
|
|||
} else if ((objFlags & OBJ_FLAG_COMPUTE_DIST_TO_MARIO) && gCurrentObject->collisionData == NULL) {
|
||||
if (!(objFlags & OBJ_FLAG_ACTIVE_FROM_AFAR)) {
|
||||
// If the object has a render distance, check if it should be shown.
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (distanceFromMario > gCurrentObject->oDrawingDistance) {
|
||||
// Out of render distance, hide the object.
|
||||
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
|
||||
gCurrentObject->activeFlags |= ACTIVE_FLAG_FAR_AWAY;
|
||||
} else if (gCurrentObject->oHeldState == HELD_FREE) {
|
||||
#else
|
||||
if (distanceFromMario <= gCurrentObject->oDrawingDistance && gCurrentObject->oHeldState == HELD_FREE) {
|
||||
#endif
|
||||
// In render distance (and not being held), show the object.
|
||||
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
|
||||
gCurrentObject->activeFlags &= ~ACTIVE_FLAG_FAR_AWAY;
|
||||
|
|
|
@ -30,12 +30,13 @@ extern Vec3s gVec3sOne;
|
|||
#define GRAPH_RENDER_Z_BUFFER (1 << 3)
|
||||
#define GRAPH_RENDER_INVISIBLE (1 << 4)
|
||||
#define GRAPH_RENDER_HAS_ANIMATION (1 << 5)
|
||||
#define GRAPH_RENDER_CYLBOARD (1 << 6)
|
||||
|
||||
// Whether the node type has a function pointer of type GraphNodeFunc
|
||||
#define GRAPH_NODE_TYPE_FUNCTIONAL 0x100
|
||||
|
||||
// Type used for Bowser and an unused geo function in obj_behaviors.c
|
||||
#define GRAPH_NODE_TYPE_400 0x400
|
||||
#define GRAPH_NODE_TYPE_400 0x400
|
||||
|
||||
// The discriminant for different types of geo nodes
|
||||
#define GRAPH_NODE_TYPE_ROOT 0x001
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include <ultra64.h>
|
||||
#ifndef TARGET_N64
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "sm64.h"
|
||||
#include "audio/external.h"
|
||||
|
@ -605,9 +604,7 @@ static void level_cmd_set_gamma(void) {
|
|||
|
||||
static void level_cmd_set_terrain_data(void) {
|
||||
if (sCurrAreaIndex != -1) {
|
||||
#ifdef TARGET_N64
|
||||
gAreas[sCurrAreaIndex].terrainData = segmented_to_virtual(CMD_GET(void *, 4));
|
||||
#else
|
||||
|
||||
Collision *data;
|
||||
u32 size;
|
||||
|
||||
|
@ -615,7 +612,7 @@ static void level_cmd_set_terrain_data(void) {
|
|||
size = get_area_terrain_size(data) * sizeof(Collision);
|
||||
gAreas[sCurrAreaIndex].terrainData = alloc_only_pool_alloc(sLevelPool, size);
|
||||
memcpy(gAreas[sCurrAreaIndex].terrainData, data, size);
|
||||
#endif
|
||||
|
||||
}
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
}
|
||||
|
@ -629,9 +626,7 @@ static void level_cmd_set_rooms(void) {
|
|||
|
||||
static void level_cmd_set_macro_objects(void) {
|
||||
if (sCurrAreaIndex != -1) {
|
||||
#ifdef TARGET_N64
|
||||
gAreas[sCurrAreaIndex].macroObjects = segmented_to_virtual(CMD_GET(void *, 4));
|
||||
#else
|
||||
|
||||
MacroObject *data = segmented_to_virtual(CMD_GET(void *, 4));
|
||||
s32 len = 0;
|
||||
while (data[len++] != 0x001E) {
|
||||
|
@ -639,7 +634,7 @@ static void level_cmd_set_macro_objects(void) {
|
|||
}
|
||||
gAreas[sCurrAreaIndex].macroObjects = alloc_only_pool_alloc(sLevelPool, len * sizeof(MacroObject));
|
||||
memcpy(gAreas[sCurrAreaIndex].macroObjects, data, len * sizeof(MacroObject));
|
||||
#endif
|
||||
|
||||
}
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
}
|
||||
|
|
|
@ -377,6 +377,31 @@ void mtxf_billboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle) {
|
|||
dest[3][3] = 1;
|
||||
}
|
||||
|
||||
void mtxf_cylboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle) { //straight up mtxf_billboard but minus the dest[1][n] lines. transform for cylindrical billboards
|
||||
dest[0][0] = coss(angle);
|
||||
dest[0][1] = sins(angle);
|
||||
dest[0][2] = 0;
|
||||
dest[0][3] = 0;
|
||||
|
||||
dest[1][0] = mtx[1][0];
|
||||
dest[1][1] = mtx[1][1];
|
||||
dest[1][2] = mtx[1][2];
|
||||
dest[1][3] = 0;
|
||||
|
||||
dest[2][0] = 0;
|
||||
dest[2][1] = 0;
|
||||
dest[2][2] = 1;
|
||||
dest[2][3] = 0;
|
||||
|
||||
dest[3][0] =
|
||||
mtx[0][0] * position[0] + mtx[1][0] * position[1] + mtx[2][0] * position[2] + mtx[3][0];
|
||||
dest[3][1] =
|
||||
mtx[0][1] * position[0] + mtx[1][1] * position[1] + mtx[2][1] * position[2] + mtx[3][1];
|
||||
dest[3][2] =
|
||||
mtx[0][2] * position[0] + mtx[1][2] * position[1] + mtx[2][2] * position[2] + mtx[3][2];
|
||||
dest[3][3] = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set 'dest' to a transformation matrix that aligns an object with the terrain
|
||||
* based on the normal. Used for enemies.
|
||||
|
|
|
@ -56,6 +56,7 @@ void mtxf_lookat(f32 mtx[4][4], Vec3f b, Vec3f c, s16 d);
|
|||
void mtxf_rotate_zxy_and_translate(f32 mtx[4][4], Vec3f b, Vec3s c);
|
||||
void mtxf_rotate_xyz_and_translate(f32 mtx[4][4], Vec3f b, Vec3s c);
|
||||
void mtxf_billboard(f32 mtx1[4][4], f32 mtx2[4][4], Vec3f c, s16 d);
|
||||
void mtxf_cylboard(f32 mtx1[4][4], f32 mtx2[4][4], Vec3f c, s16 d);
|
||||
void mtxf_align_terrain_normal(f32 mtx[4][4], Vec3f b, Vec3f c, s16 d);
|
||||
void mtxf_align_terrain_triangle(f32 mtx[4][4], Vec3f b, s16 c, f32 d);
|
||||
void mtxf_mul(f32 dest[4][4], f32 a[4][4], f32 b[4][4]);
|
||||
|
|
|
@ -533,7 +533,6 @@ void alloc_surface_pools(void) {
|
|||
reset_red_coins_collected();
|
||||
}
|
||||
|
||||
#ifndef TARGET_N64
|
||||
/**
|
||||
* Get the size of the terrain data, to get the correct size when copying later.
|
||||
*/
|
||||
|
@ -581,8 +580,6 @@ u32 get_area_terrain_size(s16 *data) {
|
|||
|
||||
return data - startPos;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Process the level file, loading in vertices, surfaces, some objects, and environmental
|
||||
|
@ -789,9 +786,13 @@ void load_object_collision_model(void) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (marioDist < gCurrentObject->oDrawingDistance) {
|
||||
#endif
|
||||
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
} else {
|
||||
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -28,9 +28,9 @@ extern struct Surface *sSurfacePool;
|
|||
extern s16 sSurfacePoolSize;
|
||||
|
||||
void alloc_surface_pools(void);
|
||||
#ifndef TARGET_N64
|
||||
|
||||
u32 get_area_terrain_size(s16 *data);
|
||||
#endif
|
||||
|
||||
void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects);
|
||||
void clear_dynamic_surfaces(void);
|
||||
void load_object_collision_model(void);
|
||||
|
|
|
@ -8,11 +8,15 @@
|
|||
void bub_spawner_act_0(void) {
|
||||
s32 i;
|
||||
s32 sp18 = o->oBirdChirpChirpUnkF4;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 1500.0f) {
|
||||
#endif
|
||||
for (i = 0; i < sp18; i++)
|
||||
spawn_object(o, MODEL_BUB, bhvBub);
|
||||
o->oAction = 1;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void bub_spawner_act_1(void) {
|
||||
|
|
|
@ -17,9 +17,11 @@ void opened_cannon_act_0(void) {
|
|||
cur_obj_enable_rendering();
|
||||
cur_obj_become_tangible();
|
||||
}
|
||||
cur_obj_become_tangible();
|
||||
cur_obj_enable_rendering();
|
||||
if (o->oDistanceToMario < 500.0f) {
|
||||
cur_obj_become_tangible();
|
||||
cur_obj_enable_rendering();
|
||||
//cur_obj_become_tangible();
|
||||
//cur_obj_enable_rendering();
|
||||
if (o->oInteractStatus & INT_STATUS_INTERACTED
|
||||
&& (!(o->oInteractStatus
|
||||
& INT_STATUS_TOUCHED_BOB_OMB))) // bob-omb explodes when it gets into a cannon
|
||||
|
@ -30,8 +32,8 @@ void opened_cannon_act_0(void) {
|
|||
} else
|
||||
o->oInteractStatus = 0;
|
||||
} else {
|
||||
cur_obj_become_intangible();
|
||||
cur_obj_disable_rendering();
|
||||
//cur_obj_become_intangible();
|
||||
//cur_obj_disable_rendering();
|
||||
o->oCannonUnk10C = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,9 @@ static void chain_chomp_act_uninitialized(void) {
|
|||
struct ChainSegment *segments;
|
||||
s32 i;
|
||||
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 3000.0f) {
|
||||
#endif
|
||||
segments = mem_pool_alloc(gObjectMemoryPool, 5 * sizeof(struct ChainSegment));
|
||||
if (segments != NULL) {
|
||||
// Each segment represents the offset of a chain part to the pivot.
|
||||
|
@ -81,7 +83,9 @@ static void chain_chomp_act_uninitialized(void) {
|
|||
cur_obj_unhide();
|
||||
}
|
||||
}
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -359,10 +363,12 @@ static void chain_chomp_act_move(void) {
|
|||
f32 maxDistToPivot;
|
||||
|
||||
// Unload chain if mario is far enough
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oChainChompReleaseStatus == CHAIN_CHOMP_NOT_RELEASED && o->oDistanceToMario > 4000.0f) {
|
||||
o->oAction = CHAIN_CHOMP_ACT_UNLOAD_CHAIN;
|
||||
o->oForwardVel = o->oVelY = 0.0f;
|
||||
} else {
|
||||
#endif
|
||||
cur_obj_update_floor_and_walls();
|
||||
|
||||
switch (o->oChainChompReleaseStatus) {
|
||||
|
@ -446,7 +452,9 @@ static void chain_chomp_act_move(void) {
|
|||
o->oGravity = -4.0f;
|
||||
o->oChainChompTargetPitch = -0x3000;
|
||||
}
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -47,10 +47,14 @@ static void cloud_act_spawn_parts(void) {
|
|||
* Wait for mario to approach, then unhide and enter the spawn parts action.
|
||||
*/
|
||||
static void cloud_act_fwoosh_hidden(void) {
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
#endif
|
||||
cur_obj_unhide();
|
||||
o->oAction = CLOUD_ACT_SPAWN_PARTS;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,9 +62,11 @@ static void cloud_act_fwoosh_hidden(void) {
|
|||
* long enough, blow wind at him.
|
||||
*/
|
||||
static void cloud_fwoosh_update(void) {
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario > 2500.0f) {
|
||||
o->oAction = CLOUD_ACT_UNLOAD;
|
||||
} else {
|
||||
#endif
|
||||
if (o->oCloudBlowing) {
|
||||
o->header.gfx.scale[0] += o->oCloudGrowSpeed;
|
||||
|
||||
|
@ -95,7 +101,9 @@ static void cloud_fwoosh_update(void) {
|
|||
}
|
||||
|
||||
cur_obj_scale(o->header.gfx.scale[0]);
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -184,17 +184,23 @@ void bhv_coin_formation_loop(void) {
|
|||
s32 bitIndex;
|
||||
switch (o->oAction) {
|
||||
case 0:
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
#endif
|
||||
for (bitIndex = 0; bitIndex < 8; bitIndex++) {
|
||||
if (!(o->oCoinUnkF4 & (1 << bitIndex)))
|
||||
spawn_coin_in_formation(bitIndex, o->oBehParams2ndByte);
|
||||
}
|
||||
o->oAction++;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 1:
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario > 2100.0f)
|
||||
o->oAction++;
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
o->oAction = 0;
|
||||
|
|
|
@ -24,12 +24,16 @@ static struct ObjectHitbox sEnemyLakituHitbox = {
|
|||
* Wait for mario to approach, then spawn the cloud and become visible.
|
||||
*/
|
||||
static void enemy_lakitu_act_uninitialized(void) {
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
#endif
|
||||
spawn_object_relative_with_scale(CLOUD_BP_LAKITU_CLOUD, 0, 0, 0, 2.0f, o, MODEL_MIST, bhvCloud);
|
||||
|
||||
cur_obj_unhide();
|
||||
o->oAction = ENEMY_LAKITU_ACT_MAIN;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -42,7 +42,9 @@ void fish_act_spawn(void) {
|
|||
* If the current level is Secret Aquarium, ignore this requirement.
|
||||
* Fish moves at random with a max-range of 700.0f.
|
||||
*/
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < minDistToMario || gCurrLevelNum == LEVEL_SA) {
|
||||
#endif
|
||||
for (i = 0; i < schoolQuantity; i++) {
|
||||
fishObject = spawn_object(o, model, bhvFish);
|
||||
fishObject->oBehParams2ndByte = o->oBehParams2ndByte;
|
||||
|
@ -50,7 +52,9 @@ void fish_act_spawn(void) {
|
|||
obj_translate_xyz_random(fishObject, 700.0f);
|
||||
}
|
||||
o->oAction = FISH_ACT_ACTIVE;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -78,7 +78,9 @@ void bhv_goomba_triplet_spawner_update(void) {
|
|||
// If mario is close enough and the goombas aren't currently loaded, then
|
||||
// spawn them
|
||||
if (o->oAction == GOOMBA_TRIPLET_SPAWNER_ACT_UNLOADED) {
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 3000.0f) {
|
||||
#endif
|
||||
// The spawner is capable of spawning more than 3 goombas, but this
|
||||
// is not used in the game
|
||||
dAngle =
|
||||
|
@ -98,11 +100,13 @@ void bhv_goomba_triplet_spawner_update(void) {
|
|||
}
|
||||
|
||||
o->oAction += 1;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
} else if (o->oDistanceToMario > 4000.0f) {
|
||||
// If mario is too far away, enter the unloaded action. The goombas
|
||||
// will detect this and unload themselves
|
||||
o->oAction = GOOMBA_TRIPLET_SPAWNER_ACT_UNLOADED;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,8 +72,12 @@ void heave_ho_act_3(void) {
|
|||
}
|
||||
|
||||
void heave_ho_act_0(void) {
|
||||
cur_obj_set_pos_to_home();
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (find_water_level(o->oPosX, o->oPosZ) < o->oPosY && o->oDistanceToMario < 4000.0f) {
|
||||
#else
|
||||
if (find_water_level(o->oPosX, o->oPosZ) < (o->oPosY - 50.0f)) {
|
||||
#endif
|
||||
cur_obj_set_pos_to_home();
|
||||
cur_obj_become_tangible();
|
||||
cur_obj_unhide();
|
||||
o->oAction = 1;
|
||||
|
|
|
@ -295,10 +295,14 @@ void king_bobomb_move(void) {
|
|||
cur_obj_move_using_fvel_and_gravity();
|
||||
cur_obj_call_action_function(sKingBobombActions);
|
||||
exec_anim_sound_state(sKingBobombSoundStates);
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 5000.0f)
|
||||
#endif
|
||||
cur_obj_enable_rendering();
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
else
|
||||
cur_obj_disable_rendering();
|
||||
#endif
|
||||
}
|
||||
|
||||
void bhv_king_bobomb_loop(void) {
|
||||
|
|
|
@ -14,18 +14,24 @@ void bhv_lll_floating_wood_bridge_loop(void) {
|
|||
s32 i;
|
||||
switch (o->oAction) {
|
||||
case 0:
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 2500.0f) {
|
||||
#endif
|
||||
for (i = 1; i < 4; i++) {
|
||||
sp3C = spawn_object_relative(0, (i - 2) * 300, 0, 0, o, MODEL_LLL_WOOD_BRIDGE,
|
||||
bhvLllWoodPiece);
|
||||
sp3C->oLllWoodPieceUnkF4 = i * 4096;
|
||||
}
|
||||
o->oAction = 1;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 1:
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario > 2600.0f)
|
||||
o->oAction = 2;
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
o->oAction = 0;
|
||||
|
|
|
@ -30,7 +30,9 @@ void fire_bar_spawn_flames(s16 a0) {
|
|||
}
|
||||
|
||||
void fire_bar_act_0(void) {
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 3000.0f)
|
||||
#endif
|
||||
o->oAction = 1;
|
||||
}
|
||||
|
||||
|
@ -45,8 +47,10 @@ void fire_bar_act_1(void) {
|
|||
void fire_bar_act_2(void) {
|
||||
o->oAngleVelYaw = -0x100;
|
||||
o->oMoveAngleYaw += o->oAngleVelYaw;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario > 3200.0f)
|
||||
o->oAction = 3;
|
||||
#endif
|
||||
}
|
||||
|
||||
void fire_bar_act_3(void) {
|
||||
|
|
|
@ -328,7 +328,7 @@ void (*TablePiranhaPlantActions[])(void) = {
|
|||
*/
|
||||
void bhv_piranha_plant_loop(void) {
|
||||
cur_obj_call_action_function(TablePiranhaPlantActions);
|
||||
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
// In WF, hide all Piranha Plants once high enough up.
|
||||
if (gCurrLevelNum == LEVEL_WF) {
|
||||
if (gMarioObject->oPosY > 3400.0f)
|
||||
|
@ -336,5 +336,6 @@ void bhv_piranha_plant_loop(void) {
|
|||
else
|
||||
cur_obj_unhide();
|
||||
}
|
||||
#endif
|
||||
o->oInteractStatus = 0;
|
||||
}
|
||||
|
|
|
@ -151,7 +151,9 @@ static void pokey_act_uninitialized(void) {
|
|||
s32 i;
|
||||
s16 partModel;
|
||||
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
#endif
|
||||
partModel = MODEL_POKEY_HEAD;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
|
@ -170,7 +172,9 @@ static void pokey_act_uninitialized(void) {
|
|||
o->oPokeyNumAliveBodyParts = 5;
|
||||
o->oPokeyBottomBodyPartSize = 1.0f;
|
||||
o->oAction = POKEY_ACT_WANDER;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,9 +189,11 @@ static void pokey_act_wander(void) {
|
|||
|
||||
if (o->oPokeyNumAliveBodyParts == 0) {
|
||||
obj_mark_for_deletion(o);
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
} else if (o->oDistanceToMario > 2500.0f) {
|
||||
o->oAction = POKEY_ACT_UNLOAD_PARTS;
|
||||
o->oForwardVel = 0.0f;
|
||||
#endif
|
||||
} else {
|
||||
treat_far_home_as_mario(1000.0f);
|
||||
cur_obj_update_floor_and_walls();
|
||||
|
|
|
@ -97,7 +97,9 @@ void bhv_sl_walking_penguin_loop(void) {
|
|||
}
|
||||
|
||||
cur_obj_move_standard(-78);
|
||||
if (!cur_obj_hide_if_mario_far_away_y(1000.0f))
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (!cur_obj_hide_if_mario_far_away_y(1000.0f))
|
||||
#endif
|
||||
play_penguin_walking_sound(PENGUIN_WALK_BIG);
|
||||
|
||||
// Adjust the position to get a point better lined up with the visual model, for stopping the wind.
|
||||
|
|
|
@ -180,7 +180,11 @@ void bhv_snufit_loop(void) {
|
|||
void bhv_snufit_balls_loop(void) {
|
||||
// If far from Mario or in a different room, despawn.
|
||||
if ((o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
|| (o->oTimer != 0 && o->oDistanceToMario > 1500.0f)) {
|
||||
#else
|
||||
|| (o->oTimer != 0)) {
|
||||
#endif
|
||||
obj_mark_for_deletion(o);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,9 +54,11 @@ static void triplet_butterfly_act_init(void) {
|
|||
}
|
||||
|
||||
static void triplet_butterfly_act_wander(void) {
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario > 1500.0f) {
|
||||
obj_mark_for_deletion(o);
|
||||
} else {
|
||||
#endif
|
||||
approach_f32_ptr(&o->oTripletButterflySpeed, 8.0f, 0.5f);
|
||||
if (o->oTimer < 60) {
|
||||
o->oTripletButterflyTargetYaw = cur_obj_angle_to_home();
|
||||
|
@ -82,7 +84,9 @@ static void triplet_butterfly_act_wander(void) {
|
|||
|
||||
obj_move_pitch_approach(o->oTripletButterflyTargetPitch, 400);
|
||||
cur_obj_rotate_yaw_toward(o->oTripletButterflyTargetYaw, random_linear_offset(400, 800));
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void triplet_butterfly_act_activate(void) {
|
||||
|
|
|
@ -38,19 +38,27 @@ void bhv_bubble_cannon_barrel_loop(void) {
|
|||
}
|
||||
|
||||
void water_bomb_cannon_act_0(void) {
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 2000.0f) {
|
||||
#endif
|
||||
spawn_object(o, MODEL_CANNON_BARREL, bhvCannonBarrelBubbles);
|
||||
cur_obj_unhide();
|
||||
|
||||
o->oAction = 1;
|
||||
o->oMoveAnglePitch = o->oWaterCannonUnkFC = 0x1C00;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void water_bomb_cannon_act_1(void) {
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario > 2500.0f) {
|
||||
o->oAction = 2;
|
||||
} else if (o->oBehParams2ndByte == 0) {
|
||||
#else
|
||||
if (o->oBehParams2ndByte == 0) {
|
||||
#endif
|
||||
if (o->oWaterCannonUnkF4 != 0) {
|
||||
o->oWaterCannonUnkF4 -= 1;
|
||||
} else {
|
||||
|
|
|
@ -35,7 +35,9 @@ void whirpool_orient_graph(void) {
|
|||
}
|
||||
|
||||
void bhv_whirlpool_loop(void) {
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (o->oDistanceToMario < 5000.0f) {
|
||||
#endif
|
||||
o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
|
||||
// not sure if actually an array
|
||||
|
@ -52,10 +54,12 @@ void bhv_whirlpool_loop(void) {
|
|||
whirpool_orient_graph();
|
||||
|
||||
o->oFaceAngleYaw += 0x1F40;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
} else {
|
||||
o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
|
||||
gEnvFxBubbleConfig[ENVFX_STATE_PARTICLECOUNT] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
cur_obj_play_sound_1(SOUND_ENV_WATER);
|
||||
|
||||
|
|
|
@ -246,10 +246,14 @@ void bhv_whomp_loop(void) {
|
|||
cur_obj_call_action_function(sWhompActions);
|
||||
cur_obj_move_standard(-20);
|
||||
if (o->oAction != 9) {
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
// o->oBehParams2ndByte here seems to be a flag
|
||||
// indicating whether this is a normal or king whomp
|
||||
if (o->oBehParams2ndByte != 0)
|
||||
cur_obj_hide_if_mario_far_away_y(2000.0f);
|
||||
else
|
||||
cur_obj_hide_if_mario_far_away_y(1000.0f);
|
||||
#endif
|
||||
load_object_collision_model();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,14 +26,9 @@ enum newcam_flagvalues
|
|||
|
||||
};
|
||||
|
||||
extern void newcam_display_options(void);
|
||||
extern void newcam_check_pause_buttons(void);
|
||||
extern void newcam_init_settings(void);
|
||||
extern void newcam_save_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;
|
||||
|
|
|
@ -31,8 +31,6 @@ NC_MODE_NOTURN: Disables horizontal and vertical control of the camera.
|
|||
//#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.
|
||||
|
@ -91,6 +89,7 @@ s16 newcam_yaw_target; // The yaw value the camera tries to set itself to when t
|
|||
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;
|
||||
f32 newcam_degrade = 0.1f; //What percent of the remaining camera movement is degraded. Default is 10%
|
||||
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;
|
||||
|
||||
|
@ -108,17 +107,6 @@ 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;
|
||||
|
@ -169,18 +157,7 @@ void newcam_init_settings(void)
|
|||
newcam_invertY = (u8)configCameraInvertY;
|
||||
newcam_mouse = (u8)configCameraMouse;
|
||||
newcam_analogue = (u8)configEnableCamera;
|
||||
}
|
||||
|
||||
void newcam_save_settings(void)
|
||||
{
|
||||
configCameraXSens = newcam_sensitivityX;
|
||||
configCameraYSens = newcam_sensitivityY;
|
||||
configCameraAggr = newcam_aggression;
|
||||
configCameraPan = newcam_panlevel;
|
||||
configCameraInvertX = newcam_invertX != 0;
|
||||
configCameraInvertY = newcam_invertY != 0;
|
||||
configEnableCamera = newcam_analogue != 0;
|
||||
configCameraMouse = newcam_mouse != 0;
|
||||
newcam_degrade = (f32)configCameraDegrade / 100.0f;
|
||||
}
|
||||
|
||||
/** Mathematic calculations. This stuffs so basic even *I* understand it lol
|
||||
|
@ -294,7 +271,7 @@ static void newcam_rotate_button(void)
|
|||
#ifdef noaccel
|
||||
newcam_yaw_acc = 0;
|
||||
#else
|
||||
newcam_yaw_acc -= (newcam_yaw_acc*(DEGRADE));
|
||||
newcam_yaw_acc -= (newcam_yaw_acc*newcam_degrade);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -306,7 +283,7 @@ static void newcam_rotate_button(void)
|
|||
#ifdef noaccel
|
||||
newcam_tilt_acc = 0;
|
||||
#else
|
||||
newcam_tilt_acc -= (newcam_tilt_acc*(DEGRADE));
|
||||
newcam_tilt_acc -= (newcam_tilt_acc*newcam_degrade);
|
||||
#endif
|
||||
|
||||
newcam_framessincec[0] += 1;
|
||||
|
@ -372,13 +349,13 @@ static void newcam_rotate_button(void)
|
|||
else
|
||||
{
|
||||
newcam_cstick_down = 0;
|
||||
newcam_yaw_acc -= (newcam_yaw_acc*(DEGRADE));
|
||||
newcam_yaw_acc -= (newcam_yaw_acc*newcam_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));
|
||||
newcam_tilt_acc -= (newcam_tilt_acc*newcam_degrade);
|
||||
}
|
||||
|
||||
if (newcam_mouse == 1)
|
||||
|
@ -404,8 +381,8 @@ static void newcam_zoom_button(void)
|
|||
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)
|
||||
//When you press L, 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 && newcam_modeflags & NC_FLAG_ZOOM)
|
||||
{
|
||||
newcam_yaw_target = -gMarioState->faceAngle[1]-0x4000;
|
||||
newcam_centering = 1;
|
||||
|
@ -673,234 +650,10 @@ void newcam_loop(struct Camera *c)
|
|||
newcam_position_cam();
|
||||
newcam_find_fixed();
|
||||
if (gMarioObject)
|
||||
newcam_apply_values(c);
|
||||
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:
|
||||
newcam_sensitivityX = newcam_clamp(newcam_sensitivityX + toggle, 10, 250);
|
||||
break;
|
||||
case 3:
|
||||
newcam_sensitivityY = newcam_clamp(newcam_sensitivityY + toggle, 10, 250);
|
||||
break;
|
||||
case 4:
|
||||
newcam_invertX ^= 1;
|
||||
break;
|
||||
case 5:
|
||||
newcam_invertY ^= 1;
|
||||
break;
|
||||
case 6:
|
||||
newcam_aggression = newcam_clamp(newcam_aggression + toggle, 0, 100);
|
||||
break;
|
||||
case 7:
|
||||
newcam_panlevel = newcam_clamp(newcam_panlevel + toggle, 0, 100);
|
||||
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)
|
||||
{
|
||||
if (newcam_option_open == 0)
|
||||
{
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs);
|
||||
#endif
|
||||
newcam_option_open = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_MARIO_CASTLE_WARP2, gDefaultSoundArgs);
|
||||
#endif
|
||||
newcam_option_open = 0;
|
||||
newcam_save_settings();
|
||||
}
|
||||
}
|
||||
|
||||
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 += 3; 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 += 3; 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "sm64.h"
|
||||
#include "audio/external.h"
|
||||
#include "buffers/buffers.h"
|
||||
#include "gfx_dimensions.h"
|
||||
#include "buffers/gfx_output_buffer.h"
|
||||
#include "buffers/framebuffers.h"
|
||||
#include "buffers/zbuffer.h"
|
||||
|
@ -152,8 +153,9 @@ void clear_frame_buffer(s32 a) {
|
|||
gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
|
||||
|
||||
gDPSetFillColor(gDisplayListHead++, a);
|
||||
gDPFillRectangle(gDisplayListHead++, 0, BORDER_HEIGHT, SCREEN_WIDTH - 1,
|
||||
SCREEN_HEIGHT - 1 - BORDER_HEIGHT);
|
||||
|
||||
// Ratio-correct borderfill
|
||||
gDPFillRectangle(gDisplayListHead++, GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(0), BORDER_HEIGHT, GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(0) - 1, SCREEN_HEIGHT - BORDER_HEIGHT - 1);
|
||||
|
||||
gDPPipeSync(gDisplayListHead++);
|
||||
|
||||
|
@ -217,13 +219,7 @@ void create_task_structure(void) {
|
|||
gGfxSPTask->msgqueue = &D_80339CB8;
|
||||
gGfxSPTask->msg = (OSMesg) 2;
|
||||
gGfxSPTask->task.t.type = M_GFXTASK;
|
||||
#if TARGET_N64
|
||||
gGfxSPTask->task.t.ucode_boot = rspF3DBootStart;
|
||||
gGfxSPTask->task.t.ucode_boot_size = ((u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart);
|
||||
gGfxSPTask->task.t.flags = 0;
|
||||
gGfxSPTask->task.t.ucode = rspF3DStart;
|
||||
gGfxSPTask->task.t.ucode_data = rspF3DDataStart;
|
||||
#endif
|
||||
|
||||
gGfxSPTask->task.t.ucode_size = SP_UCODE_SIZE; // (this size is ignored)
|
||||
gGfxSPTask->task.t.ucode_data_size = SP_UCODE_DATA_SIZE;
|
||||
gGfxSPTask->task.t.dram_stack = (u64 *) gGfxSPTaskStack;
|
||||
|
@ -267,33 +263,9 @@ void end_master_display_list(void) {
|
|||
create_task_structure();
|
||||
}
|
||||
|
||||
void draw_reset_bars(void) {
|
||||
s32 sp24;
|
||||
s32 sp20;
|
||||
s32 fbNum;
|
||||
u64 *sp18;
|
||||
|
||||
if (gResetTimer != 0 && D_8032C648 < 15) {
|
||||
if (sCurrFBNum == 0) {
|
||||
fbNum = 2;
|
||||
} else {
|
||||
fbNum = sCurrFBNum - 1;
|
||||
}
|
||||
|
||||
sp18 = (u64 *) PHYSICAL_TO_VIRTUAL(gPhysicalFrameBuffers[fbNum]);
|
||||
sp18 += D_8032C648++ * (SCREEN_WIDTH / 4);
|
||||
|
||||
for (sp24 = 0; sp24 < ((SCREEN_HEIGHT / 16) + 1); sp24++) {
|
||||
// Must be on one line to match -O2
|
||||
for (sp20 = 0; sp20 < (SCREEN_WIDTH / 4); sp20++) *sp18++ = 0;
|
||||
sp18 += ((SCREEN_WIDTH / 4) * 14);
|
||||
}
|
||||
}
|
||||
|
||||
osWritebackDCacheAll();
|
||||
osRecvMesg(&gGameVblankQueue, &D_80339BEC, OS_MESG_BLOCK);
|
||||
osRecvMesg(&gGameVblankQueue, &D_80339BEC, OS_MESG_BLOCK);
|
||||
}
|
||||
//void draw_reset_bars(void) { // TARGET_64 only
|
||||
// Stubbed. Only N64 target uses this
|
||||
// }
|
||||
|
||||
void rendering_init(void) {
|
||||
gGfxPool = &gGfxPools[0];
|
||||
|
@ -525,7 +497,7 @@ void read_controller_inputs(void) {
|
|||
controller->stickMag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#else
|
||||
for (i = 0; i < 2; i++) {
|
||||
|
@ -626,16 +598,12 @@ void setup_game_memory(void) {
|
|||
load_segment_decompress(2, _segment2_mio0SegmentRomStart, _segment2_mio0SegmentRomEnd);
|
||||
}
|
||||
|
||||
#ifndef TARGET_N64
|
||||
|
||||
static struct LevelCommand *levelCommandAddr;
|
||||
#endif
|
||||
|
||||
// main game loop thread. runs forever as long as the game
|
||||
// continues.
|
||||
void thread5_game_loop(UNUSED void *arg) {
|
||||
#ifdef TARGET_N64
|
||||
struct LevelCommand *levelCommandAddr;
|
||||
#endif
|
||||
|
||||
setup_game_memory();
|
||||
#ifdef VERSION_SH
|
||||
|
@ -655,32 +623,21 @@ void thread5_game_loop(UNUSED void *arg) {
|
|||
play_music(SEQ_PLAYER_SFX, SEQUENCE_ARGS(0, SEQ_SOUND_PLAYER), 0);
|
||||
set_sound_mode(save_file_get_sound_mode());
|
||||
|
||||
#ifdef TARGET_N64
|
||||
func_80247ED8();
|
||||
rendering_init();
|
||||
|
||||
while (1) {
|
||||
#else
|
||||
gGlobalTimer++;
|
||||
}
|
||||
|
||||
void game_loop_one_iteration(void) {
|
||||
#endif
|
||||
// if the reset timer is active, run the process to reset the game.
|
||||
if (gResetTimer) {
|
||||
//if (gResetTimer) {
|
||||
// draw_reset_bars(); (N64 target only?)
|
||||
//}
|
||||
|
||||
#ifdef TARGET_N64
|
||||
draw_reset_bars();
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
profiler_log_thread5_time(THREAD5_START);
|
||||
|
||||
// if any controllers are plugged in, start read the data for when
|
||||
// read_controller_inputs is called later.
|
||||
if (gControllerBits) {
|
||||
|
||||
#ifdef VERSION_SH
|
||||
block_until_rumble_pak_free();
|
||||
#endif
|
||||
|
@ -699,7 +656,5 @@ void game_loop_one_iteration(void) {
|
|||
// amount of free space remaining.
|
||||
print_text_fmt_int(180, 20, "BUF %d", gGfxPoolEnd - (u8 *) gDisplayListHead);
|
||||
}
|
||||
#ifdef TARGET_N64
|
||||
}
|
||||
#endif
|
||||
// } was here for ifdef targ 64
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ extern void clear_viewport(Vp *, s32);
|
|||
void make_viewport_clip_rect(Vp *viewport);
|
||||
extern void init_render_image(void);
|
||||
extern void end_master_display_list(void);
|
||||
extern void draw_reset_bars(void);
|
||||
//extern void draw_reset_bars(void); Target_64 only. Not used
|
||||
extern void rendering_init(void);
|
||||
extern void config_gfx_pool(void);
|
||||
extern void display_and_vsync(void);
|
||||
|
|
|
@ -46,11 +46,8 @@ s8 gFlyingCarpetState;
|
|||
*
|
||||
* Texture coordinates are s10.5 fixed-point, which means you should left-shift the actual coordinates by 5.
|
||||
*/
|
||||
#ifdef TARGET_N64
|
||||
void make_vertex(Vtx *vtx, s32 n, s16 x, s16 y, s16 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a) {
|
||||
#else
|
||||
void make_vertex(Vtx *vtx, s32 n, f32 x, f32 y, f32 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a) {
|
||||
#endif
|
||||
|
||||
vtx[n].v.ob[0] = x;
|
||||
vtx[n].v.ob[1] = y;
|
||||
vtx[n].v.ob[2] = z;
|
||||
|
|
|
@ -12,15 +12,9 @@ enum FlyingCarpetState
|
|||
|
||||
extern s8 gFlyingCarpetState;
|
||||
|
||||
#ifdef TARGET_N64
|
||||
extern void make_vertex(
|
||||
Vtx *vtx, s32 n, s16 x, s16 y, s16 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a
|
||||
);
|
||||
#else
|
||||
extern void make_vertex(
|
||||
Vtx *vtx, s32 n, f32 x, f32 y, f32 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a
|
||||
);
|
||||
#endif
|
||||
extern s16 round_float(f32);
|
||||
extern Gfx *geo_exec_inside_castle_light(s32 callContext, struct GraphNode *node, f32 mtx[4][4]);
|
||||
extern Gfx *geo_exec_flying_carpet_timer_update(s32 callContext, struct GraphNode *node,
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
#ifdef BETTERCAMERA
|
||||
#include "bettercamera.h"
|
||||
#endif
|
||||
#ifdef EXT_OPTIONS_MENU
|
||||
#include "options_menu.h"
|
||||
#endif
|
||||
|
||||
extern Gfx *gDisplayListHead;
|
||||
extern s16 gCurrCourseNum;
|
||||
|
@ -131,14 +134,7 @@ void create_dl_identity_matrix(void) {
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef TARGET_N64
|
||||
matrix->m[0][0] = 0x00010000; matrix->m[1][0] = 0x00000000; matrix->m[2][0] = 0x00000000; matrix->m[3][0] = 0x00000000;
|
||||
matrix->m[0][1] = 0x00000000; matrix->m[1][1] = 0x00010000; matrix->m[2][1] = 0x00000000; matrix->m[3][1] = 0x00000000;
|
||||
matrix->m[0][2] = 0x00000001; matrix->m[1][2] = 0x00000000; matrix->m[2][2] = 0x00000000; matrix->m[3][2] = 0x00000000;
|
||||
matrix->m[0][3] = 0x00000000; matrix->m[1][3] = 0x00000001; matrix->m[2][3] = 0x00000000; matrix->m[3][3] = 0x00000000;
|
||||
#else
|
||||
guMtxIdent(matrix);
|
||||
#endif
|
||||
|
||||
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
|
||||
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
|
||||
|
@ -1802,25 +1798,18 @@ void render_dialog_entries(void) {
|
|||
render_dialog_box_type(dialog, dialog->linesPerBox);
|
||||
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE,
|
||||
#ifdef TARGET_N64
|
||||
ensure_nonnegative(dialog->leftOffset),
|
||||
#else
|
||||
|
||||
0,
|
||||
#endif
|
||||
ensure_nonnegative(DIAG_VAL2 - dialog->width),
|
||||
#ifdef VERSION_EU
|
||||
#ifdef TARGET_N64
|
||||
ensure_nonnegative(dialog->leftOffset + DIAG_VAL3 / gDialogBoxScale),
|
||||
#else
|
||||
|
||||
SCREEN_WIDTH,
|
||||
#endif
|
||||
|
||||
ensure_nonnegative((240 - dialog->width) + ((dialog->linesPerBox * 80) / DIAG_VAL4) / gDialogBoxScale));
|
||||
#else
|
||||
#ifdef TARGET_N64
|
||||
ensure_nonnegative(DIAG_VAL3 + dialog->leftOffset),
|
||||
#else
|
||||
|
||||
SCREEN_WIDTH,
|
||||
#endif
|
||||
|
||||
ensure_nonnegative(240 + ((dialog->linesPerBox * 80) / DIAG_VAL4) - dialog->width));
|
||||
#endif
|
||||
#if defined(VERSION_JP) || defined(VERSION_SH)
|
||||
|
@ -2133,12 +2122,9 @@ void shade_screen(void) {
|
|||
|
||||
// This is a bit weird. It reuses the dialog text box (width 130, height -80),
|
||||
// so scale to at least fit the screen.
|
||||
#ifdef TARGET_N64
|
||||
create_dl_scale_matrix(MENU_MTX_NOPUSH, 2.6f, 3.4f, 1.0f);
|
||||
#else
|
||||
|
||||
create_dl_scale_matrix(MENU_MTX_NOPUSH,
|
||||
GFX_DIMENSIONS_ASPECT_RATIO * SCREEN_HEIGHT / 130.0f, 3.0f, 1.0f);
|
||||
#endif
|
||||
|
||||
gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 110);
|
||||
gSPDisplayList(gDisplayListHead++, dl_draw_text_bg_box);
|
||||
|
@ -2388,12 +2374,6 @@ void render_pause_course_options(s16 x, s16 y, s8 *index, s16 yIndex) {
|
|||
{ TEXT_EXIT_COURSE_DE }
|
||||
};
|
||||
|
||||
u8 textExitGame[][22] ={
|
||||
{ TEXT_EXIT_GAME },
|
||||
{ TEXT_EXIT_GAME_FR },
|
||||
{ TEXT_EXIT_GAME_DE }
|
||||
};
|
||||
|
||||
u8 textCameraAngleR[][24] = {
|
||||
{ TEXT_CAMERA_ANGLE_R },
|
||||
{ TEXT_CAMERA_ANGLE_R_FR },
|
||||
|
@ -2401,27 +2381,23 @@ void render_pause_course_options(s16 x, s16 y, s8 *index, s16 yIndex) {
|
|||
};
|
||||
#define textContinue textContinue[gInGameLanguage]
|
||||
#define textExitCourse textExitCourse[gInGameLanguage]
|
||||
#define textExitGame textExitGame[gInGameLanguage]
|
||||
#define textCameraAngleR textCameraAngleR[gInGameLanguage]
|
||||
#else
|
||||
u8 textContinue[] = { TEXT_CONTINUE };
|
||||
u8 textExitCourse[] = { TEXT_EXIT_COURSE };
|
||||
u8 textExitGame[] = { TEXT_EXIT_GAME };
|
||||
u8 textCameraAngleR[] = { TEXT_CAMERA_ANGLE_R };
|
||||
#endif
|
||||
|
||||
handle_menu_scrolling(MENU_SCROLL_VERTICAL, index, 1, 4); // Index max raised to 4 from 3
|
||||
handle_menu_scrolling(MENU_SCROLL_VERTICAL, index, 1, 3);
|
||||
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha);
|
||||
|
||||
print_generic_string(x + 10, y - 2, textContinue);
|
||||
print_generic_string(x + 10, y - 17, textExitCourse);
|
||||
print_generic_string(x + 10, y - 33, textExitGame);
|
||||
|
||||
|
||||
if (index[0] != 4) {
|
||||
print_generic_string(x + 10, y - 48, textCameraAngleR);
|
||||
if (index[0] != 3) {
|
||||
print_generic_string(x + 10, y - 33, textCameraAngleR);
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
||||
|
||||
create_dl_translation_matrix(MENU_MTX_PUSH, x - X_VAL8, (y - ((index[0] - 1) * yIndex)) - Y_VAL8, 0);
|
||||
|
@ -2429,10 +2405,8 @@ void render_pause_course_options(s16 x, s16 y, s8 *index, s16 yIndex) {
|
|||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha);
|
||||
gSPDisplayList(gDisplayListHead++, dl_draw_triangle);
|
||||
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
if (index[0] == 4) {
|
||||
render_pause_camera_options(x - 42, y - 57, &gDialogCameraAngleIndex, 110);
|
||||
} else {
|
||||
render_pause_camera_options(x - 42, y - 42, &gDialogCameraAngleIndex, 110);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2629,9 +2603,8 @@ s16 render_pause_courses_and_castle(void) {
|
|||
#ifdef VERSION_EU
|
||||
gInGameLanguage = eu_get_language();
|
||||
#endif
|
||||
#ifdef BETTERCAMERA
|
||||
if (newcam_option_open == 0)
|
||||
{
|
||||
#ifdef EXT_OPTIONS_MENU
|
||||
if (optmenu_open == 0) {
|
||||
#endif
|
||||
switch (gDialogBoxState) {
|
||||
case DIALOG_STATE_OPENING:
|
||||
|
@ -2673,7 +2646,7 @@ s16 render_pause_courses_and_castle(void) {
|
|||
gDialogBoxState = DIALOG_STATE_OPENING;
|
||||
gMenuMode = -1;
|
||||
|
||||
if (gDialogLineNum == 2 || gDialogLineNum == 3) {
|
||||
if (gDialogLineNum == 2) {
|
||||
num = gDialogLineNum;
|
||||
} else {
|
||||
num = 1;
|
||||
|
@ -2708,15 +2681,13 @@ s16 render_pause_courses_and_castle(void) {
|
|||
if (gDialogTextAlpha < 250) {
|
||||
gDialogTextAlpha += 25;
|
||||
}
|
||||
#ifdef BETTERCAMERA
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef EXT_OPTIONS_MENU
|
||||
} else {
|
||||
shade_screen();
|
||||
newcam_display_options();
|
||||
optmenu_draw();
|
||||
}
|
||||
newcam_check_pause_buttons();
|
||||
newcam_render_option_text();
|
||||
optmenu_check_buttons();
|
||||
optmenu_draw_prompt();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "../pc/configfile.h"
|
||||
#define CONFIG_FILE "sm64config.txt"
|
||||
|
||||
#include "pc/cliopts.h"
|
||||
|
||||
#define PLAY_MODE_NORMAL 0
|
||||
#define PLAY_MODE_PAUSED 2
|
||||
#define PLAY_MODE_CHANGE_AREA 3
|
||||
|
@ -176,7 +178,8 @@ s8 D_8032C9E0 = 0;
|
|||
u8 unused3[4];
|
||||
u8 unused4[2];
|
||||
|
||||
|
||||
// For configfile intro skipping
|
||||
extern unsigned int configSkipIntro;
|
||||
|
||||
|
||||
void basic_update(s16 *arg);
|
||||
|
@ -1214,7 +1217,7 @@ s32 init_level(void) {
|
|||
if (gMarioState->action != ACT_UNINITIALIZED) {
|
||||
if (save_file_exists(gCurrSaveFileNum - 1)) {
|
||||
set_mario_action(gMarioState, ACT_IDLE, 0);
|
||||
} else {
|
||||
} else if (gCLIOpts.SkipIntro == 0 && configSkipIntro == 0) {
|
||||
set_mario_action(gMarioState, ACT_INTRO_CUTSCENE, 0);
|
||||
val4 = 1;
|
||||
}
|
||||
|
@ -1284,7 +1287,7 @@ s32 lvl_init_from_save_file(UNUSED s16 arg0, s32 levelNum) {
|
|||
#endif
|
||||
sWarpDest.type = WARP_TYPE_NOT_WARPING;
|
||||
sDelayedWarpOp = WARP_OP_NONE;
|
||||
gShouldNotPlayCastleMusic = !save_file_exists(gCurrSaveFileNum - 1);
|
||||
gShouldNotPlayCastleMusic = !save_file_exists(gCurrSaveFileNum - 1) && gCLIOpts.SkipIntro == 0 && configSkipIntro == 0;
|
||||
|
||||
gCurrLevelNum = levelNum;
|
||||
gCurrCourseNum = COURSE_NONE;
|
||||
|
|
|
@ -328,7 +328,7 @@ void spawn_special_objects(s16 areaIndex, s16 **specialObjList) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef TARGET_N64
|
||||
// PC Port, so always use below
|
||||
u32 get_special_objects_size(s16 *data) {
|
||||
s16 *startPos = data;
|
||||
s32 numOfSpecialObjects;
|
||||
|
@ -372,4 +372,3 @@ u32 get_special_objects_size(s16 *data) {
|
|||
|
||||
return data - startPos;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -16,8 +16,6 @@ extern void spawn_macro_abs_special(u32 model, const BehaviorScript *behavior, s
|
|||
extern void spawn_macro_objects(s16 areaIndex, s16 * macroObjList);
|
||||
extern void spawn_macro_objects_hardcoded(s16 areaIndex, s16 * macroObjList);
|
||||
extern void spawn_special_objects(s16 areaIndex, s16 ** specialObjList);
|
||||
#ifndef TARGET_N64
|
||||
extern u32 get_special_objects_size(s16 *data);
|
||||
#endif
|
||||
|
||||
#endif /* MACRO_SPECIAL_OBJECTS_H */
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include <ultra64.h>
|
||||
#ifndef TARGET_N64
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "sm64.h"
|
||||
|
||||
|
@ -78,27 +76,6 @@ void *get_segment_base_addr(s32 segment) {
|
|||
return (void *) (sSegmentTable[segment] | 0x80000000);
|
||||
}
|
||||
|
||||
#ifdef TARGET_N64
|
||||
void *segmented_to_virtual(const void *addr) {
|
||||
size_t segment = (uintptr_t) addr >> 24;
|
||||
size_t offset = (uintptr_t) addr & 0x00FFFFFF;
|
||||
|
||||
return (void *) ((sSegmentTable[segment] + offset) | 0x80000000);
|
||||
}
|
||||
|
||||
void *virtual_to_segmented(u32 segment, const void *addr) {
|
||||
size_t offset = ((uintptr_t) addr & 0x1FFFFFFF) - sSegmentTable[segment];
|
||||
|
||||
return (void *) ((segment << 24) + offset);
|
||||
}
|
||||
|
||||
void move_segment_table_to_dmem(void) {
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
gSPSegment(gDisplayListHead++, i, sSegmentTable[i]);
|
||||
}
|
||||
#else
|
||||
void *segmented_to_virtual(const void *addr) {
|
||||
return (void *) addr;
|
||||
}
|
||||
|
@ -109,7 +86,7 @@ void *virtual_to_segmented(u32 segment, const void *addr) {
|
|||
|
||||
void move_segment_table_to_dmem(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the main memory pool. This pool is conceptually a pair of stacks
|
||||
|
@ -248,22 +225,8 @@ u32 main_pool_pop_state(void) {
|
|||
*/
|
||||
static void dma_read(u8 *dest, u8 *srcStart, u8 *srcEnd) {
|
||||
u32 size = ALIGN16(srcEnd - srcStart);
|
||||
#ifdef TARGET_N64
|
||||
osInvalDCache(dest, size);
|
||||
while (size != 0) {
|
||||
u32 copySize = (size >= 0x1000) ? 0x1000 : size;
|
||||
|
||||
osPiStartDma(&gDmaIoMesg, OS_MESG_PRI_NORMAL, OS_READ, (uintptr_t) srcStart, dest, copySize,
|
||||
&gDmaMesgQueue);
|
||||
osRecvMesg(&gDmaMesgQueue, &D_80339BEC, OS_MESG_BLOCK);
|
||||
|
||||
dest += copySize;
|
||||
srcStart += copySize;
|
||||
size -= copySize;
|
||||
}
|
||||
#else
|
||||
memcpy(dest, srcStart, srcEnd - srcStart);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -281,103 +244,6 @@ static void *dynamic_dma_read(u8 *srcStart, u8 *srcEnd, u32 side) {
|
|||
return dest;
|
||||
}
|
||||
|
||||
#ifdef TARGET_N64
|
||||
/**
|
||||
* Load data from ROM into a newly allocated block, and set the segment base
|
||||
* address to this block.
|
||||
*/
|
||||
void *load_segment(s32 segment, u8 *srcStart, u8 *srcEnd, u32 side) {
|
||||
void *addr = dynamic_dma_read(srcStart, srcEnd, side);
|
||||
|
||||
if (addr != NULL) {
|
||||
set_segment_base_addr(segment, addr);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a block of memory starting at destAddr and ending at the righthand
|
||||
* end of the memory pool. Then copy srcStart through srcEnd from ROM to this
|
||||
* block.
|
||||
* If this block is not large enough to hold the ROM data, or that portion
|
||||
* of the pool is already allocated, return NULL.
|
||||
*/
|
||||
void *load_to_fixed_pool_addr(u8 *destAddr, u8 *srcStart, u8 *srcEnd) {
|
||||
void *dest = NULL;
|
||||
u32 srcSize = ALIGN16(srcEnd - srcStart);
|
||||
u32 destSize = ALIGN16((u8 *) sPoolListHeadR - destAddr);
|
||||
|
||||
if (srcSize <= destSize) {
|
||||
dest = main_pool_alloc(destSize, MEMORY_POOL_RIGHT);
|
||||
if (dest != NULL) {
|
||||
bzero(dest, destSize);
|
||||
osWritebackDCacheAll();
|
||||
dma_read(dest, srcStart, srcEnd);
|
||||
osInvalICache(dest, destSize);
|
||||
osInvalDCache(dest, destSize);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress the block of ROM data from srcStart to srcEnd and return a
|
||||
* pointer to an allocated buffer holding the decompressed data. Set the
|
||||
* base address of segment to this address.
|
||||
*/
|
||||
void *load_segment_decompress(s32 segment, u8 *srcStart, u8 *srcEnd) {
|
||||
void *dest = NULL;
|
||||
|
||||
u32 compSize = ALIGN16(srcEnd - srcStart);
|
||||
u8 *compressed = main_pool_alloc(compSize, MEMORY_POOL_RIGHT);
|
||||
|
||||
// Decompressed size from mio0 header
|
||||
u32 *size = (u32 *) (compressed + 4);
|
||||
|
||||
if (compressed != NULL) {
|
||||
dma_read(compressed, srcStart, srcEnd);
|
||||
dest = main_pool_alloc(*size, MEMORY_POOL_LEFT);
|
||||
if (dest != NULL) {
|
||||
decompress(compressed, dest);
|
||||
set_segment_base_addr(segment, dest);
|
||||
main_pool_free(compressed);
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *load_segment_decompress_heap(u32 segment, u8 *srcStart, u8 *srcEnd) {
|
||||
UNUSED void *dest = NULL;
|
||||
u32 compSize = ALIGN16(srcEnd - srcStart);
|
||||
u8 *compressed = main_pool_alloc(compSize, MEMORY_POOL_RIGHT);
|
||||
UNUSED u32 *pUncSize = (u32 *) (compressed + 4);
|
||||
|
||||
if (compressed != NULL) {
|
||||
dma_read(compressed, srcStart, srcEnd);
|
||||
decompress(compressed, gDecompressionHeap);
|
||||
set_segment_base_addr(segment, gDecompressionHeap);
|
||||
main_pool_free(compressed);
|
||||
} else {
|
||||
}
|
||||
return gDecompressionHeap;
|
||||
}
|
||||
|
||||
void load_engine_code_segment(void) {
|
||||
void *startAddr = (void *) SEG_ENGINE;
|
||||
u32 totalSize = SEG_FRAMEBUFFERS - SEG_ENGINE;
|
||||
UNUSED u32 alignedSize = ALIGN16(_engineSegmentRomEnd - _engineSegmentRomStart);
|
||||
|
||||
bzero(startAddr, totalSize);
|
||||
osWritebackDCacheAll();
|
||||
dma_read(startAddr, _engineSegmentRomStart, _engineSegmentRomEnd);
|
||||
osInvalICache(startAddr, totalSize);
|
||||
osInvalDCache(startAddr, totalSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Allocate an allocation-only pool from the main pool. This pool doesn't
|
||||
* support freeing allocated memory.
|
||||
|
|
|
@ -37,19 +37,11 @@ u32 main_pool_available(void);
|
|||
u32 main_pool_push_state(void);
|
||||
u32 main_pool_pop_state(void);
|
||||
|
||||
#ifdef TARGET_N64
|
||||
void *load_segment(s32 segment, u8 *srcStart, u8 *srcEnd, u32 side);
|
||||
void *load_to_fixed_pool_addr(u8 *destAddr, u8 *srcStart, u8 *srcEnd);
|
||||
void *load_segment_decompress(s32 segment, u8 *srcStart, u8 *srcEnd);
|
||||
void *load_segment_decompress_heap(u32 segment, u8 *srcStart, u8 *srcEnd);
|
||||
void load_engine_code_segment(void);
|
||||
#else
|
||||
#define load_segment(...)
|
||||
#define load_to_fixed_pool_addr(...)
|
||||
#define load_segment_decompress(...)
|
||||
#define load_segment_decompress_heap(...)
|
||||
#define load_engine_code_segment(...)
|
||||
#endif
|
||||
|
||||
struct AllocOnlyPool *alloc_only_pool_init(u32 size, u32 side);
|
||||
void *alloc_only_pool_alloc(struct AllocOnlyPool *pool, s32 size);
|
||||
|
|
|
@ -527,11 +527,15 @@ void set_object_visibility(struct Object *obj, s32 dist) {
|
|||
f32 objY = obj->oPosY;
|
||||
f32 objZ = obj->oPosZ;
|
||||
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
if (is_point_within_radius_of_mario(objX, objY, objZ, dist) == TRUE) {
|
||||
#endif
|
||||
obj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
#ifndef NODRAWINGDISTANCE
|
||||
} else {
|
||||
obj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -984,7 +984,7 @@ BAD_RETURN(s16) cur_obj_reverse_animation(void) {
|
|||
BAD_RETURN(s32) cur_obj_extend_animation_if_at_end(void) {
|
||||
s32 sp4 = o->header.gfx.unk38.animFrame;
|
||||
s32 sp0 = o->header.gfx.unk38.curAnim->unk08 - 2;
|
||||
|
||||
|
||||
if (sp4 == sp0) o->header.gfx.unk38.animFrame--;
|
||||
}
|
||||
|
||||
|
@ -1595,6 +1595,10 @@ void obj_set_billboard(struct Object *obj) {
|
|||
obj->header.gfx.node.flags |= GRAPH_RENDER_BILLBOARD;
|
||||
}
|
||||
|
||||
void obj_set_cylboard(struct Object *obj) {
|
||||
obj->header.gfx.node.flags |= GRAPH_RENDER_CYLBOARD;
|
||||
}
|
||||
|
||||
void cur_obj_set_hitbox_radius_and_height(f32 radius, f32 height) {
|
||||
o->hitboxRadius = radius;
|
||||
o->hitboxHeight = height;
|
||||
|
|
|
@ -292,6 +292,7 @@ extern void cur_obj_shake_y(f32);
|
|||
void cur_obj_start_cam_event(struct Object *obj, s32 cameraEvent);
|
||||
// extern ? set_mario_interact_hoot_if_in_range(?);
|
||||
void obj_set_billboard(struct Object *a0);
|
||||
void obj_set_cylboard(struct Object *a0);
|
||||
void cur_obj_set_hitbox_radius_and_height(f32,f32);
|
||||
void cur_obj_set_hurtbox_radius_and_height(f32,f32);
|
||||
// extern ? obj_spawn_loot_coins(?);
|
||||
|
|
526
src/game/options_menu.c
Normal file
526
src/game/options_menu.c
Normal file
|
@ -0,0 +1,526 @@
|
|||
#ifdef EXT_OPTIONS_MENU
|
||||
|
||||
#include "sm64.h"
|
||||
#include "include/text_strings.h"
|
||||
#include "engine/math_util.h"
|
||||
#include "audio/external.h"
|
||||
#include "game/camera.h"
|
||||
#include "game/level_update.h"
|
||||
#include "game/print.h"
|
||||
#include "game/segment2.h"
|
||||
#include "game/save_file.h"
|
||||
#ifdef BETTERCAMERA
|
||||
#include "game/bettercamera.h"
|
||||
#endif
|
||||
#include "game/mario_misc.h"
|
||||
#include "game/game_init.h"
|
||||
#include "game/ingame_menu.h"
|
||||
#include "game/options_menu.h"
|
||||
#include "pc/cliopts.h"
|
||||
#include "pc/configfile.h"
|
||||
#include "pc/controller/controller_api.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
u8 optmenu_open = 0;
|
||||
|
||||
static u8 optmenu_binding = 0;
|
||||
static u8 optmenu_bind_idx = 0;
|
||||
|
||||
// How to add stuff:
|
||||
// strings: add them to include/text_strings.h.in
|
||||
// and to menuStr[] / opts*Str[]
|
||||
// options: add them to the relevant options list
|
||||
// menus: add a new submenu definition and a new
|
||||
// option to the optsMain list
|
||||
|
||||
static const u8 toggleStr[][16] = {
|
||||
{ TEXT_OPT_DISABLED },
|
||||
{ TEXT_OPT_ENABLED },
|
||||
};
|
||||
|
||||
static const u8 menuStr[][32] = {
|
||||
{ TEXT_OPT_HIGHLIGHT },
|
||||
{ TEXT_OPT_BUTTON1 },
|
||||
{ TEXT_OPT_BUTTON2 },
|
||||
{ TEXT_OPT_OPTIONS },
|
||||
{ TEXT_OPT_CAMERA },
|
||||
{ TEXT_OPT_CONTROLS },
|
||||
{ TEXT_OPT_VIDEO },
|
||||
{ TEXT_OPT_AUDIO },
|
||||
{ TEXT_EXIT_GAME },
|
||||
};
|
||||
|
||||
static const u8 optsCameraStr[][32] = {
|
||||
{ TEXT_OPT_CAMX },
|
||||
{ TEXT_OPT_CAMY },
|
||||
{ TEXT_OPT_INVERTX },
|
||||
{ TEXT_OPT_INVERTY },
|
||||
{ TEXT_OPT_CAMC },
|
||||
{ TEXT_OPT_CAMP },
|
||||
{ TEXT_OPT_ANALOGUE },
|
||||
{ TEXT_OPT_MOUSE },
|
||||
{ TEXT_OPT_CAMD },
|
||||
};
|
||||
|
||||
static const u8 optsVideoStr[][32] = {
|
||||
{ TEXT_OPT_FSCREEN },
|
||||
{ TEXT_OPT_TEXFILTER },
|
||||
{ TEXT_OPT_NEAREST },
|
||||
{ TEXT_OPT_LINEAR },
|
||||
};
|
||||
|
||||
static const u8 optsAudioStr[][32] = {
|
||||
{ TEXT_OPT_MVOLUME },
|
||||
};
|
||||
|
||||
static const u8 bindStr[][32] = {
|
||||
{ TEXT_OPT_UNBOUND },
|
||||
{ TEXT_OPT_PRESSKEY },
|
||||
{ TEXT_BIND_A },
|
||||
{ TEXT_BIND_B },
|
||||
{ TEXT_BIND_START },
|
||||
{ TEXT_BIND_L },
|
||||
{ TEXT_BIND_R },
|
||||
{ TEXT_BIND_Z },
|
||||
{ TEXT_BIND_C_UP },
|
||||
{ TEXT_BIND_C_DOWN },
|
||||
{ TEXT_BIND_C_LEFT },
|
||||
{ TEXT_BIND_C_RIGHT },
|
||||
{ TEXT_BIND_UP },
|
||||
{ TEXT_BIND_DOWN },
|
||||
{ TEXT_BIND_LEFT },
|
||||
{ TEXT_BIND_RIGHT },
|
||||
};
|
||||
|
||||
static const u8 *filterChoices[] = {
|
||||
optsVideoStr[2],
|
||||
optsVideoStr[3],
|
||||
};
|
||||
|
||||
enum OptType {
|
||||
OPT_INVALID = 0,
|
||||
OPT_TOGGLE,
|
||||
OPT_CHOICE,
|
||||
OPT_SCROLL,
|
||||
OPT_SUBMENU,
|
||||
OPT_BIND,
|
||||
OPT_BUTTON,
|
||||
};
|
||||
|
||||
struct SubMenu;
|
||||
|
||||
struct Option {
|
||||
enum OptType type;
|
||||
const u8 *label;
|
||||
union {
|
||||
u32 *uval;
|
||||
bool *bval;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
const u8 **choices;
|
||||
u32 numChoices;
|
||||
};
|
||||
struct {
|
||||
u32 scrMin;
|
||||
u32 scrMax;
|
||||
u32 scrStep;
|
||||
};
|
||||
struct SubMenu *nextMenu;
|
||||
void (*actionFn)(struct Option *, s32);
|
||||
};
|
||||
};
|
||||
|
||||
struct SubMenu {
|
||||
struct SubMenu *prev; // this is set at runtime to avoid needless complication
|
||||
const u8 *label;
|
||||
struct Option *opts;
|
||||
s32 numOpts;
|
||||
s32 select;
|
||||
s32 scroll;
|
||||
};
|
||||
|
||||
/* helper macros */
|
||||
|
||||
#define DEF_OPT_TOGGLE(lbl, bv) \
|
||||
{ .type = OPT_TOGGLE, .label = lbl, .bval = bv }
|
||||
#define DEF_OPT_SCROLL(lbl, uv, min, max, st) \
|
||||
{ .type = OPT_SCROLL, .label = lbl, .uval = uv, .scrMin = min, .scrMax = max, .scrStep = st }
|
||||
#define DEF_OPT_CHOICE(lbl, uv, ch) \
|
||||
{ .type = OPT_CHOICE, .label = lbl, .uval = uv, .choices = ch, .numChoices = sizeof(ch) / sizeof(ch[0]) }
|
||||
#define DEF_OPT_SUBMENU(lbl, nm) \
|
||||
{ .type = OPT_SUBMENU, .label = lbl, .nextMenu = nm }
|
||||
#define DEF_OPT_BIND(lbl, uv) \
|
||||
{ .type = OPT_BIND, .label = lbl, .uval = uv }
|
||||
#define DEF_OPT_BUTTON(lbl, act) \
|
||||
{ .type = OPT_BUTTON, .label = lbl, .actionFn = act }
|
||||
#define DEF_SUBMENU(lbl, opt) \
|
||||
{ .label = lbl, .opts = opt, .numOpts = sizeof(opt) / sizeof(opt[0]) }
|
||||
|
||||
/* button action functions */
|
||||
|
||||
static void optmenu_act_exit(UNUSED struct Option *self, s32 arg) {
|
||||
if (!arg) exit(0); // only exit on A press and not directions
|
||||
}
|
||||
|
||||
/* submenu option lists */
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
static struct Option optsCamera[] = {
|
||||
DEF_OPT_TOGGLE( optsCameraStr[6], &configEnableCamera ),
|
||||
DEF_OPT_TOGGLE( optsCameraStr[7], &configCameraMouse ),
|
||||
DEF_OPT_TOGGLE( optsCameraStr[2], &configCameraInvertX ),
|
||||
DEF_OPT_TOGGLE( optsCameraStr[3], &configCameraInvertY ),
|
||||
DEF_OPT_SCROLL( optsCameraStr[0], &configCameraXSens, 10, 250, 1 ),
|
||||
DEF_OPT_SCROLL( optsCameraStr[1], &configCameraYSens, 10, 250, 1 ),
|
||||
DEF_OPT_SCROLL( optsCameraStr[4], &configCameraAggr, 0, 100, 1 ),
|
||||
DEF_OPT_SCROLL( optsCameraStr[5], &configCameraPan, 0, 100, 1 ),
|
||||
DEF_OPT_SCROLL( optsCameraStr[8], &configCameraDegrade, 0, 100, 1 ),
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct Option optsControls[] = {
|
||||
DEF_OPT_BIND( bindStr[ 2], configKeyA ),
|
||||
DEF_OPT_BIND( bindStr[ 3], configKeyB ),
|
||||
DEF_OPT_BIND( bindStr[ 4], configKeyStart ),
|
||||
DEF_OPT_BIND( bindStr[ 5], configKeyL ),
|
||||
DEF_OPT_BIND( bindStr[ 6], configKeyR ),
|
||||
DEF_OPT_BIND( bindStr[ 7], configKeyZ ),
|
||||
DEF_OPT_BIND( bindStr[ 8], configKeyCUp ),
|
||||
DEF_OPT_BIND( bindStr[ 9], configKeyCDown ),
|
||||
DEF_OPT_BIND( bindStr[10], configKeyCLeft ),
|
||||
DEF_OPT_BIND( bindStr[11], configKeyCRight ),
|
||||
DEF_OPT_BIND( bindStr[12], configKeyStickUp ),
|
||||
DEF_OPT_BIND( bindStr[13], configKeyStickDown ),
|
||||
DEF_OPT_BIND( bindStr[14], configKeyStickLeft ),
|
||||
DEF_OPT_BIND( bindStr[15], configKeyStickRight ),
|
||||
};
|
||||
|
||||
static struct Option optsVideo[] = {
|
||||
DEF_OPT_TOGGLE( optsVideoStr[0], &configFullscreen ),
|
||||
DEF_OPT_CHOICE( optsVideoStr[1], &configFiltering, filterChoices ),
|
||||
};
|
||||
|
||||
static struct Option optsAudio[] = {
|
||||
DEF_OPT_SCROLL( optsAudioStr[0], &configMasterVolume, 0, MAX_VOLUME, 1 ),
|
||||
};
|
||||
|
||||
/* submenu definitions */
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
static struct SubMenu menuCamera = DEF_SUBMENU( menuStr[4], optsCamera );
|
||||
#endif
|
||||
static struct SubMenu menuControls = DEF_SUBMENU( menuStr[5], optsControls );
|
||||
static struct SubMenu menuVideo = DEF_SUBMENU( menuStr[6], optsVideo );
|
||||
static struct SubMenu menuAudio = DEF_SUBMENU( menuStr[7], optsAudio );
|
||||
|
||||
/* main options menu definition */
|
||||
|
||||
static struct Option optsMain[] = {
|
||||
#ifdef BETTERCAMERA
|
||||
DEF_OPT_SUBMENU( menuStr[4], &menuCamera ),
|
||||
#endif
|
||||
DEF_OPT_SUBMENU( menuStr[5], &menuControls ),
|
||||
DEF_OPT_SUBMENU( menuStr[6], &menuVideo ),
|
||||
DEF_OPT_SUBMENU( menuStr[7], &menuAudio ),
|
||||
DEF_OPT_BUTTON ( menuStr[8], optmenu_act_exit ),
|
||||
};
|
||||
|
||||
static struct SubMenu menuMain = DEF_SUBMENU( menuStr[3], optsMain );
|
||||
|
||||
/* implementation */
|
||||
|
||||
static s32 optmenu_option_timer = 0;
|
||||
static u8 optmenu_hold_count = 0;
|
||||
|
||||
static struct SubMenu *currentMenu = &menuMain;
|
||||
|
||||
static inline s32 wrap_add(s32 a, const s32 b, const s32 min, const s32 max) {
|
||||
a += b;
|
||||
if (a < min) a = max - (min - a) + 1;
|
||||
else if (a > max) a = min + (a - max) - 1;
|
||||
return a;
|
||||
}
|
||||
|
||||
static void uint_to_hex(u32 num, u8 *dst) {
|
||||
u8 places = 4;
|
||||
while (places--) {
|
||||
const u32 digit = num & 0xF;
|
||||
dst[places] = digit;
|
||||
num >>= 4;
|
||||
}
|
||||
dst[4] = DIALOG_CHAR_TERMINATOR;
|
||||
}
|
||||
|
||||
//Displays a box.
|
||||
static void optmenu_draw_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);
|
||||
}
|
||||
|
||||
static void optmenu_draw_text(s16 x, s16 y, const u8 *str, u8 col) {
|
||||
const u8 textX = get_str_x_pos_from_center(x, (u8*)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);
|
||||
}
|
||||
|
||||
static void optmenu_draw_opt(const struct Option *opt, s16 x, s16 y, u8 sel) {
|
||||
u8 buf[32] = { 0 };
|
||||
|
||||
if (opt->type == OPT_SUBMENU || opt->type == OPT_BUTTON)
|
||||
y -= 6;
|
||||
|
||||
optmenu_draw_text(x, y, opt->label, sel);
|
||||
|
||||
switch (opt->type) {
|
||||
case OPT_TOGGLE:
|
||||
optmenu_draw_text(x, y-13, toggleStr[(int)*opt->bval], sel);
|
||||
break;
|
||||
|
||||
case OPT_CHOICE:
|
||||
optmenu_draw_text(x, y-13, opt->choices[*opt->uval], sel);
|
||||
break;
|
||||
|
||||
case OPT_SCROLL:
|
||||
int_to_str(*opt->uval, buf);
|
||||
optmenu_draw_text(x, y-13, buf, sel);
|
||||
break;
|
||||
|
||||
case OPT_BIND:
|
||||
x = 112;
|
||||
for (u8 i = 0; i < MAX_BINDS; ++i, x += 48) {
|
||||
const u8 white = (sel && (optmenu_bind_idx == i));
|
||||
// TODO: button names
|
||||
if (opt->uval[i] == VK_INVALID) {
|
||||
if (optmenu_binding && white)
|
||||
optmenu_draw_text(x, y-13, bindStr[1], 1);
|
||||
else
|
||||
optmenu_draw_text(x, y-13, bindStr[0], white);
|
||||
} else {
|
||||
uint_to_hex(opt->uval[i], buf);
|
||||
optmenu_draw_text(x, y-13, buf, white);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
};
|
||||
}
|
||||
|
||||
static void optmenu_opt_change(struct Option *opt, s32 val) {
|
||||
switch (opt->type) {
|
||||
case OPT_TOGGLE:
|
||||
*opt->bval = !*opt->bval;
|
||||
break;
|
||||
|
||||
case OPT_CHOICE:
|
||||
*opt->uval = wrap_add(*opt->uval, val, 0, opt->numChoices - 1);
|
||||
break;
|
||||
|
||||
case OPT_SCROLL:
|
||||
*opt->uval = wrap_add(*opt->uval, opt->scrStep * val, opt->scrMin, opt->scrMax);
|
||||
break;
|
||||
|
||||
case OPT_SUBMENU:
|
||||
opt->nextMenu->prev = currentMenu;
|
||||
currentMenu = opt->nextMenu;
|
||||
break;
|
||||
|
||||
case OPT_BUTTON:
|
||||
if (opt->actionFn)
|
||||
opt->actionFn(opt, val);
|
||||
break;
|
||||
|
||||
case OPT_BIND:
|
||||
if (val == 0xFF) {
|
||||
// clear the bind
|
||||
opt->uval[optmenu_bind_idx] = VK_INVALID;
|
||||
} else if (val == 0) {
|
||||
opt->uval[optmenu_bind_idx] = VK_INVALID;
|
||||
optmenu_binding = 1;
|
||||
controller_get_raw_key(); // clear the last key, which is probably A
|
||||
} else {
|
||||
optmenu_bind_idx = wrap_add(optmenu_bind_idx, val, 0, MAX_BINDS - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline s16 get_hudstr_centered_x(const s16 sx, const u8 *str) {
|
||||
const u8 *chr = str;
|
||||
s16 len = 0;
|
||||
while (*chr != GLOBAR_CHAR_TERMINATOR) ++chr, ++len;
|
||||
return sx - len * 6; // stride is 12
|
||||
}
|
||||
|
||||
//Options menu
|
||||
void optmenu_draw(void) {
|
||||
s16 scroll;
|
||||
s16 scrollpos;
|
||||
|
||||
const s16 labelX = get_hudstr_centered_x(160, currentMenu->label);
|
||||
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin);
|
||||
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255);
|
||||
print_hud_lut_string(HUD_LUT_GLOBAL, labelX, 40, currentMenu->label);
|
||||
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end);
|
||||
|
||||
if (currentMenu->numOpts > 4) {
|
||||
optmenu_draw_box(272, 90, 280, 208, 0x80, 0x80, 0x80);
|
||||
scrollpos = 54 * ((f32)currentMenu->scroll / (currentMenu->numOpts-4));
|
||||
optmenu_draw_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 (u8 i = 0; i < currentMenu->numOpts; i++) {
|
||||
scroll = 140 - 32 * i + currentMenu->scroll * 32;
|
||||
// FIXME: just start from the first visible option bruh
|
||||
if (scroll <= 140 && scroll > 32)
|
||||
optmenu_draw_opt(¤tMenu->opts[i], 160, scroll, (currentMenu->select == i));
|
||||
}
|
||||
|
||||
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 * (currentMenu->select - currentMenu->scroll)), menuStr[0]);
|
||||
print_hud_lut_string(HUD_LUT_GLOBAL, 224, 90 + (32 * (currentMenu->select - currentMenu->scroll)), menuStr[0]);
|
||||
gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end);
|
||||
}
|
||||
|
||||
//This has been separated for interesting reasons. Don't question it.
|
||||
void optmenu_draw_prompt(void) {
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
|
||||
optmenu_draw_text(278, 212, menuStr[1 + optmenu_open], 0);
|
||||
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
|
||||
}
|
||||
|
||||
void optmenu_toggle(void) {
|
||||
if (optmenu_open == 0) {
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs);
|
||||
#endif
|
||||
currentMenu = &menuMain;
|
||||
optmenu_open = 1;
|
||||
} else {
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_MARIO_CASTLE_WARP2, gDefaultSoundArgs);
|
||||
#endif
|
||||
optmenu_open = 0;
|
||||
#ifdef BETTERCAMERA
|
||||
newcam_init_settings(); // load bettercam settings from config vars
|
||||
#endif
|
||||
controller_reconfigure(); // rebind using new config values
|
||||
configfile_save(gCLIOpts.ConfigFile);
|
||||
}
|
||||
}
|
||||
|
||||
void optmenu_check_buttons(void) {
|
||||
if (optmenu_binding) {
|
||||
u32 key = controller_get_raw_key();
|
||||
if (key != VK_INVALID) {
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs);
|
||||
#endif
|
||||
currentMenu->opts[currentMenu->select].uval[optmenu_bind_idx] = key;
|
||||
optmenu_binding = 0;
|
||||
optmenu_option_timer = 12;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (gPlayer1Controller->buttonPressed & R_TRIG)
|
||||
optmenu_toggle();
|
||||
|
||||
if (!optmenu_open) return;
|
||||
|
||||
u8 allowInput = 0;
|
||||
|
||||
optmenu_option_timer--;
|
||||
if (optmenu_option_timer <= 0) {
|
||||
if (optmenu_hold_count == 0) {
|
||||
optmenu_hold_count++;
|
||||
optmenu_option_timer = 10;
|
||||
} else {
|
||||
optmenu_option_timer = 3;
|
||||
}
|
||||
allowInput = 1;
|
||||
}
|
||||
|
||||
if (ABS(gPlayer1Controller->stickY) > 60) {
|
||||
if (allowInput) {
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs);
|
||||
#endif
|
||||
|
||||
if (gPlayer1Controller->stickY >= 60) {
|
||||
currentMenu->select--;
|
||||
if (currentMenu->select < 0)
|
||||
currentMenu->select = currentMenu->numOpts-1;
|
||||
} else {
|
||||
currentMenu->select++;
|
||||
if (currentMenu->select >= currentMenu->numOpts)
|
||||
currentMenu->select = 0;
|
||||
}
|
||||
|
||||
if (currentMenu->select < currentMenu->scroll)
|
||||
currentMenu->scroll = currentMenu->select;
|
||||
else if (currentMenu->select > currentMenu->scroll + 3)
|
||||
currentMenu->scroll = currentMenu->select - 3;
|
||||
}
|
||||
} else if (ABS(gPlayer1Controller->stickX) > 60) {
|
||||
if (allowInput) {
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs);
|
||||
#endif
|
||||
if (gPlayer1Controller->stickX >= 60)
|
||||
optmenu_opt_change(¤tMenu->opts[currentMenu->select], 1);
|
||||
else
|
||||
optmenu_opt_change(¤tMenu->opts[currentMenu->select], -1);
|
||||
}
|
||||
} else if (gPlayer1Controller->buttonPressed & A_BUTTON) {
|
||||
if (allowInput) {
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs);
|
||||
#endif
|
||||
optmenu_opt_change(¤tMenu->opts[currentMenu->select], 0);
|
||||
}
|
||||
} else if (gPlayer1Controller->buttonPressed & B_BUTTON) {
|
||||
if (allowInput) {
|
||||
if (currentMenu->prev) {
|
||||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs);
|
||||
#endif
|
||||
currentMenu = currentMenu->prev;
|
||||
} else {
|
||||
// can't go back, exit the menu altogether
|
||||
optmenu_toggle();
|
||||
}
|
||||
}
|
||||
} else if (gPlayer1Controller->buttonPressed & Z_TRIG) {
|
||||
// HACK: clear binds with Z
|
||||
if (allowInput && currentMenu->opts[currentMenu->select].type == OPT_BIND)
|
||||
optmenu_opt_change(¤tMenu->opts[currentMenu->select], 0xFF);
|
||||
} else if (gPlayer1Controller->buttonPressed & START_BUTTON) {
|
||||
if (allowInput) optmenu_toggle();
|
||||
} else {
|
||||
optmenu_hold_count = 0;
|
||||
optmenu_option_timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // EXT_OPTIONS_MENU
|
11
src/game/options_menu.h
Normal file
11
src/game/options_menu.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef OPTIONS_MENU_H
|
||||
#define OPTIONS_MENU_H
|
||||
|
||||
void optmenu_toggle(void);
|
||||
void optmenu_draw(void);
|
||||
void optmenu_draw_prompt(void);
|
||||
void optmenu_check_buttons(void);
|
||||
|
||||
extern u8 optmenu_open;
|
||||
|
||||
#endif // OPTIONS_MENU_H
|
|
@ -366,29 +366,6 @@ void add_glyph_texture(s8 glyphIndex) {
|
|||
gSPDisplayList(gDisplayListHead++, dl_hud_img_load_tex_block);
|
||||
}
|
||||
|
||||
#ifdef TARGET_N64
|
||||
/**
|
||||
* Clips textrect into the boundaries defined.
|
||||
*/
|
||||
void clip_to_bounds(s32 *x, s32 *y) {
|
||||
if (*x < TEXRECT_MIN_X) {
|
||||
*x = TEXRECT_MIN_X;
|
||||
}
|
||||
|
||||
if (*x > TEXRECT_MAX_X) {
|
||||
*x = TEXRECT_MAX_X;
|
||||
}
|
||||
|
||||
if (*y < TEXRECT_MIN_Y) {
|
||||
*y = TEXRECT_MIN_Y;
|
||||
}
|
||||
|
||||
if (*y > TEXRECT_MAX_Y) {
|
||||
*y = TEXRECT_MAX_Y;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Renders the glyph that's set at the given position.
|
||||
*/
|
||||
|
@ -398,9 +375,6 @@ void render_textrect(s32 x, s32 y, s32 pos) {
|
|||
s32 rectX;
|
||||
s32 rectY;
|
||||
|
||||
#ifdef TARGET_N64
|
||||
clip_to_bounds(&rectBaseX, &rectBaseY);
|
||||
#endif
|
||||
rectX = rectBaseX;
|
||||
rectY = rectBaseY;
|
||||
gSPTextureRectangle(gDisplayListHead++, rectX << 2, rectY << 2, (rectX + 15) << 2,
|
||||
|
|
|
@ -506,11 +506,7 @@ static void geo_process_background(struct GraphNodeBackground *node) {
|
|||
if (list != 0) {
|
||||
geo_append_display_list((void *) VIRTUAL_TO_PHYSICAL(list), node->fnNode.node.flags >> 8);
|
||||
} else if (gCurGraphNodeMasterList != NULL) {
|
||||
#ifdef TARGET_N64
|
||||
Gfx *gfxStart = alloc_display_list(sizeof(Gfx) * 7);
|
||||
#else
|
||||
Gfx *gfxStart = alloc_display_list(sizeof(Gfx) * 8);
|
||||
#endif
|
||||
Gfx *gfx = gfxStart;
|
||||
|
||||
gDPPipeSync(gfx++);
|
||||
|
@ -757,9 +753,7 @@ static int obj_is_in_view(struct GraphNodeObject *node, Mat4 matrix) {
|
|||
// the amount of units between the center of the screen and the horizontal edge
|
||||
// given the distance from the object to the camera.
|
||||
|
||||
#ifndef TARGET_N64
|
||||
hScreenEdge *= GFX_DIMENSIONS_ASPECT_RATIO;
|
||||
#endif
|
||||
|
||||
if (geo != NULL && geo->type == GRAPH_NODE_TYPE_CULLING_RADIUS) {
|
||||
cullingRadius =
|
||||
|
@ -802,6 +796,9 @@ static void geo_process_object(struct Object *node) {
|
|||
if (node->header.gfx.throwMatrix != NULL) {
|
||||
mtxf_mul(gMatStack[gMatStackIndex + 1], (void *) node->header.gfx.throwMatrix,
|
||||
gMatStack[gMatStackIndex]);
|
||||
} else if (node->header.gfx.node.flags & GRAPH_RENDER_CYLBOARD) {
|
||||
mtxf_cylboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex],
|
||||
node->header.gfx.pos, gCurGraphNodeCamera->roll);
|
||||
} else if (node->header.gfx.node.flags & GRAPH_RENDER_BILLBOARD) {
|
||||
mtxf_billboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex],
|
||||
node->header.gfx.pos, gCurGraphNodeCamera->roll);
|
||||
|
|
|
@ -15,6 +15,12 @@
|
|||
#define MENU_DATA_MAGIC 0x4849
|
||||
#define SAVE_FILE_MAGIC 0x4441
|
||||
|
||||
#define BSWAP16(x) \
|
||||
( (((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00) )
|
||||
#define BSWAP32(x) \
|
||||
( (((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | \
|
||||
(((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000) )
|
||||
|
||||
STATIC_ASSERT(sizeof(struct SaveBuffer) == EEPROM_SIZE, "eeprom buffer size must match");
|
||||
|
||||
extern struct SaveBuffer gSaveBuffer;
|
||||
|
@ -50,6 +56,38 @@ static void stub_save_file_1(void) {
|
|||
UNUSED s32 pad;
|
||||
}
|
||||
|
||||
/**
|
||||
* Byteswap all multibyte fields in a SaveBlockSignature.
|
||||
*/
|
||||
static inline void bswap_signature(struct SaveBlockSignature *data) {
|
||||
data->magic = BSWAP16(data->magic);
|
||||
data->chksum = BSWAP16(data->chksum); // valid as long as the checksum is a literal sum
|
||||
}
|
||||
|
||||
/**
|
||||
* Byteswap all multibyte fields in a MainMenuSaveData.
|
||||
*/
|
||||
static inline void bswap_menudata(struct MainMenuSaveData *data) {
|
||||
for (int i = 0; i < NUM_SAVE_FILES; ++i)
|
||||
data->coinScoreAges[i] = BSWAP32(data->coinScoreAges[i]);
|
||||
data->soundMode = BSWAP16(data->soundMode);
|
||||
#ifdef VERSION_EU
|
||||
data->language = BSWAP16(data->language);
|
||||
#endif
|
||||
bswap_signature(&data->signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Byteswap all multibyte fields in a SaveFile.
|
||||
*/
|
||||
static inline void bswap_savefile(struct SaveFile *data) {
|
||||
data->capPos[0] = BSWAP16(data->capPos[0]);
|
||||
data->capPos[1] = BSWAP16(data->capPos[1]);
|
||||
data->capPos[2] = BSWAP16(data->capPos[2]);
|
||||
data->flags = BSWAP32(data->flags);
|
||||
bswap_signature(&data->signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from EEPROM to a given address.
|
||||
* The EEPROM address is computed using the offset of the destination address from gSaveBuffer.
|
||||
|
@ -80,16 +118,16 @@ static s32 read_eeprom_data(void *buffer, s32 size) {
|
|||
|
||||
/**
|
||||
* Write data to EEPROM.
|
||||
* The EEPROM address is computed using the offset of the source address from gSaveBuffer.
|
||||
* The EEPROM address was originally computed using the offset of the source address from gSaveBuffer.
|
||||
* Try at most 4 times, and return 0 on success. On failure, return the status returned from
|
||||
* osEepromLongWrite. Unlike read_eeprom_data, return 1 if EEPROM isn't loaded.
|
||||
*/
|
||||
static s32 write_eeprom_data(void *buffer, s32 size) {
|
||||
static s32 write_eeprom_data(void *buffer, s32 size, const uintptr_t baseofs) {
|
||||
s32 status = 1;
|
||||
|
||||
if (gEepromProbe != 0) {
|
||||
s32 triesLeft = 4;
|
||||
u32 offset = (u32)((u8 *) buffer - (u8 *) &gSaveBuffer) >> 3;
|
||||
u32 offset = (u32)baseofs >> 3;
|
||||
|
||||
do {
|
||||
#ifdef VERSION_SH
|
||||
|
@ -106,6 +144,41 @@ static s32 write_eeprom_data(void *buffer, s32 size) {
|
|||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrappers that byteswap the data on LE platforms before writing it to 'EEPROM'
|
||||
*/
|
||||
|
||||
static inline s32 write_eeprom_savefile(const u32 file, const u32 slot, const u32 num) {
|
||||
// calculate the EEPROM address using the file number and slot
|
||||
const uintptr_t ofs = (u8*)&gSaveBuffer.files[file][slot] - (u8*)&gSaveBuffer;
|
||||
|
||||
#if IS_BIG_ENDIAN
|
||||
return write_eeprom_data(&gSaveBuffer.files[file][slot], num * sizeof(struct SaveFile), ofs);
|
||||
#else
|
||||
// byteswap the data and then write it
|
||||
struct SaveFile sf[num];
|
||||
bcopy(&gSaveBuffer.files[file][slot], sf, num * sizeof(sf[0]));
|
||||
for (u32 i = 0; i < num; ++i) bswap_savefile(&sf[i]);
|
||||
return write_eeprom_data(&sf, sizeof(sf), ofs);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline s32 write_eeprom_menudata(const u32 slot, const u32 num) {
|
||||
// calculate the EEPROM address using the slot
|
||||
const uintptr_t ofs = (u8*)&gSaveBuffer.menuData[slot] - (u8*)&gSaveBuffer;
|
||||
|
||||
#if IS_BIG_ENDIAN
|
||||
return write_eeprom_data(&gSaveBuffer.menuData[slot], num * sizeof(struct MainMenuSaveData), ofs);
|
||||
#else
|
||||
// byteswap the data and then write it
|
||||
struct MainMenuSaveData md[num];
|
||||
bcopy(&gSaveBuffer.menuData[slot], md, num * sizeof(md[0]));
|
||||
for (u32 i = 0; i < num; ++i) bswap_menudata(&md[i]);
|
||||
return write_eeprom_data(&md, sizeof(md), ofs);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sum the bytes in data to data + size - 2. The last two bytes are ignored
|
||||
* because that is where the checksum is stored.
|
||||
|
@ -157,7 +230,7 @@ static void restore_main_menu_data(s32 srcSlot) {
|
|||
bcopy(&gSaveBuffer.menuData[srcSlot], &gSaveBuffer.menuData[destSlot], sizeof(gSaveBuffer.menuData[destSlot]));
|
||||
|
||||
// Write destination data to EEPROM
|
||||
write_eeprom_data(&gSaveBuffer.menuData[destSlot], sizeof(gSaveBuffer.menuData[destSlot]));
|
||||
write_eeprom_menudata(destSlot, 1);
|
||||
}
|
||||
|
||||
static void save_main_menu_data(void) {
|
||||
|
@ -169,7 +242,7 @@ static void save_main_menu_data(void) {
|
|||
bcopy(&gSaveBuffer.menuData[0], &gSaveBuffer.menuData[1], sizeof(gSaveBuffer.menuData[1]));
|
||||
|
||||
// Write to EEPROM
|
||||
write_eeprom_data(gSaveBuffer.menuData, sizeof(gSaveBuffer.menuData));
|
||||
write_eeprom_menudata(0, 2);
|
||||
|
||||
gMainMenuDataModified = FALSE;
|
||||
}
|
||||
|
@ -245,8 +318,35 @@ static void restore_save_file_data(s32 fileIndex, s32 srcSlot) {
|
|||
sizeof(gSaveBuffer.files[fileIndex][destSlot]));
|
||||
|
||||
// Write destination data to EEPROM
|
||||
write_eeprom_data(&gSaveBuffer.files[fileIndex][destSlot],
|
||||
sizeof(gSaveBuffer.files[fileIndex][destSlot]));
|
||||
write_eeprom_savefile(fileIndex, destSlot, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the 'EEPROM' save has different endianness (e.g. it's from an actual N64).
|
||||
*/
|
||||
static u8 save_file_need_bswap(const struct SaveBuffer *buf) {
|
||||
// check all signatures just in case
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (buf->menuData[i].signature.magic == BSWAP16(MENU_DATA_MAGIC))
|
||||
return TRUE;
|
||||
for (int j = 0; j < NUM_SAVE_FILES; ++j) {
|
||||
if (buf->files[j][i].signature.magic == BSWAP16(SAVE_FILE_MAGIC))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Byteswap all multibyte fields in a SaveBuffer.
|
||||
*/
|
||||
static void save_file_bswap(struct SaveBuffer *buf) {
|
||||
bswap_menudata(buf->menuData + 0);
|
||||
bswap_menudata(buf->menuData + 1);
|
||||
for (int i = 0; i < NUM_SAVE_FILES; ++i) {
|
||||
bswap_savefile(buf->files[i] + 0);
|
||||
bswap_savefile(buf->files[i] + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void save_file_do_save(s32 fileIndex) {
|
||||
|
@ -260,7 +360,7 @@ void save_file_do_save(s32 fileIndex) {
|
|||
sizeof(gSaveBuffer.files[fileIndex][1]));
|
||||
|
||||
// Write to EEPROM
|
||||
write_eeprom_data(gSaveBuffer.files[fileIndex], sizeof(gSaveBuffer.files[fileIndex]));
|
||||
write_eeprom_savefile(fileIndex, 0, 2);
|
||||
|
||||
gSaveFileModified = FALSE;
|
||||
}
|
||||
|
@ -298,6 +398,9 @@ void save_file_load_all(void) {
|
|||
bzero(&gSaveBuffer, sizeof(gSaveBuffer));
|
||||
read_eeprom_data(&gSaveBuffer, sizeof(gSaveBuffer));
|
||||
|
||||
if (save_file_need_bswap(&gSaveBuffer))
|
||||
save_file_bswap(&gSaveBuffer);
|
||||
|
||||
// Verify the main menu data and create a backup copy if only one of the slots is valid.
|
||||
validSlots = verify_save_block_signature(&gSaveBuffer.menuData[0], sizeof(gSaveBuffer.menuData[0]), MENU_DATA_MAGIC);
|
||||
validSlots |= verify_save_block_signature(&gSaveBuffer.menuData[1], sizeof(gSaveBuffer.menuData[1]),MENU_DATA_MAGIC) << 1;
|
||||
|
|
|
@ -241,13 +241,10 @@ int render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct Wa
|
|||
}
|
||||
|
||||
Gfx *render_cannon_circle_base(void) {
|
||||
#ifdef TARGET_N64
|
||||
Vtx *verts = alloc_display_list(4 * sizeof(*verts));
|
||||
Gfx *dlist = alloc_display_list(16 * sizeof(*dlist));
|
||||
#else
|
||||
|
||||
Vtx *verts = alloc_display_list(8 * sizeof(*verts));
|
||||
Gfx *dlist = alloc_display_list(20 * sizeof(*dlist));
|
||||
#endif
|
||||
|
||||
Gfx *g = dlist;
|
||||
|
||||
if (verts != NULL && dlist != NULL) {
|
||||
|
@ -256,12 +253,10 @@ Gfx *render_cannon_circle_base(void) {
|
|||
make_vertex(verts, 2, SCREEN_WIDTH, SCREEN_HEIGHT, -1, 1152, 192, 0, 0, 0, 255);
|
||||
make_vertex(verts, 3, 0, SCREEN_HEIGHT, -1, -1152, 192, 0, 0, 0, 255);
|
||||
|
||||
#ifndef TARGET_N64
|
||||
make_vertex(verts, 4, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 0, -1, 0, 0, 0, 0, 0, 255);
|
||||
make_vertex(verts, 5, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), 0, -1, 0, 0, 0, 0, 0, 255);
|
||||
make_vertex(verts, 6, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, 0, 0, 0, 255);
|
||||
make_vertex(verts, 7, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, 0, 0, 0, 255);
|
||||
#endif
|
||||
|
||||
gSPDisplayList(g++, dl_proj_mtx_fullscreen);
|
||||
gDPSetCombineMode(g++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
|
||||
|
@ -272,12 +267,12 @@ Gfx *render_cannon_circle_base(void) {
|
|||
gSPVertex(g++, VIRTUAL_TO_PHYSICAL(verts), 4, 0);
|
||||
gSPDisplayList(g++, dl_draw_quad_verts_0123);
|
||||
gSPTexture(g++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF);
|
||||
#ifndef TARGET_N64
|
||||
|
||||
gDPSetCombineMode(g++, G_CC_SHADE, G_CC_SHADE);
|
||||
gSPVertex(g++, VIRTUAL_TO_PHYSICAL(verts + 4), 4, 4);
|
||||
gSP2Triangles(g++, 4, 0, 3, 0, 4, 3, 7, 0);
|
||||
gSP2Triangles(g++, 1, 5, 6, 0, 1, 6, 2, 0);
|
||||
#endif
|
||||
|
||||
gSPDisplayList(g++, dl_screen_transition_end);
|
||||
gSPEndDisplayList(g);
|
||||
} else {
|
||||
|
|
|
@ -242,7 +242,6 @@ void *create_skybox_ortho_matrix(s8 player) {
|
|||
f32 top = sSkyBoxInfo[player].scaledY;
|
||||
Mtx *mtx = alloc_display_list(sizeof(*mtx));
|
||||
|
||||
#ifndef TARGET_N64
|
||||
f32 half_width = (4.0f / 3.0f) / GFX_DIMENSIONS_ASPECT_RATIO * SCREEN_WIDTH / 2;
|
||||
f32 center = (sSkyBoxInfo[player].scaledX + SCREEN_WIDTH / 2);
|
||||
if (half_width < SCREEN_WIDTH / 2) {
|
||||
|
@ -250,7 +249,6 @@ void *create_skybox_ortho_matrix(s8 player) {
|
|||
left = center - half_width;
|
||||
right = center + half_width;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mtx != NULL) {
|
||||
guOrtho(mtx, left, right, bottom, top, 0.0f, 3.0f, 1.0f);
|
||||
|
|
|
@ -22,20 +22,15 @@
|
|||
#include "gd_math.h"
|
||||
#include "shape_helper.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "gfx_dimensions.h"
|
||||
|
||||
#define MAX_GD_DLS 1000
|
||||
#define OS_MESG_SI_COMPLETE 0x33333333
|
||||
|
||||
#ifdef TARGET_N64
|
||||
#define GD_VIRTUAL_TO_PHYSICAL(addr) ((uintptr_t)(addr) &0x0FFFFFFF)
|
||||
#define GD_LOWER_24(addr) ((uintptr_t)(addr) &0x00FFFFFF)
|
||||
#define GD_LOWER_29(addr) (((uintptr_t)(addr)) & 0x1FFFFFFF)
|
||||
#else
|
||||
#define GD_VIRTUAL_TO_PHYSICAL(addr) (addr)
|
||||
#define GD_LOWER_24(addr) ((uintptr_t)(addr))
|
||||
#define GD_LOWER_29(addr) (((uintptr_t)(addr)))
|
||||
#endif
|
||||
|
||||
#define MTX_INTPART_PACK(w1, w2) (((w1) &0xFFFF0000) | (((w2) >> 16) & 0xFFFF))
|
||||
#define MTX_FRACPART_PACK(w1, w2) ((((w1) << 16) & 0xFFFF0000) | ((w2) &0xFFFF))
|
||||
|
@ -1691,27 +1686,9 @@ u32 Unknown8019EC88(Gfx *dl, UNUSED s32 arg1) {
|
|||
|
||||
/* 24D4C4 -> 24D63C; orig name: func_8019ECF4 */
|
||||
void mat4_to_mtx(const Mat4f *src, Mtx *dst) {
|
||||
#ifdef TARGET_N64
|
||||
s32 i; // 14
|
||||
s32 j; // 10
|
||||
s32 w1;
|
||||
s32 w2;
|
||||
s32 *mtxInt = (s32 *) dst->m[0]; // s32 part
|
||||
s32 *mtxFrc = (s32 *) dst->m[2]; // frac part
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
w1 = (s32)((*src)[i][j * 2] * 65536.0f);
|
||||
w2 = (s32)((*src)[i][j * 2 + 1] * 65536.0f);
|
||||
*mtxInt = MTX_INTPART_PACK(w1, w2);
|
||||
mtxInt++;
|
||||
*mtxFrc = MTX_FRACPART_PACK(w1, w2);
|
||||
mtxFrc++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
guMtxF2L(src, dst);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* 24D63C -> 24D6E4; orig name: func_8019EE6C */
|
||||
|
@ -2326,7 +2303,7 @@ void start_view_dl(struct ObjView *view) {
|
|||
uly = lry - 1.0f;
|
||||
}
|
||||
|
||||
gDPSetScissor(next_gfx(), G_SC_NON_INTERLACE, ulx, uly, lrx, lry);
|
||||
// gDPSetScissor(next_gfx(), G_SC_NON_INTERLACE, ulx, uly, lrx, lry); // N64 only
|
||||
gSPClearGeometryMode(next_gfx(), 0xFFFFFFFF);
|
||||
gSPSetGeometryMode(next_gfx(), G_LIGHTING | G_CULL_BACK | G_SHADING_SMOOTH | G_SHADE);
|
||||
if (view->flags & VIEW_ALLOC_ZBUF) {
|
||||
|
@ -2985,9 +2962,9 @@ void update_cursor(void) {
|
|||
reset_dlnum_indices(sHandShape->gdDls[gGdFrameBuf]);
|
||||
|
||||
if (gGdCtrl.btnApressed) {
|
||||
gd_put_sprite((u16 *) gd_texture_hand_closed, sHandView->upperLeft.x, sHandView->upperLeft.y, 0x20, 0x20);
|
||||
gd_put_sprite((u16 *) gd_texture_hand_closed, sHandView->upperLeft.x, sHandView->upperLeft.y, 32, 32);
|
||||
} else {
|
||||
gd_put_sprite((u16 *) gd_texture_hand_open, sHandView->upperLeft.x, sHandView->upperLeft.y, 0x20, 0x20);
|
||||
gd_put_sprite((u16 *) gd_texture_hand_open, sHandView->upperLeft.x, sHandView->upperLeft.y, 32, 32);
|
||||
}
|
||||
gd_enddlsplist_parent();
|
||||
|
||||
|
@ -3443,7 +3420,8 @@ void Unknown801A5FF8(struct ObjGroup *arg0) {
|
|||
void gd_put_sprite(u16 *sprite, s32 x, s32 y, s32 wx, s32 wy) {
|
||||
s32 c; // 5c
|
||||
s32 r; // 58
|
||||
f32 aspect = GFX_DIMENSIONS_ASPECT_RATIO * 0.75;
|
||||
// Must be game screen aspect ratio, not GFX window aspect ratio
|
||||
f32 aspect = ((float) SCREEN_WIDTH) / ((float) SCREEN_HEIGHT ) * 0.75;
|
||||
x *= aspect;
|
||||
|
||||
gSPDisplayList(next_gfx(), osVirtualToPhysical(gd_dl_sprite_start_tex_block));
|
||||
|
@ -3632,89 +3610,9 @@ void Unknown801A6E30(UNUSED u32 a0) {
|
|||
void Unknown801A6E44(UNUSED u32 a0) {
|
||||
}
|
||||
|
||||
#ifdef TARGET_N64
|
||||
/* 255628 -> 255704; orig name: func_801A6E58 */
|
||||
void gd_block_dma(u32 devAddr, void *vAddr, s32 size) {
|
||||
s32 transfer; // 2c
|
||||
|
||||
do {
|
||||
if ((transfer = size) > 0x1000) {
|
||||
transfer = 0x1000;
|
||||
}
|
||||
|
||||
osPiStartDma(&D_801BE980, OS_MESG_PRI_NORMAL, OS_READ, devAddr, vAddr, transfer, &sGdDMAQueue);
|
||||
osRecvMesg(&sGdDMAQueue, &D_801BE97C, OS_MESG_BLOCK);
|
||||
devAddr += transfer;
|
||||
vAddr = (void *) ((uintptr_t) vAddr + transfer);
|
||||
size -= 0x1000;
|
||||
} while (size > 0);
|
||||
}
|
||||
|
||||
/* 255704 -> 255988 */
|
||||
struct GdObj *load_dynlist(struct DynList *dynlist) {
|
||||
u32 segSize; // 4c
|
||||
u8 *allocSegSpace; // 48
|
||||
void *allocPtr; // 44
|
||||
uintptr_t dynlistSegStart; // 40
|
||||
uintptr_t dynlistSegEnd; // 3c
|
||||
s32 i; // 38
|
||||
s32 sp34; // tlbPage
|
||||
struct GdObj *loadedList; // 30
|
||||
|
||||
i = -1;
|
||||
|
||||
while (sDynLists[++i].list != NULL) {
|
||||
if (sDynLists[i].list == dynlist) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sDynLists[i].list == NULL) {
|
||||
fatal_printf("load_dynlist() ptr not found in any banks");
|
||||
}
|
||||
|
||||
switch (sDynLists[i].flag) {
|
||||
case STD_LIST_BANK:
|
||||
dynlistSegStart = (uintptr_t) _gd_dynlistsSegmentRomStart;
|
||||
dynlistSegEnd = (uintptr_t) _gd_dynlistsSegmentRomEnd;
|
||||
break;
|
||||
default:
|
||||
fatal_printf("load_dynlist() unkown bank");
|
||||
}
|
||||
|
||||
segSize = dynlistSegEnd - dynlistSegStart;
|
||||
allocSegSpace = gd_malloc_temp(segSize + 0x10000);
|
||||
|
||||
if ((allocPtr = (void *) allocSegSpace) == NULL) {
|
||||
fatal_printf("Not enough DRAM for DATA segment \n");
|
||||
}
|
||||
|
||||
allocSegSpace = (u8 *) (((uintptr_t) allocSegSpace + 0x10000) & 0xFFFF0000);
|
||||
gd_block_dma(dynlistSegStart, (void *) allocSegSpace, segSize);
|
||||
osUnmapTLBAll();
|
||||
|
||||
sp34 = (segSize / 0x10000) / 2 + 1; //? has to be written this way
|
||||
if (sp34 >= 31) {
|
||||
fatal_printf("load_dynlist() too many TLBs");
|
||||
}
|
||||
|
||||
for (i = 0; i < sp34; i++) {
|
||||
osMapTLB(i, OS_PM_64K, (void *) (uintptr_t) (0x04000000 + (i * 2 * 0x10000)),
|
||||
GD_LOWER_24(((uintptr_t) allocSegSpace) + (i * 2 * 0x10000)),
|
||||
GD_LOWER_24(((uintptr_t) allocSegSpace) + (i * 2 * 0x10000) + 0x10000), -1);
|
||||
}
|
||||
|
||||
loadedList = proc_dynlist(dynlist);
|
||||
gd_free(allocPtr);
|
||||
osUnmapTLBAll();
|
||||
|
||||
return loadedList;
|
||||
}
|
||||
#else
|
||||
struct GdObj *load_dynlist(struct DynList *dynlist) {
|
||||
return proc_dynlist(dynlist);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 255988 -> 25599C */
|
||||
void stub_801A71B8(UNUSED u32 a0) {
|
||||
|
|
|
@ -303,9 +303,7 @@ void convert_gd_verts_to_Vn(struct ObjGroup *grp) {
|
|||
u8 nx, ny, nz; // 24, 25, 26
|
||||
UNUSED u32 pad20;
|
||||
register struct VtxLink *vtxlink; // a1
|
||||
#ifdef TARGET_N64
|
||||
register s16 *vnPos; // a2
|
||||
#endif
|
||||
|
||||
register s16 x; // a3
|
||||
register s16 y; // t0
|
||||
register s16 z; // t1
|
||||
|
@ -325,18 +323,12 @@ void convert_gd_verts_to_Vn(struct ObjGroup *grp) {
|
|||
nz = (u8)(vtx->normal.z * 255.0f);
|
||||
|
||||
for (vtxlink = vtx->gbiVerts; vtxlink != NULL; vtxlink = vtxlink->prev) {
|
||||
#ifdef TARGET_N64
|
||||
vnPos = vtxlink->data->n.ob;
|
||||
vn = vtxlink->data;
|
||||
*vnPos++ = x;
|
||||
*vnPos++ = y;
|
||||
*vnPos++ = z;
|
||||
#else
|
||||
|
||||
vn = vtxlink->data;
|
||||
vn->n.ob[0] = x;
|
||||
vn->n.ob[1] = y;
|
||||
vn->n.ob[2] = z;
|
||||
#endif
|
||||
|
||||
vn->n.n[0] = nx;
|
||||
vn->n.n[1] = ny;
|
||||
vn->n.n[2] = nz;
|
||||
|
@ -348,9 +340,7 @@ void convert_gd_verts_to_Vn(struct ObjGroup *grp) {
|
|||
void convert_gd_verts_to_Vtx(struct ObjGroup *grp) {
|
||||
UNUSED u32 pad24[6];
|
||||
register struct VtxLink *vtxlink; // a1
|
||||
#ifdef TARGET_N64
|
||||
register s16 *vtxcoords; // a2
|
||||
#endif
|
||||
|
||||
register s16 x; // a3
|
||||
register s16 y; // t0
|
||||
register s16 z; // t1
|
||||
|
@ -366,16 +356,10 @@ void convert_gd_verts_to_Vtx(struct ObjGroup *grp) {
|
|||
z = (s16) vtx->pos.z;
|
||||
|
||||
for (vtxlink = vtx->gbiVerts; vtxlink != NULL; vtxlink = vtxlink->prev) {
|
||||
#ifdef TARGET_N64
|
||||
vtxcoords = vtxlink->data->v.ob;
|
||||
vtxcoords[0] = x;
|
||||
vtxcoords[1] = y;
|
||||
vtxcoords[2] = z;
|
||||
#else
|
||||
|
||||
vtxlink->data->v.ob[0] = x;
|
||||
vtxlink->data->v.ob[1] = y;
|
||||
vtxlink->data->v.ob[2] = z;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ struct AudioAPI {
|
|||
int (*buffered)(void);
|
||||
int (*get_desired_buffered)(void);
|
||||
void (*play)(const uint8_t *buf, size_t len);
|
||||
void (*shutdown)(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,9 +15,13 @@ static int audio_null_get_desired_buffered(void) {
|
|||
static void audio_null_play(const uint8_t *buf, size_t len) {
|
||||
}
|
||||
|
||||
static void audio_null_shutdown(void) {
|
||||
}
|
||||
|
||||
struct AudioAPI audio_null = {
|
||||
audio_null_init,
|
||||
audio_null_buffered,
|
||||
audio_null_get_desired_buffered,
|
||||
audio_null_play
|
||||
};
|
||||
audio_null_play,
|
||||
audio_null_shutdown
|
||||
};
|
|
@ -40,9 +40,21 @@ static void audio_sdl_play(const uint8_t *buf, size_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
static void audio_sdl_shutdown(void)
|
||||
{
|
||||
if (SDL_WasInit(SDL_INIT_AUDIO)) {
|
||||
if (dev != 0) {
|
||||
SDL_CloseAudioDevice(dev);
|
||||
dev = 0;
|
||||
}
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
}
|
||||
}
|
||||
|
||||
struct AudioAPI audio_sdl = {
|
||||
audio_sdl_init,
|
||||
audio_sdl_buffered,
|
||||
audio_sdl_get_desired_buffered,
|
||||
audio_sdl_play
|
||||
audio_sdl_play,
|
||||
audio_sdl_shutdown
|
||||
};
|
42
src/pc/cliopts.c
Normal file
42
src/pc/cliopts.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include "cliopts.h"
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct PCCLIOptions gCLIOpts;
|
||||
|
||||
void parse_cli_opts(int argc, char* argv[])
|
||||
{
|
||||
// Initialize options with false values.
|
||||
gCLIOpts.SkipIntro = 0;
|
||||
gCLIOpts.FullScreen = 0;
|
||||
gCLIOpts.ConfigFile = malloc(31);
|
||||
strncpy(gCLIOpts.ConfigFile, "sm64config.txt", strlen("sm64config.txt"));
|
||||
|
||||
// Scan arguments for options
|
||||
if (argc > 1)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i], "--skip-intro") == 0) // Skip Peach Intro
|
||||
gCLIOpts.SkipIntro = 1;
|
||||
|
||||
if (strcmp(argv[i], "--fullscreen") == 0) // Open game in fullscreen
|
||||
gCLIOpts.FullScreen = 1;
|
||||
|
||||
if (strncmp(argv[i], "--configfile", strlen("--configfile")) == 0)
|
||||
{
|
||||
if (i+1 < argc)
|
||||
{
|
||||
if (strlen(argv[i]) > 30) {
|
||||
fprintf(stderr, "Configuration file supplied has a name too long.\n");
|
||||
} else {
|
||||
memset(gCLIOpts.ConfigFile, 0, 30);
|
||||
strncpy(gCLIOpts.ConfigFile, argv[i+1], strlen(argv[i+1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
src/pc/cliopts.h
Normal file
12
src/pc/cliopts.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "sm64.h"
|
||||
|
||||
struct PCCLIOptions
|
||||
{
|
||||
u8 SkipIntro;
|
||||
u8 FullScreen;
|
||||
char * ConfigFile;
|
||||
};
|
||||
|
||||
extern struct PCCLIOptions gCLIOpts;
|
||||
|
||||
void parse_cli_opts(int argc, char* argv[]);
|
|
@ -7,6 +7,7 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "controller/controller_api.h"
|
||||
|
||||
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
|
@ -14,6 +15,7 @@ enum ConfigOptionType {
|
|||
CONFIG_TYPE_BOOL,
|
||||
CONFIG_TYPE_UINT,
|
||||
CONFIG_TYPE_FLOAT,
|
||||
CONFIG_TYPE_BIND,
|
||||
};
|
||||
|
||||
struct ConfigOption {
|
||||
|
@ -29,74 +31,60 @@ struct ConfigOption {
|
|||
/*
|
||||
*Config options and default values
|
||||
*/
|
||||
bool configFullscreen = false;
|
||||
// Keyboard mappings (scancode values)
|
||||
unsigned int configKeyA = 0x26;
|
||||
unsigned int configKeyB = 0x33;
|
||||
unsigned int configKeyStart = 0x39;
|
||||
unsigned int configKeyL = 0x34;
|
||||
unsigned int configKeyR = 0x36;
|
||||
unsigned int configKeyZ = 0x25;
|
||||
unsigned int configKeyCUp = 0x148;
|
||||
unsigned int configKeyCDown = 0x150;
|
||||
unsigned int configKeyCLeft = 0x14B;
|
||||
unsigned int configKeyCRight = 0x14D;
|
||||
unsigned int configKeyStickUp = 0x11;
|
||||
unsigned int configKeyStickDown = 0x1F;
|
||||
unsigned int configKeyStickLeft = 0x1E;
|
||||
unsigned int configKeyStickRight = 0x20;
|
||||
// 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;
|
||||
|
||||
// Video/audio stuff
|
||||
bool configFullscreen = false;
|
||||
unsigned int configFiltering = 1; // 0=force nearest, 1=linear, (TODO) 2=three-point
|
||||
unsigned int configMasterVolume = MAX_VOLUME; // 0 - MAX_VOLUME
|
||||
|
||||
// Keyboard mappings (VK_ values, by default keyboard/gamepad/mouse)
|
||||
unsigned int configKeyA[MAX_BINDS] = { 0x0026, 0x1000, 0x1103 };
|
||||
unsigned int configKeyB[MAX_BINDS] = { 0x0033, 0x1002, 0x1101 };
|
||||
unsigned int configKeyStart[MAX_BINDS] = { 0x0039, 0x1006, VK_INVALID };
|
||||
unsigned int configKeyL[MAX_BINDS] = { 0x0034, 0x1007, 0x1104 };
|
||||
unsigned int configKeyR[MAX_BINDS] = { 0x0036, 0x100A, 0x1105 };
|
||||
unsigned int configKeyZ[MAX_BINDS] = { 0x0025, 0x1009, 0x1102 };
|
||||
unsigned int configKeyCUp[MAX_BINDS] = { 0x0148, VK_INVALID, VK_INVALID };
|
||||
unsigned int configKeyCDown[MAX_BINDS] = { 0x0150, VK_INVALID, VK_INVALID };
|
||||
unsigned int configKeyCLeft[MAX_BINDS] = { 0x014B, VK_INVALID, VK_INVALID };
|
||||
unsigned int configKeyCRight[MAX_BINDS] = { 0x014D, VK_INVALID, VK_INVALID };
|
||||
unsigned int configKeyStickUp[MAX_BINDS] = { 0x0011, VK_INVALID, VK_INVALID };
|
||||
unsigned int configKeyStickDown[MAX_BINDS] = { 0x001F, VK_INVALID, VK_INVALID };
|
||||
unsigned int configKeyStickLeft[MAX_BINDS] = { 0x001E, VK_INVALID, VK_INVALID };
|
||||
unsigned int configKeyStickRight[MAX_BINDS] = { 0x0020, VK_INVALID, VK_INVALID };
|
||||
|
||||
#ifdef BETTERCAMERA
|
||||
// BetterCamera settings
|
||||
unsigned int configCameraXSens = 50;
|
||||
unsigned int configCameraYSens = 50;
|
||||
unsigned int configCameraAggr = 0;
|
||||
unsigned int configCameraPan = 0;
|
||||
unsigned int configCameraDegrade = 10; // 0 - 100%
|
||||
bool configCameraInvertX = false;
|
||||
bool configCameraInvertY = false;
|
||||
bool configEnableCamera = false;
|
||||
bool configCameraMouse = false;
|
||||
#endif
|
||||
unsigned int configSkipIntro = 0;
|
||||
|
||||
static const struct ConfigOption options[] = {
|
||||
{.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configFullscreen},
|
||||
{.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},
|
||||
{.name = "key_cdown", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyCDown},
|
||||
{.name = "key_cleft", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyCLeft},
|
||||
{.name = "key_cright", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyCRight},
|
||||
{.name = "key_stickup", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickUp},
|
||||
{.name = "key_stickdown", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickDown},
|
||||
{.name = "key_stickleft", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickLeft},
|
||||
{.name = "key_stickright", .type = CONFIG_TYPE_UINT, .uintValue = &configKeyStickRight},
|
||||
{.name = "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},
|
||||
{.name = "texture_filtering", .type = CONFIG_TYPE_UINT, .uintValue = &configFiltering},
|
||||
{.name = "master_volume", .type = CONFIG_TYPE_UINT, .uintValue = &configMasterVolume},
|
||||
{.name = "key_a", .type = CONFIG_TYPE_BIND, .uintValue = configKeyA},
|
||||
{.name = "key_b", .type = CONFIG_TYPE_BIND, .uintValue = configKeyB},
|
||||
{.name = "key_start", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStart},
|
||||
{.name = "key_l", .type = CONFIG_TYPE_BIND, .uintValue = configKeyL},
|
||||
{.name = "key_r", .type = CONFIG_TYPE_BIND, .uintValue = configKeyR},
|
||||
{.name = "key_z", .type = CONFIG_TYPE_BIND, .uintValue = configKeyZ},
|
||||
{.name = "key_cup", .type = CONFIG_TYPE_BIND, .uintValue = configKeyCUp},
|
||||
{.name = "key_cdown", .type = CONFIG_TYPE_BIND, .uintValue = configKeyCDown},
|
||||
{.name = "key_cleft", .type = CONFIG_TYPE_BIND, .uintValue = configKeyCLeft},
|
||||
{.name = "key_cright", .type = CONFIG_TYPE_BIND, .uintValue = configKeyCRight},
|
||||
{.name = "key_stickup", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickUp},
|
||||
{.name = "key_stickdown", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickDown},
|
||||
{.name = "key_stickleft", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickLeft},
|
||||
{.name = "key_stickright", .type = CONFIG_TYPE_BIND, .uintValue = configKeyStickRight},
|
||||
#ifdef BETTERCAMERA
|
||||
{.name = "bettercam_enable", .type = CONFIG_TYPE_BOOL, .boolValue = &configEnableCamera},
|
||||
{.name = "bettercam_mouse_look", .type = CONFIG_TYPE_BOOL, .boolValue = &configCameraMouse},
|
||||
|
@ -106,7 +94,9 @@ static const struct ConfigOption options[] = {
|
|||
{.name = "bettercam_ysens", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraYSens},
|
||||
{.name = "bettercam_aggression", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraAggr},
|
||||
{.name = "bettercam_pan_level", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraPan},
|
||||
{.name = "bettercam_degrade", .type = CONFIG_TYPE_UINT, .uintValue = &configCameraDegrade},
|
||||
#endif
|
||||
{.name = "skip_intro", .type = CONFIG_TYPE_UINT, .uintValue = &configSkipIntro}, // Add this back!
|
||||
};
|
||||
|
||||
// Reads an entire line from a file (excluding the newline character) and returns an allocated string
|
||||
|
@ -207,9 +197,13 @@ void configfile_load(const char *filename) {
|
|||
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
|
||||
if (!*p || *p == '#') // comment or empty line
|
||||
continue;
|
||||
|
||||
numTokens = tokenize_string(p, 2, tokens);
|
||||
if (numTokens != 0) {
|
||||
if (numTokens == 2) {
|
||||
if (numTokens >= 2) {
|
||||
const struct ConfigOption *option = NULL;
|
||||
|
||||
for (unsigned int i = 0; i < ARRAY_LEN(options); i++) {
|
||||
|
@ -231,6 +225,10 @@ void configfile_load(const char *filename) {
|
|||
case CONFIG_TYPE_UINT:
|
||||
sscanf(tokens[1], "%u", option->uintValue);
|
||||
break;
|
||||
case CONFIG_TYPE_BIND:
|
||||
for (int i = 0; i < MAX_BINDS && i < numTokens - 1; ++i)
|
||||
sscanf(tokens[i + 1], "%x", option->uintValue + i);
|
||||
break;
|
||||
case CONFIG_TYPE_FLOAT:
|
||||
sscanf(tokens[1], "%f", option->floatValue);
|
||||
break;
|
||||
|
@ -273,6 +271,12 @@ void configfile_save(const char *filename) {
|
|||
case CONFIG_TYPE_FLOAT:
|
||||
fprintf(file, "%s %f\n", option->name, *option->floatValue);
|
||||
break;
|
||||
case CONFIG_TYPE_BIND:
|
||||
fprintf(file, "%s ", option->name);
|
||||
for (int i = 0; i < MAX_BINDS; ++i)
|
||||
fprintf(file, "%04x ", option->uintValue[i]);
|
||||
fprintf(file, "\n");
|
||||
break;
|
||||
default:
|
||||
assert(0); // unknown type
|
||||
}
|
||||
|
|
|
@ -3,40 +3,33 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CONFIG_FILE "sm64config.txt"
|
||||
#define MAX_BINDS 3
|
||||
#define MAX_VOLUME 127
|
||||
#define VOLUME_SHIFT 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;
|
||||
extern unsigned int configKeyCDown;
|
||||
extern unsigned int configKeyCLeft;
|
||||
extern unsigned int configKeyCRight;
|
||||
extern unsigned int configKeyStickUp;
|
||||
extern unsigned int configKeyStickDown;
|
||||
extern unsigned int configKeyStickLeft;
|
||||
extern unsigned int configKeyStickRight;
|
||||
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;
|
||||
extern unsigned int configFiltering;
|
||||
extern unsigned int configMasterVolume;
|
||||
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[];
|
||||
extern unsigned int configKeyCDown[];
|
||||
extern unsigned int configKeyCLeft[];
|
||||
extern unsigned int configKeyCRight[];
|
||||
extern unsigned int configKeyStickUp[];
|
||||
extern unsigned int configKeyStickDown[];
|
||||
extern unsigned int configKeyStickLeft[];
|
||||
extern unsigned int configKeyStickRight[];
|
||||
#ifdef BETTERCAMERA
|
||||
extern unsigned int configCameraXSens;
|
||||
extern unsigned int configCameraYSens;
|
||||
extern unsigned int configCameraAggr;
|
||||
extern unsigned int configCameraPan;
|
||||
extern unsigned int configCameraDegrade;
|
||||
extern bool configCameraInvertX;
|
||||
extern bool configCameraInvertY;
|
||||
extern bool configEnableCamera;
|
||||
|
|
|
@ -2,15 +2,25 @@
|
|||
#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
|
||||
#define VK_INVALID 0xFFFF
|
||||
#define VK_SIZE 0x1000
|
||||
|
||||
#include <ultra64.h>
|
||||
|
||||
struct ControllerAPI {
|
||||
void (*init)(void);
|
||||
void (*read)(OSContPad *pad);
|
||||
const u32 vkbase; // base number in the virtual keyspace (e.g. keyboard is 0x0000-0x1000)
|
||||
void (*init)(void); // call once, also calls reconfig()
|
||||
void (*read)(OSContPad *pad); // read controller and update N64 pad values
|
||||
u32 (*rawkey)(void); // returns last pressed virtual key or VK_INVALID if none
|
||||
void (*reconfig)(void); // (optional) call when bindings have changed
|
||||
void (*shutdown)(void); // (optional) call in osContReset
|
||||
};
|
||||
|
||||
// used for binding keys
|
||||
u32 controller_get_raw_key(void);
|
||||
void controller_reconfigure(void);
|
||||
|
||||
// calls the shutdown() function of all controller subsystems
|
||||
void controller_shutdown(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -56,3 +56,25 @@ void osContGetReadData(OSContPad *pad) {
|
|||
controller_implementations[i]->read(pad);
|
||||
}
|
||||
}
|
||||
|
||||
u32 controller_get_raw_key(void) {
|
||||
for (size_t i = 0; i < sizeof(controller_implementations) / sizeof(struct ControllerAPI *); i++) {
|
||||
u32 vk = controller_implementations[i]->rawkey();
|
||||
if (vk != VK_INVALID) return vk + controller_implementations[i]->vkbase;
|
||||
}
|
||||
return VK_INVALID;
|
||||
}
|
||||
|
||||
void controller_shutdown(void) {
|
||||
for (size_t i = 0; i < sizeof(controller_implementations) / sizeof(struct ControllerAPI *); i++) {
|
||||
if (controller_implementations[i]->shutdown)
|
||||
controller_implementations[i]->shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void controller_reconfigure(void) {
|
||||
for (size_t i = 0; i < sizeof(controller_implementations) / sizeof(struct ControllerAPI *); i++) {
|
||||
if (controller_implementations[i]->reconfig)
|
||||
controller_implementations[i]->reconfig();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,14 +8,19 @@
|
|||
#endif
|
||||
|
||||
#include "../configfile.h"
|
||||
#include "controller_keyboard.h"
|
||||
|
||||
static int keyboard_buttons_down;
|
||||
|
||||
static int keyboard_mapping[14][2];
|
||||
#define MAX_KEYBINDS 64
|
||||
static int keyboard_mapping[MAX_KEYBINDS][2];
|
||||
static int num_keybinds = 0;
|
||||
|
||||
static u32 keyboard_lastkey = VK_INVALID;
|
||||
|
||||
static int keyboard_map_scancode(int scancode) {
|
||||
int ret = 0;
|
||||
for (size_t i = 0; i < sizeof(keyboard_mapping) / sizeof(keyboard_mapping[0]); i++) {
|
||||
for (int i = 0; i < num_keybinds; i++) {
|
||||
if (keyboard_mapping[i][0] == scancode) {
|
||||
ret |= keyboard_mapping[i][1];
|
||||
}
|
||||
|
@ -26,12 +31,15 @@ static int keyboard_map_scancode(int scancode) {
|
|||
bool keyboard_on_key_down(int scancode) {
|
||||
int mapped = keyboard_map_scancode(scancode);
|
||||
keyboard_buttons_down |= mapped;
|
||||
keyboard_lastkey = scancode;
|
||||
return mapped != 0;
|
||||
}
|
||||
|
||||
bool keyboard_on_key_up(int scancode) {
|
||||
int mapped = keyboard_map_scancode(scancode);
|
||||
keyboard_buttons_down &= ~mapped;
|
||||
if (keyboard_lastkey == (u32) scancode)
|
||||
keyboard_lastkey = VK_INVALID;
|
||||
return mapped != 0;
|
||||
}
|
||||
|
||||
|
@ -39,28 +47,38 @@ void keyboard_on_all_keys_up(void) {
|
|||
keyboard_buttons_down = 0;
|
||||
}
|
||||
|
||||
static void set_keyboard_mapping(int index, int mask, int scancode) {
|
||||
keyboard_mapping[index][0] = scancode;
|
||||
keyboard_mapping[index][1] = mask;
|
||||
static void keyboard_add_binds(int mask, unsigned int *scancode) {
|
||||
for (int i = 0; i < MAX_BINDS && num_keybinds < MAX_KEYBINDS; ++i) {
|
||||
if (scancode[i] < VK_BASE_KEYBOARD + VK_SIZE) {
|
||||
keyboard_mapping[num_keybinds][0] = scancode[i];
|
||||
keyboard_mapping[num_keybinds][1] = mask;
|
||||
num_keybinds++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void keyboard_bindkeys(void) {
|
||||
bzero(keyboard_mapping, sizeof(keyboard_mapping));
|
||||
num_keybinds = 0;
|
||||
|
||||
keyboard_add_binds(0x80000, configKeyStickUp);
|
||||
keyboard_add_binds(0x10000, configKeyStickLeft);
|
||||
keyboard_add_binds(0x40000, configKeyStickDown);
|
||||
keyboard_add_binds(0x20000, configKeyStickRight);
|
||||
keyboard_add_binds(A_BUTTON, configKeyA);
|
||||
keyboard_add_binds(B_BUTTON, configKeyB);
|
||||
keyboard_add_binds(Z_TRIG, configKeyZ);
|
||||
keyboard_add_binds(U_CBUTTONS, configKeyCUp);
|
||||
keyboard_add_binds(L_CBUTTONS, configKeyCLeft);
|
||||
keyboard_add_binds(D_CBUTTONS, configKeyCDown);
|
||||
keyboard_add_binds(R_CBUTTONS, configKeyCRight);
|
||||
keyboard_add_binds(L_TRIG, configKeyL);
|
||||
keyboard_add_binds(R_TRIG, configKeyR);
|
||||
keyboard_add_binds(START_BUTTON, configKeyStart);
|
||||
}
|
||||
|
||||
static void keyboard_init(void) {
|
||||
int i = 0;
|
||||
|
||||
set_keyboard_mapping(i++, 0x80000, configKeyStickUp);
|
||||
set_keyboard_mapping(i++, 0x10000, configKeyStickLeft);
|
||||
set_keyboard_mapping(i++, 0x40000, configKeyStickDown);
|
||||
set_keyboard_mapping(i++, 0x20000, configKeyStickRight);
|
||||
set_keyboard_mapping(i++, A_BUTTON, configKeyA);
|
||||
set_keyboard_mapping(i++, B_BUTTON, configKeyB);
|
||||
set_keyboard_mapping(i++, Z_TRIG, configKeyZ);
|
||||
set_keyboard_mapping(i++, U_CBUTTONS, configKeyCUp);
|
||||
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);
|
||||
keyboard_bindkeys();
|
||||
|
||||
#ifdef TARGET_WEB
|
||||
controller_emscripten_keyboard_init();
|
||||
|
@ -83,7 +101,20 @@ static void keyboard_read(OSContPad *pad) {
|
|||
}
|
||||
}
|
||||
|
||||
static u32 keyboard_rawkey(void) {
|
||||
const u32 ret = keyboard_lastkey;
|
||||
keyboard_lastkey = VK_INVALID;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void keyboard_shutdown(void) {
|
||||
}
|
||||
|
||||
struct ControllerAPI controller_keyboard = {
|
||||
VK_BASE_KEYBOARD,
|
||||
keyboard_init,
|
||||
keyboard_read
|
||||
keyboard_read,
|
||||
keyboard_rawkey,
|
||||
keyboard_bindkeys,
|
||||
keyboard_shutdown
|
||||
};
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <stdbool.h>
|
||||
#include "controller_api.h"
|
||||
|
||||
# define VK_BASE_KEYBOARD 0x0000
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -23,7 +23,22 @@ static void tas_read(OSContPad *pad) {
|
|||
}
|
||||
}
|
||||
|
||||
static void tas_shutdown(void) {
|
||||
if (fp != NULL) {
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 tas_rawkey(void) {
|
||||
return VK_INVALID;
|
||||
}
|
||||
|
||||
struct ControllerAPI controller_recorded_tas = {
|
||||
VK_INVALID,
|
||||
tas_init,
|
||||
tas_read
|
||||
tas_read,
|
||||
tas_rawkey,
|
||||
NULL, // no rebinding
|
||||
tas_shutdown
|
||||
};
|
||||
|
|
|
@ -11,9 +11,15 @@
|
|||
#include <ultra64.h>
|
||||
|
||||
#include "controller_api.h"
|
||||
|
||||
#include "controller_sdl.h"
|
||||
#include "../configfile.h"
|
||||
|
||||
// mouse buttons are also in the controller namespace (why), just offset 0x100
|
||||
#define VK_OFS_SDL_MOUSE 0x0100
|
||||
#define VK_BASE_SDL_MOUSE (VK_BASE_SDL_GAMEPAD + VK_OFS_SDL_MOUSE)
|
||||
#define MAX_JOYBINDS 32
|
||||
#define MAX_MOUSEBUTTONS 8 // arbitrary
|
||||
|
||||
extern int16_t rightx;
|
||||
extern int16_t righty;
|
||||
|
||||
|
@ -27,6 +33,51 @@ extern u8 newcam_mouse;
|
|||
static bool init_ok;
|
||||
static SDL_GameController *sdl_cntrl;
|
||||
|
||||
|
||||
static u32 num_joy_binds = 0;
|
||||
static u32 num_mouse_binds = 0;
|
||||
static u32 joy_binds[MAX_JOYBINDS][2];
|
||||
static u32 mouse_binds[MAX_JOYBINDS][2];
|
||||
|
||||
static bool joy_buttons[SDL_CONTROLLER_BUTTON_MAX ] = { false };
|
||||
static u32 mouse_buttons = 0;
|
||||
static u32 last_mouse = VK_INVALID;
|
||||
static u32 last_joybutton = VK_INVALID;
|
||||
|
||||
static inline void controller_add_binds(const u32 mask, const u32 *btns) {
|
||||
for (u32 i = 0; i < MAX_BINDS; ++i) {
|
||||
if (btns[i] >= VK_BASE_SDL_GAMEPAD && btns[i] <= VK_BASE_SDL_GAMEPAD + VK_SIZE) {
|
||||
if (btns[i] >= VK_BASE_SDL_MOUSE && num_joy_binds < MAX_JOYBINDS) {
|
||||
mouse_binds[num_mouse_binds][0] = btns[i] - VK_BASE_SDL_MOUSE;
|
||||
mouse_binds[num_mouse_binds][1] = mask;
|
||||
++num_mouse_binds;
|
||||
} else if (num_mouse_binds < MAX_JOYBINDS) {
|
||||
joy_binds[num_joy_binds][0] = btns[i] - VK_BASE_SDL_GAMEPAD;
|
||||
joy_binds[num_joy_binds][1] = mask;
|
||||
++num_joy_binds;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void controller_sdl_bind(void) {
|
||||
bzero(joy_binds, sizeof(joy_binds));
|
||||
bzero(mouse_binds, sizeof(mouse_binds));
|
||||
num_joy_binds = 0;
|
||||
num_mouse_binds = 0;
|
||||
|
||||
controller_add_binds(A_BUTTON, configKeyA);
|
||||
controller_add_binds(B_BUTTON, configKeyB);
|
||||
controller_add_binds(Z_TRIG, configKeyZ);
|
||||
controller_add_binds(U_CBUTTONS, configKeyCUp);
|
||||
controller_add_binds(L_CBUTTONS, configKeyCLeft);
|
||||
controller_add_binds(D_CBUTTONS, configKeyCDown);
|
||||
controller_add_binds(R_CBUTTONS, configKeyCRight);
|
||||
controller_add_binds(L_TRIG, configKeyL);
|
||||
controller_add_binds(R_TRIG, configKeyR);
|
||||
controller_add_binds(START_BUTTON, configKeyStart);
|
||||
}
|
||||
|
||||
static void controller_sdl_init(void) {
|
||||
if (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS) != 0) {
|
||||
fprintf(stderr, "SDL init error: %s\n", SDL_GetError());
|
||||
|
@ -39,6 +90,8 @@ static void controller_sdl_init(void) {
|
|||
SDL_GetRelativeMouseState(&mouse_x, &mouse_y);
|
||||
#endif
|
||||
|
||||
controller_sdl_bind();
|
||||
|
||||
init_ok = true;
|
||||
}
|
||||
|
||||
|
@ -53,13 +106,16 @@ static void controller_sdl_read(OSContPad *pad) {
|
|||
else
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
|
||||
const u32 mbuttons = SDL_GetRelativeMouseState(&mouse_x, &mouse_y);
|
||||
u32 mouse = SDL_GetRelativeMouseState(&mouse_x, &mouse_y);
|
||||
|
||||
for (u32 i = 0; i < num_mouse_binds; ++i)
|
||||
if (mouse & SDL_BUTTON(mouse_binds[i][0]))
|
||||
pad->button |= mouse_binds[i][1];
|
||||
|
||||
// remember buttons that changed from 0 to 1
|
||||
last_mouse = (mouse_buttons ^ mouse) & mouse;
|
||||
mouse_buttons = mouse;
|
||||
|
||||
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();
|
||||
|
@ -82,12 +138,16 @@ static void controller_sdl_read(OSContPad *pad) {
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
for (u32 i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) {
|
||||
const bool new = SDL_GameControllerGetButton(sdl_cntrl, i);
|
||||
const bool pressed = !joy_buttons[i] && new;
|
||||
joy_buttons[i] = new;
|
||||
if (pressed) last_joybutton = i;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < num_joy_binds; ++i)
|
||||
if (joy_buttons[joy_binds[i][0]])
|
||||
pad->button |= joy_binds[i][1];
|
||||
|
||||
int16_t leftx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTX);
|
||||
int16_t lefty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTY);
|
||||
|
@ -127,7 +187,39 @@ static void controller_sdl_read(OSContPad *pad) {
|
|||
}
|
||||
}
|
||||
|
||||
static u32 controller_sdl_rawkey(void) {
|
||||
if (last_joybutton != VK_INVALID) {
|
||||
const u32 ret = last_joybutton;
|
||||
last_joybutton = VK_INVALID;
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_MOUSEBUTTONS; ++i) {
|
||||
if (last_mouse & SDL_BUTTON(i)) {
|
||||
const u32 ret = VK_OFS_SDL_MOUSE + i;
|
||||
last_mouse = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return VK_INVALID;
|
||||
}
|
||||
|
||||
static void controller_sdl_shutdown(void) {
|
||||
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER)) {
|
||||
if (sdl_cntrl) {
|
||||
SDL_GameControllerClose(sdl_cntrl);
|
||||
sdl_cntrl = NULL;
|
||||
}
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
}
|
||||
init_ok = false;
|
||||
}
|
||||
|
||||
struct ControllerAPI controller_sdl = {
|
||||
VK_BASE_SDL_GAMEPAD,
|
||||
controller_sdl_init,
|
||||
controller_sdl_read
|
||||
controller_sdl_read,
|
||||
controller_sdl_rawkey,
|
||||
controller_sdl_bind,
|
||||
controller_sdl_shutdown
|
||||
};
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "controller_api.h"
|
||||
|
||||
#define VK_BASE_SDL_GAMEPAD 0x1000
|
||||
|
||||
extern struct ControllerAPI controller_sdl;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,12 +18,19 @@
|
|||
#include <SDL2/SDL.h>
|
||||
#define GL_GLEXT_PROTOTYPES 1
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
|
||||
#else
|
||||
#include <SDL2/SDL.h>
|
||||
#define GL_GLEXT_PROTOTYPES 1
|
||||
|
||||
#ifdef OSX_BUILD
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
#else
|
||||
#include <SDL2/SDL_opengles2.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "gfx_cc.h"
|
||||
#include "gfx_rendering_api.h"
|
||||
|
||||
|
@ -49,7 +56,7 @@ static bool gfx_opengl_z_is_from_0_to_1(void) {
|
|||
static void gfx_opengl_vertex_array_set_attribs(struct ShaderProgram *prg) {
|
||||
size_t num_floats = prg->num_floats;
|
||||
size_t pos = 0;
|
||||
|
||||
|
||||
for (int i = 0; i < prg->num_attribs; i++) {
|
||||
glEnableVertexAttribArray(prg->attrib_locations[i]);
|
||||
glVertexAttribPointer(prg->attrib_locations[i], prg->attrib_sizes[i], GL_FLOAT, GL_FALSE, num_floats * sizeof(float), (void *)(pos * sizeof(float)));
|
||||
|
@ -179,15 +186,19 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad
|
|||
bool do_multiply[2] = {c[0][1] == 0 && c[0][3] == 0, c[1][1] == 0 && c[1][3] == 0};
|
||||
bool do_mix[2] = {c[0][1] == c[0][3], c[1][1] == c[1][3]};
|
||||
bool color_alpha_same = (shader_id & 0xfff) == ((shader_id >> 12) & 0xfff);
|
||||
|
||||
|
||||
char vs_buf[1024];
|
||||
char fs_buf[1024];
|
||||
size_t vs_len = 0;
|
||||
size_t fs_len = 0;
|
||||
size_t num_floats = 4;
|
||||
|
||||
|
||||
// Vertex shader
|
||||
#ifdef OSX_BUILD
|
||||
append_line(vs_buf, &vs_len, "");
|
||||
#else
|
||||
append_line(vs_buf, &vs_len, "#version 100");
|
||||
#endif
|
||||
append_line(vs_buf, &vs_len, "attribute vec4 aVtxPos;");
|
||||
if (used_textures[0] || used_textures[1]) {
|
||||
append_line(vs_buf, &vs_len, "attribute vec2 aTexCoord;");
|
||||
|
@ -216,10 +227,15 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad
|
|||
}
|
||||
append_line(vs_buf, &vs_len, "gl_Position = aVtxPos;");
|
||||
append_line(vs_buf, &vs_len, "}");
|
||||
|
||||
|
||||
// Fragment shader
|
||||
#ifdef OSX_BUILD
|
||||
append_line(fs_buf, &fs_len, "");
|
||||
#else
|
||||
append_line(fs_buf, &fs_len, "#version 100");
|
||||
append_line(fs_buf, &fs_len, "precision mediump float;");
|
||||
#endif
|
||||
|
||||
if (used_textures[0] || used_textures[1]) {
|
||||
append_line(fs_buf, &fs_len, "varying vec2 vTexCoord;");
|
||||
}
|
||||
|
@ -408,9 +424,10 @@ static uint32_t gfx_cm_to_opengl(uint32_t val) {
|
|||
}
|
||||
|
||||
static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) {
|
||||
const GLenum filter = linear_filter ? GL_LINEAR : GL_NEAREST;
|
||||
glActiveTexture(GL_TEXTURE0 + tile);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear_filter ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear_filter ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gfx_cm_to_opengl(cms));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gfx_cm_to_opengl(cmt));
|
||||
}
|
||||
|
@ -463,7 +480,11 @@ static void gfx_opengl_init(void) {
|
|||
#if FOR_WINDOWS
|
||||
glewInit();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef OSX_BUILD
|
||||
glewInit();
|
||||
#endif
|
||||
|
||||
glGenBuffers(1, &opengl_vbo);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, opengl_vbo);
|
||||
|
@ -480,6 +501,9 @@ static void gfx_opengl_start_frame(void) {
|
|||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
static void gfx_opengl_shutdown(void) {
|
||||
}
|
||||
|
||||
struct GfxRenderingAPI gfx_opengl_api = {
|
||||
gfx_opengl_z_is_from_0_to_1,
|
||||
gfx_opengl_unload_shader,
|
||||
|
@ -499,5 +523,6 @@ struct GfxRenderingAPI gfx_opengl_api = {
|
|||
gfx_opengl_set_use_alpha,
|
||||
gfx_opengl_draw_triangles,
|
||||
gfx_opengl_init,
|
||||
gfx_opengl_start_frame
|
||||
gfx_opengl_start_frame,
|
||||
gfx_opengl_shutdown
|
||||
};
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "gfx_rendering_api.h"
|
||||
#include "gfx_screen_config.h"
|
||||
|
||||
#include "../configfile.h"
|
||||
|
||||
#define SUPPORT_CHECK(x) assert(x)
|
||||
|
||||
// SCALE_M_N: upscale/downscale M-bit integer to N-bit
|
||||
|
@ -586,10 +588,16 @@ static void gfx_sp_vertex(size_t n_vertices, size_t dest_index, const Vtx *verti
|
|||
calculate_normal_dir(&lookat_y, rsp.current_lookat_coeffs[1]);
|
||||
rsp.lights_changed = false;
|
||||
}
|
||||
|
||||
int r = rsp.current_lights[rsp.current_num_lights - 1].col[0];
|
||||
int g = rsp.current_lights[rsp.current_num_lights - 1].col[1];
|
||||
int b = rsp.current_lights[rsp.current_num_lights - 1].col[2];
|
||||
|
||||
// Inspired by:
|
||||
// https://github.com/gonetz/GLideN64/commit/c8cbafff71a81bee5112aaafe6e21d6648ff8125#diff-69d8715ec7f9fd627ec4f5516edd003dL484
|
||||
const bool useFirstColor = (dest_index & 1) == 0;
|
||||
const unsigned char* col = useFirstColor
|
||||
? rsp.current_lights[rsp.current_num_lights - 1].col
|
||||
: rsp.current_lights[rsp.current_num_lights - 1].colc;
|
||||
int r = col[0];
|
||||
int g = col[1];
|
||||
int b = col[2];
|
||||
|
||||
for (int i = 0; i < rsp.current_num_lights - 1; i++) {
|
||||
float intensity = 0;
|
||||
|
@ -598,9 +606,14 @@ static void gfx_sp_vertex(size_t n_vertices, size_t dest_index, const Vtx *verti
|
|||
intensity += vn->n[2] * rsp.current_lights_coeffs[i][2];
|
||||
intensity /= 127.0f;
|
||||
if (intensity > 0.0f) {
|
||||
r += intensity * rsp.current_lights[i].col[0];
|
||||
g += intensity * rsp.current_lights[i].col[1];
|
||||
b += intensity * rsp.current_lights[i].col[2];
|
||||
// Inspired by:
|
||||
// https://github.com/gonetz/GLideN64/commit/c8cbafff71a81bee5112aaafe6e21d6648ff8125#diff-69d8715ec7f9fd627ec4f5516edd003dL492
|
||||
col = useFirstColor
|
||||
? rsp.current_lights[i].col
|
||||
: rsp.current_lights[i].colc;
|
||||
r += intensity * col[0];
|
||||
g += intensity * col[1];
|
||||
b += intensity * col[2];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -780,7 +793,7 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx) {
|
|||
import_texture(i);
|
||||
rdp.textures_changed[i] = false;
|
||||
}
|
||||
bool linear_filter = (rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) != G_TF_POINT;
|
||||
bool linear_filter = configFiltering && ((rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) != G_TF_POINT);
|
||||
if (linear_filter != rendering_state.textures[i]->linear_filter || rdp.texture_tile.cms != rendering_state.textures[i]->cms || rdp.texture_tile.cmt != rendering_state.textures[i]->cmt) {
|
||||
gfx_flush();
|
||||
gfx_rapi->set_sampler_parameters(i, linear_filter, rdp.texture_tile.cms, rdp.texture_tile.cmt);
|
||||
|
@ -1562,3 +1575,14 @@ void gfx_end_frame(void) {
|
|||
gfx_wapi->swap_buffers_end();
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_shutdown(void) {
|
||||
if (gfx_rapi) {
|
||||
if (gfx_rapi->shutdown) gfx_rapi->shutdown();
|
||||
gfx_rapi = NULL;
|
||||
}
|
||||
if (gfx_wapi) {
|
||||
if (gfx_wapi->shutdown) gfx_wapi->shutdown();
|
||||
gfx_wapi = NULL;
|
||||
}
|
||||
}
|
|
@ -15,5 +15,6 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi);
|
|||
void gfx_start_frame(void);
|
||||
void gfx_run(Gfx *commands);
|
||||
void gfx_end_frame(void);
|
||||
void gfx_shutdown(void);
|
||||
|
||||
#endif
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue