Registrarse

[Otros] (BDSP) (C++) Inserción de Código ExeFS

Blup

Ribbit ribbit
Encargado de Switch
(BDSP) (C++) Inserción de Código ExeFS

Introducción

En este tutorial voy a enseñar cómo preparar el entorno de desarrollo para crear mods que editan el código del juego.

¿Qué es la inserción de código ExeFS?

Insertar código ExeFS requiere de:
  • Investigar el código fuente del juego utilizando herramientas de ingeniería inversa
  • Buscar funciones que queremos reemplazar
  • Entender cómo funcionan esas funciones
  • Escribir una nueva función en C++ que reemplazará el código original
Cuando el juego llame a la función, se ejecutará lo que hemos escrito nosotros.

¿Qué se puede hacer con esto?

Editando el código ExeFS es posible hacer cosas como:
  • Programar nuevas habilidades y movimientos
  • Crear nuevos objetos (caramelos raros infinitos)
  • Modificar las probabilidades de encontrar un Pokémon shiny
  • Crear nuevos sistemas (límite de nivel basado en medallas obtenidas)
  • Y mucho más
Importante: Este es un tema mucho más avanzado que los otros tutoriales que he escrito. Es recomendable tener conocimientos sobre ingeniería inversa (Ghidra/IDA) y C++.

Para contactar conmigo y resolver dudas, podéis uniros a mi servidor de Discord sobre modding de BDSP: https://discord.gg/5Qwz85EvC3

Índice del tutorial
  • Introducción
  • Preparando Ghidra
  • Preparando Starlight
  • Ejemplo 1: Modificar las probabilidades de Shiny
  • Ejemplo 2: Límite de nivel personalizado
  • Documentación extra

Preparando Ghidra

¿Qué es Ghidra?

Ghidra es el programa de ingeniería inversa que se utiliza para:
  • Investigar el código fuente del juego
  • Encontrar la localización (offsets) de las funciones
  • Saber dónde debemos inyectar el código

Instalación y configuración

El proceso para instalar y preparar el programa es sencillo, así que no me extenderé en este tutorial.

Podéis encontrar toda la información detallada en la documentación de Team Luminescent: https://luminescent.team/rom-hacking/exefs/ghidra

Preparando Starlight

En este tutorial voy a enseñar únicamente cómo trabajar con la plantilla que se utiliza para Luminescent Platinum, ya que es lo más accesible para empezar y utilizar como ejemplo.

Alternativa avanzada: Re:Illuminated Platinum utiliza otra plantilla (Exlaunch). Podéis echarle un vistazo al repositorio: https://github.com/TeamLumi/Luminescent_ExLaunch y tenéis una guía de cómo prepararlo en: https://luminescent.team/rom-hacking/exefs/exlaunch

Paso 1: Clonar el repositorio

El primer paso es clonar el fork de Starlight de Luminescent Platinum: https://github.com/SaltContainer/Luminescent

Herramientas recomendadas

Paso 2: Instalar WSL y Ubuntu (Windows)

Instalación de WSL
Abrid CMD y escribid los siguientes comandos:
Código:
wsl --install
A continuación es recomendable utilizar la versión 2 de WSL:
Código:
wsl --set-default-version 2
Después instalamos Ubuntu:
Código:
wsl --install -d Ubuntu
Una vez Ubuntu está instalado, es posible que tengáis que reiniciar el ordenador, y se os pedirá que elijáis un usuario y contraseña.

Paso 3: Instalar dependencias en Ubuntu

El siguiente paso es instalar todo lo necesario en Ubuntu. Vamos a necesitar:
  • CMake (versión 3.25.2)
  • devkitpro (devkitA64 versión r24-1)
Para ello, abrid la consola de WSL (podéis simplemente buscar WSL en el menu de inicio de Windows).

Instalación de devkitpro

Ejecutad los siguientes comandos:
Código:
wget https://apt.devkitpro.org/install-devkitpro-pacman
chmod +x ./install-devkitpro-pacman
sudo ./install-devkitpro-pacman
Instalación de paquetes de Switch

Después necesitamos instalar los paquetes de switch-dev y switch-portlibs:
Código:
sudo dkp-pacman -Sy
sudo dkp-pacman -S switch-dev
sudo dkp-pacman -S switch-portlibs
Instalación de devkitA64 r24

A continuación, necesitamos específicamente la versión r24 de devkitA64:
Código:
sudo wget "https://wii.leseratte10.de/devkitPro/devkitA64/r24%20%282023-09-17%29/devkitA64-r24-1-linux_x86_64.pkg.tar.zst" -O devkitA64-r24-1.pkg.tar.zst
sudo dkp-pacman -U ./devkitA64-r24-1.pkg.tar.zst
Instalación de keystone-engine

El siguiente paso es instalar la librería keystone-engine para Python:
Código:
sudo apt update
sudo apt install python-is-python3 pip
pip install keystone-engine
Instalación de CMake

Después instalamos CMake:
Código:
wget https://github.com/Kitware/CMake/releases/download/v3.25.2/cmake-3.25.2-linux-x86_64.sh
chmod +x cmake-3.25.2-linux-x86_64.sh
./cmake-3.25.2-linux-x86_64.sh
export PATH=/home/blupblurp/cmake-3.25.2-linux-x86_64/bin:$PATH
Importante: Reemplazad "blupblurp" con el nombre que habéis elegido para vuestro usuario.
Eso sería todo lo que necesitamos instalar por ahora.

Paso 4: Configurar CLion

Configuración de Toolchains

Abrid el repositorio que habéis clonado con CLion y dirigíos a: Settings > Build, Execution, Deployment > Toolchains

Aquí seleccionaremos:
  • WSL
  • Vuestra distribución de Ubuntu
  • La ruta de CMake como se ve en la imagen
Nota: gdb-multiarch se utiliza para hacer debugging, veremos cómo más adelante


Configuración de CMake

Luego, debajo de Toolchains seleccionad CMake, y configuradlo de la siguiente forma:



En CMake options tenéis que escribir:
Código:
-G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain.cmake
En Environment:
Código:
DEVKITPRO=/opt/devkitpro
El argumento de Build options es opcional. En este caso -j 12 indica que CMake puede usar 12 núcleos en mi CPU.

Paso 5: Recargar CMake

Y eso sería todo lo que tenéis que configurar. Ahora podéis:
  1. Cerrar la pestaña de configuración
  2. En CLion, abajo a la izquierda, seleccionar CMake
  3. A continuación hacer clic en Reload



Paso 6: Compilar por primera vez

Para aseguraros de que habéis configurado e instalado todo correctamente:
  1. Dirigíos a arriba a la derecha
  2. Seleccionad una configuración
  3. Hacer clic en Build



Sobre las configuraciones disponibles

Todas las configuraciones compilan el mismo resultado:
  • Las opciones de Ryujinx, Yuzu o Atmosphere tan solo tienen una estructura de carpetas distinta
  • Las opciones de zip comprimen directamente los archivos en un zip
  • Yo recomiendo utilizar release_ryujinx

Resultados de la compilación
  • Si compila con errores: Es posible que os hayáis saltado alguno de los pasos anteriores
  • Si compila exitosamente: En la carpeta de vuestro proyecto se creará una carpeta llamada release, que contiene una carpeta exefs

Instalación del mod

Para instalar vuestro mod:
  1. Copiad la carpeta exefs generada
  2. Pegadla en la carpeta de Luminescent Platinum (donde se encuentran las carpetas romfs y exefs)
  3. Reemplazad cuando os lo indique

Ejemplo 1: Modificar las probabilidades de Shiny

Crear nuevos parches es algo muy complejo y requiere de mucha investigación, por lo que como ejemplo, voy a enseñaros a editar uno de los parches existentes.

Localización del archivo

En la carpeta src, encontraréis una carpeta patches. Dentro tenéis todas las modificaciones que fueron programadas para Luminescent Platinum.

Como ejemplo, vamos a centrarnos en el archivo shiny.cpp:



¿Qué hace este parche?

Este parche modifica la probabilidad de encontrar un Pokémon shiny:
  • Por defecto en BDSP: La probabilidad es de 1 entre 4096
  • En Luminescent: Modifica esta probabilidad haciendo que el juego vuelva a intentarlo ocho veces, lo que aproximadamente da una probabilidad de 8 entre 4096

Pasos para modificar el parche

Cambiar la probabilidad base

Podemos editar el valor uint8_t rolls = 8; para cambiar la probabilidad.

Por ejemplo, cambiadlo a 41 veces:
Código:
uint8_t rolls = 41;
Esto resulta en aproximadamente un 1% de probabilidades.

Modificar el efecto del Amuleto Iris

También podemos modificar la probabilidad extra que añade tener el objeto Amuleto Iris (por defecto 2 veces más en Lumi).

Limitación importante: Ya que este número se guarda en una variable de tipo byte, el valor total máximo (probabilidad base + amuleto iris) no puede superar 255 (6%).

Compilar e instalar

Si modificáis estos valores y compiláis el proyecto como he indicado anteriormente:
  1. Obtendréis vuestro propio parche ExeFS
  2. Podéis utilizarlo para reemplazar el de Luminescent Platinum
  3. Modificará la probabilidad de encontrar Pokémon shiny en vuestro juego

Descarga directa

Si simplemente queréis utilizar este mod sin hacerlo vosotros mismos, ya he publicado el parche en Nexus Mods: https://www.nexusmods.com/pokemonbdsp/mods/59

Podéis echarle un vistazo al resto de parches para modificarlos o entender mejor cómo funciona todo y poder crear los vuestros propios.

Ejemplo 2: Límite de nivel personalizado

Otro parche que creo que puede ser interesante modificar en vuestros proyectos es el límite de nivel.

Localización del archivo

Para ello dirigíos a la carpeta src y al archivo util.cpp

Aquí encontraréis algunas funciones que son utilizadas en otros parches.

Modificar el Límite de nivel

Editar flags requeridas

Para editar qué flags deben estar activadas en los scripts para activar el siguiente límite de nivel, podéis modificar la función getLevelCapIndex():



Editar niveles máximos

Para modificar el nivel máximo de cada límite, podéis modificar la función getMaxLevelOfCapIndex():



Documentación extra

Recursos para crear tus propios parches

Para más información y cómo crear vuestros propios parches desde cero, visitad:

Wiki de Team Luminescent
https://luminescent.team/rom-hacking/category/exefs

Wiki de BDSP Modding
https://bdsp-modding.wiki/index.php/Code_Injection
 

Micolo

Autista de creatividad ilimitada
Miembro del equipo
Moderador/a
Un tutorial impresionante que será muy útil para los curiosos
 

Erkey830

Fuck off!
Miembro del equipo
Moderador/a
(BDSP) (C++) Inserción de Código ExeFS

Introducción

En este tutorial voy a enseñar cómo preparar el entorno de desarrollo para crear mods que editan el código del juego.

¿Qué es la inserción de código ExeFS?

Insertar código ExeFS requiere de:
  • Investigar el código fuente del juego utilizando herramientas de ingeniería inversa
  • Buscar funciones que queremos reemplazar
  • Entender cómo funcionan esas funciones
  • Escribir una nueva función en C++ que reemplazará el código original
Cuando el juego llame a la función, se ejecutará lo que hemos escrito nosotros.

¿Qué se puede hacer con esto?

Editando el código ExeFS es posible hacer cosas como:
  • Programar nuevas habilidades y movimientos
  • Crear nuevos objetos (caramelos raros infinitos)
  • Modificar las probabilidades de encontrar un Pokémon shiny
  • Crear nuevos sistemas (límite de nivel basado en medallas obtenidas)
  • Y mucho más
Importante: Este es un tema mucho más avanzado que los otros tutoriales que he escrito. Es recomendable tener conocimientos sobre ingeniería inversa (Ghidra/IDA) y C++.




Índice del tutorial
  • Introducción
  • Preparando Ghidra
  • Preparando Starlight
  • Ejemplo 1: Modificar las probabilidades de Shiny
  • Ejemplo 2: Límite de nivel personalizado
  • Documentación extra

Preparando Ghidra

¿Qué es Ghidra?

Ghidra es el programa de ingeniería inversa que se utiliza para:
  • Investigar el código fuente del juego
  • Encontrar la localización (offsets) de las funciones
  • Saber dónde debemos inyectar el código

Instalación y configuración

El proceso para instalar y preparar el programa es sencillo, así que no me extenderé en este tutorial.

Podéis encontrar toda la información detallada en la documentación de Team Luminescent: https://luminescent.team/rom-hacking/exefs/ghidra

Preparando Starlight

En este tutorial voy a enseñar únicamente cómo trabajar con la plantilla que se utiliza para Luminescent Platinum, ya que es lo más accesible para empezar y utilizar como ejemplo.




Paso 1: Clonar el repositorio

El primer paso es clonar el fork de Starlight de Luminescent Platinum: https://github.com/SaltContainer/Luminescent

Herramientas recomendadas

Paso 2: Instalar WSL y Ubuntu (Windows)

Instalación de WSL
Abrid CMD y escribid los siguientes comandos:
Código:
wsl --install
A continuación es recomendable utilizar la versión 2 de WSL:
Código:
wsl --set-default-version 2
Después instalamos Ubuntu:
Código:
wsl --install -d Ubuntu



Paso 3: Instalar dependencias en Ubuntu

El siguiente paso es instalar todo lo necesario en Ubuntu. Vamos a necesitar:
  • CMake (versión 3.25.2)
  • devkitpro (devkitA64 versión r24-1)
Para ello, abrid la consola de WSL (podéis simplemente buscar WSL en el menu de inicio de Windows).

Instalación de devkitpro

Ejecutad los siguientes comandos:
Código:
wget https://apt.devkitpro.org/install-devkitpro-pacman
chmod +x ./install-devkitpro-pacman
sudo ./install-devkitpro-pacman
Instalación de paquetes de Switch

Después necesitamos instalar los paquetes de switch-dev y switch-portlibs:
Código:
sudo dkp-pacman -Sy
sudo dkp-pacman -S switch-dev
sudo dkp-pacman -S switch-portlibs
Instalación de devkitA64 r24

A continuación, necesitamos específicamente la versión r24 de devkitA64:
Código:
sudo wget "https://wii.leseratte10.de/devkitPro/devkitA64/r24%20%282023-09-17%29/devkitA64-r24-1-linux_x86_64.pkg.tar.zst" -O devkitA64-r24-1.pkg.tar.zst
sudo dkp-pacman -U ./devkitA64-r24-1.pkg.tar.zst
Instalación de keystone-engine

El siguiente paso es instalar la librería keystone-engine para Python:
Código:
sudo apt update
sudo apt install python-is-python3 pip
pip install keystone-engine
Instalación de CMake

Después instalamos CMake:
Código:
wget https://github.com/Kitware/CMake/releases/download/v3.25.2/cmake-3.25.2-linux-x86_64.sh
chmod +x cmake-3.25.2-linux-x86_64.sh
./cmake-3.25.2-linux-x86_64.sh
export PATH=/home/blupblurp/cmake-3.25.2-linux-x86_64/bin:$PATH


Eso sería todo lo que necesitamos instalar por ahora.

Paso 4: Configurar CLion

Configuración de Toolchains

Abrid el repositorio que habéis clonado con CLion y dirigíos a: Settings > Build, Execution, Deployment > Toolchains

Aquí seleccionaremos:
  • WSL
  • Vuestra distribución de Ubuntu
  • La ruta de CMake como se ve en la imagen




Configuración de CMake

Luego, debajo de Toolchains seleccionad CMake, y configuradlo de la siguiente forma:



En CMake options tenéis que escribir:
Código:
-G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain.cmake
En Environment:
Código:
DEVKITPRO=/opt/devkitpro



Paso 5: Recargar CMake

Y eso sería todo lo que tenéis que configurar. Ahora podéis:
  1. Cerrar la pestaña de configuración
  2. En CLion, abajo a la izquierda, seleccionar CMake
  3. A continuación hacer clic en Reload



Paso 6: Compilar por primera vez

Para aseguraros de que habéis configurado e instalado todo correctamente:
  1. Dirigíos a arriba a la derecha
  2. Seleccionad una configuración
  3. Hacer clic en Build



Sobre las configuraciones disponibles

Todas las configuraciones compilan el mismo resultado:
  • Las opciones de Ryujinx, Yuzu o Atmosphere tan solo tienen una estructura de carpetas distinta
  • Las opciones de zip comprimen directamente los archivos en un zip
  • Yo recomiendo utilizar release_ryujinx

Resultados de la compilación
  • Si compila con errores: Es posible que os hayáis saltado alguno de los pasos anteriores
  • Si compila exitosamente: En la carpeta de vuestro proyecto se creará una carpeta llamada release, que contiene una carpeta exefs

Instalación del mod

Para instalar vuestro mod:
  1. Copiad la carpeta exefs generada
  2. Pegadla en la carpeta de Luminescent Platinum (donde se encuentran las carpetas romfs y exefs)
  3. Reemplazad cuando os lo indique

Ejemplo 1: Modificar las probabilidades de Shiny

Crear nuevos parches es algo muy complejo y requiere de mucha investigación, por lo que como ejemplo, voy a enseñaros a editar uno de los parches existentes.

Localización del archivo

En la carpeta src, encontraréis una carpeta patches. Dentro tenéis todas las modificaciones que fueron programadas para Luminescent Platinum.

Como ejemplo, vamos a centrarnos en el archivo shiny.cpp:



¿Qué hace este parche?

Este parche modifica la probabilidad de encontrar un Pokémon shiny:
  • Por defecto en BDSP: La probabilidad es de 1 entre 4096
  • En Luminescent: Modifica esta probabilidad haciendo que el juego vuelva a intentarlo ocho veces, lo que aproximadamente da una probabilidad de 8 entre 4096

Pasos para modificar el parche

Cambiar la probabilidad base

Podemos editar el valor uint8_t rolls = 8; para cambiar la probabilidad.

Por ejemplo, cambiadlo a 41 veces:
Código:
uint8_t rolls = 41;
Esto resulta en aproximadamente un 1% de probabilidades.

Modificar el efecto del Amuleto Iris

También podemos modificar la probabilidad extra que añade tener el objeto Amuleto Iris (por defecto 2 veces más en Lumi).




Compilar e instalar

Si modificáis estos valores y compiláis el proyecto como he indicado anteriormente:
  1. Obtendréis vuestro propio parche ExeFS
  2. Podéis utilizarlo para reemplazar el de Luminescent Platinum
  3. Modificará la probabilidad de encontrar Pokémon shiny en vuestro juego

Descarga directa

Si simplemente queréis utilizar este mod sin hacerlo vosotros mismos, ya he publicado el parche en Nexus Mods: https://www.nexusmods.com/pokemonbdsp/mods/59




Ejemplo 2: Límite de nivel personalizado

Otro parche que creo que puede ser interesante modificar en vuestros proyectos es el límite de nivel.

Localización del archivo

Para ello dirigíos a la carpeta src y al archivo util.cpp

Aquí encontraréis algunas funciones que son utilizadas en otros parches.

Modificar el Límite de nivel

Editar flags requeridas

Para editar qué flags deben estar activadas en los scripts para activar el siguiente límite de nivel, podéis modificar la función getLevelCapIndex():



Editar niveles máximos

Para modificar el nivel máximo de cada límite, podéis modificar la función getMaxLevelOfCapIndex():



Documentación extra

Recursos para crear tus propios parches

Para más información y cómo crear vuestros propios parches desde cero, visitad:

Wiki de Team Luminescent
https://luminescent.team/rom-hacking/category/exefs

Wiki de BDSP Modding
https://bdsp-modding.wiki/index.php/Code_Injection
Pregunta:
Mediante este tutorial por ejemplo podríamos modificar la Pokedex o añadir nuevas especies sin usar el método de las formas regionales?
 

Blup

Ribbit ribbit
Encargado de Switch
Pregunta:
Mediante este tutorial por ejemplo podríamos modificar la Pokedex o añadir nuevas especies sin usar el método de las formas regionales?
Sí, definitivamente.
Le puedes echar un vistazo a src/patches/drnd.cpp ahí es donde se añaden las nuevas entradas de Lumi como Litwick, Sylveon, Pikipek, Obstagoon, etc. 17 nuevos Pokémon añadidos.
Pero tienes que añadirlos a mano cada vez que quieras incluir uno nuevo.

Relumi lo hace con Exlaunch, puedes encontrar como en src/mod/features/save_data/dex_expansion.cpp
La Pokédex está expandida a 1025 entradas, y puede expandirse a cualquier número fácilmente, pero requiere de modificar el formato y estructura del archivo de guardado.
 
Arriba