Registrarse

N64 Romhacking #1 [MIPS ASM]

seohaine

Usuario de platino
Hola, soy seohaine y he decidido hacer un tutorial de como romhackear juegos de n64 ya que hubieron muchos que me escribían en las redes preguntando, y pues no iba a decirles a cada uno el como hacer las cosas, entonces hare esta guía para que aprendan, así que vamos al lio...

Esta guía la hare muy enfocada al romhacking e ingeniería inversa para que aprendan rápido.

La N64 tiene su propio lenguaje el cual adoptaron casi todas las consolas de nintendo y sony este lenguaje de ensamblador es MIPS el cual es muy preciso a la hora de inyectar código.


Este lenguaje se compone por 31 registros básicos los cuales son los que almacenan datos:

1648134424505.png


cada uno va acompañado por "opcodes" que son las instrucciones que seguirán, y ahora veremos los mas usados o básicos.

Gestor de direcciones

LI, LUI (Load Immediate) Se utiliza para almacenar valores de 32 bits y generalmente aquí se utiliza para cargar las direcciones de la RAM.

Los que pasan datos de la memoria a los registros

LW (Load Word) Se utiliza para almacenar valores de 32 bits de la memoria.
LH, LHU (Load Half) Se utiliza para almacenar valores de 16 bits de la memoria.
LB, LBU (Load Byte) Se utiliza para almacenar valores de 8 bits de la memoria.

Los que pasan datos de los registros a la memoria

SW(Store Word) Se utiliza para almacenar valores de 32 bits en la memoria.
SH(Store Half) Se utiliza para almacenar valores de 16 bits en la memoria.
SB (Store Byte) Se utiliza para almacenar valores de 8 bits en la memoria.

Los operacionales

ADDI, ADDIU, ADDU(Add inmmediate) Se utiliza para almacenar valores de 16 bits o hacer una operación de suma o agregación.
SUB, SUBU(Substract) Se utiliza para restar los valores de los registros.
MULT, MULTU,(Multiply) Se utiliza para multiplicar los valores de los registros y almacena el resultado en LO y residuo en HI.
DIV, DIVU (Divide) Se utiliza para dividir los valores de los registros y almacena el resultado en LO y residuo en HI.
MFHI(Move From Hi) Se utiliza para pasar el residuo de una multiplicación y división del registro HI.
MFLO(Move From LO) Se utiliza para pasar el resultado de una multiplicación y división del registro LO.

Los de condición
B, BNEZ, BNE, BEQ, BEQZ (Branches) Estos son utilizados para generar condiciones.
SLT, SLTI, SLTU (Set On Less Than) Se utiliza para comparar 2 registros y devolver true (01) o false (00).

Los de salto y retorno
J, JAL, JR (Jumps)
Se utilizan para saltar a funciones especificas o inyectar código externo( hooks) y retornar a funciones de rutina.

Lógicos
OR, ORI(Or Immediate) Se utiliza para almacenar valores de 16 bits o hacer una operación OR.
AND, ANDI (And Immediate) Se utiliza para hacer una operación AND.

Bitwise
SLL( shift left logical) Hace una operación bitwise a la izquierda o básicamente potenciar por 2 las veces que se establezca.
SRL ( shift right logical) Hace una operación bitwise a la derecha o básicamente la raiz por 2 las veces que se establezca.

Estos son los opcodes básicos que se utilizan mayormente para agregar código a la rom.
Ahora vamos a ver algunas pequeñas diferencias de como son usados algunos registros específicos en funciones ya establecidas por un compiler.

AT: Este registro es usado como condición.

A0: Este registro es usado generalmente como argumento 1 de una función.
-Puede llevar direcciones RAM o direcciones ROM.

A1: Este registro es usado generalmente como argumento 2 de una función.
-Puede llevar direcciones ROM .

A2: Este registro es usado generalmente como argumento 3 de una función.
-Puede llevar alguna propiedad o parámetro.

A3: Este registro es usado generalmente como argumento 4 de una función.
-Puede llevar alguna propiedad o parámetro secundario.

SP: Este registro es usado como stack para almacenar temporalmente datos en una pila para luego ser restaurados luego de una función.

RA: Este registro es usado como retorno de una función, se utiliza para continuar o volver a su rutina normal.

Y bien esos han sido algunas diferencias de como se usan ciertos registros, y es muy útil ya que ayudan a saber que esta haciendo cada uno.

Nosotros como no somos compilers podemos utilizar todos los registros para cualquier cosa pero primero tenemos que almacenar datos en la memoria que vayan a ocupar de dichos registros.

Bueno esto será todo por ahora, espero se entienda y cualquier cosa pueden preguntarme si tienen dudas y a veces me paso por twitch: seohaine haciendo streams de romhacking así que también por ahí , hasta la próxima
En la otra lección veremos todo sobre floating points.
 
Última edición:
Arriba