[TUTORIAL] Crear tu primer emulador. Parte 1. Informandose

Antes que nada, recomiendo que si nunca has programado para la NDS o PC (graficos) no empiezes con esto, mejor haz pruebas con los modos de pantalla que tenga la NDS (toca tiles, bitmap, etc.).


Bien, empezemos:
Para empezar a programar un emulador, primero tendremos que elegir qué sistema queremos emular. En este tutorial lo haremos como si quisieramos emular Chip8, un sistema muy simple que todos recomiendan para empezar.

¿Como funciona un emulador?
Lo que basicamente es emular una consola (estos son los que nos interesan). Pero que exactamente hace para emularlo?
Hablando de un emulador sencillo de un sistema sencillo, lo que necesitaremos para hacer un emulador sera:
-Informacion de la CPU: docs (documentos), ... informacion basicamente
-Preparar registros necsarios para poder ejecutar las instrucciones (PC, SP, v0-v15...)
-Preparar contador de ciclos para que no vaya demasiado deprisa/despacio.
-Ejecutar las instrucciones de la ROM.
-Renderizar graficos.

Informacion de la CPU
Para saber que debemos emular de Chip8, necesitaremos saber que ensamblador utiliza, registros, velocidad, ... vamos, todo o "casi todo".
Tratandose de un tutorial, os facilito las paginas donde tendreis que ir:
-Docs: http://www.pdc.kth.se/~lfo/chip8/CHIP8.htm Leeros un poco esto antes de empezar
-Emuladores: http://www.zophar.net/chip8.html (Como supongo que no teneis un Chip8, tendreis que utilizar un emulador para comprobar que todo va correcto).
-Roms (son PD/homebrew !): http://www.zophar.net/pdroms/chip8/chip-8-games-pack.html

Ententiendo los Docs:
En el apartado 1.2 veremos "CHIP8 programs and memory". Nos dice, basicamente, que esta estructurada de la sigueinte forma:
-0x000-0x1FF: Sector de Memoria del Intérprete (cosas en memoria de la consola, que no han de tocarse. En chip8 contiene los graficos de los valores 0x0 al 0xF, para mostrar la puntuación en pantalla, etc.)
-0x200: Donde empiezan las instrucciones de la ROM
-0xFFF: Fin de la memoria, suponiendo que la rom ocupa ~4KB.

1.3: registros
Si no habeis programado en ensamblador antes, hacedlo ahora o olvidaos de seguir con esto [carcajad]. (Para los que no sepan, lo iré explicando un poco)
Los registros son como las variables en C/C++/java/loquesea, pero claro: solo hay 16, y no todas las podemos utilizar. (Los compiladores en realidad traducen todo lo escrito i se las manejan para poder usar esas 16 variables solamente).

-Los registros son de 8 bits, habiendo 16 de ellos. Llamados V0-VF.
El registro VF se utiliza especialmente para el Carry i Detector de Colisiones (MUY simple, si dibuja un pixel blanco encima de otro, se pone VF a 1, tambien se pone a 1 si hay Carry en una operacion).

Si no sabeis que es un Carry:
Al sumar 2 numeros en cualquier base, normalmente decimos "a+b = tal, y me llevo 1". Pues ese "1" es el carry. Habrá carry en una operacion si sumas/restas 2 numeros y se sale del rango, por ejemplo:
(4bits) 1111 + 0001 = 0000 , C = 1
(4bits) 1011 + 0001 = 1100 , C = 0
(4bits) 1111 + 1111 = 1110 , C = 1


-El registro de direccion: Hay uno, y se le llama I. Sirve para aseñalar una dirección de la memoria. Lo utilizamos ya que para acceder a cualquier punto de memoria se necesitan 16 bits y con los 8bits de los registros no se podria.
Ejemplo:
I = 0x200 (I apunta al inicio de la ROM)
V0 = 0xFF (un numero cualquiera, no puede ser 0x1FF o 0x2FF ya que superaria los 8 bits permitidos)
-Los temporizadores:
-DT (Delay Timer): Mientras tenga un valor mas grande que 0, se decrementará hasta llegar a 0. No continuará ejecutandose ninguna instruccion de la ROM mientras este temporizador no termine. (Decrementa por 1 unas 60 veces por segundo)
-ST (Sound Timer): Mientras tenga un valor mas grande que 0, sonará un "beep". (Decrementa por 1 unas 60 veces por segundo)

-The stack: Sirve para llamar a subrutinas (como si llamaras a una funcion, para que sepa a que parte de la ROM ha de volver al acabar).
por ejemplo:
022E: LD V0, 0x05;
0230: CALL 0x250;    //al ejecutar esta instruccion, se añade un valor a la lista de SP con el valor 0x230. Y continua ejecutando con PC = 250
...
0250: ADD V0, V0, 0x01;
0252: RET;     //PC = ultimo valor en la lista de SP



Nota: Si no sabeis lo que es PC:
PC: Program Counter. Es la variable que utiliza la maquina para acordarse de donde ha de leer el siguiente ciclo (la siguiente instruccion que ha de leer). Se incrementa por 2 automaticamente cada vez que se ejecuta una instruccion, a no ser que se le diga lo contrario (Por ejemplo la instruccion CALL anterior, ponia PC = 0x250 (aparte de tocar los SP)).


Graficos:
Como por ahora no lo utilizaremos, pasamos de ello (leeroslo vosotros! xD)

Instrucciones:
La lista de instrucciones y su correspondiente OPCODE.
OPCODE: OPeration CODE (Codigo de Operacion).
Lo veremos mejor con un ejemplo, observemos este:
8XY2 VX = VX AND VY
Esto nos indica que, despues de leer nuestro opcode de la ROM, si el valor tiene la forma 8XY2 (siendo X i Y un número cualquiera), significa que tendrá que realizar la operacion "Vx = Vx AND Vy".

Ejemplo de codigo, para que os hagais una idea de un emulador de Chip8 que entiende la isntruccion 8xy2:
//(Todas las variables de registros, etc.. ya estan declaradas)
int opcode = 0x8375
int B0 = opcode%16;   //B0 = 5
...
int B4 = opcode%16;   //B4 = 8

if (B4 == 8 and B0 == 5) V[B1] = V[B1] AND V[B2];


Acabad de miraros los documentos y a buscar un poco mas de informacion si no habeis entendido algo, porque esto es lo BASICO (no se ni si llega a eso)


Por ahora aqui acaba la primera parte, en unos dias escribiré la 2a y empezaremos de verdad a ejecutar las instrucciones.
Vaya muchas gracias, veo que te has dado prisa en postearlo ;).

No tengo tiempo ahora mismo para leer la información de la CPU, pero mañana mismo me pondré para seguir este tuto, a ver si asi pillo unas nociones sobre este tema que siempre me ha interesado.

PD: Una pregunta sobre esta linea:
if (B4 == 8 and B0 == 5) V[B1] = V[B1] AND V[B2];

Dando por hecho que V es un vector, ¿es de tipo booleano por eso de que haces un AND, o podría hacerse con otro tipo de datos?.

Gracias de nuevo! Salu2!
Alber_h escribió:PD: Una pregunta sobre esta linea:
if (B4 == 8 and B0 == 5) V[B1] = V[B1] AND V[B2];

Dando por hecho que V es un vector, ¿es de tipo booleano por eso de que haces un AND, o podría hacerse con otro tipo de datos?.

Gracias de nuevo! Salu2!


Era solo un ejemplo, en la parte 2 entraré mas al tema :P

pero bueno, La declaración del vector V es esta:
u8 V[16]; //u8 porque son registros de 8 bits, 16 posiciones porque hay 16 registros


Y sobre lo de AND, no es una operación booleana, sino Lógica..!
Ahora que lo dices, no se si se podia poner asi, pero así seguro que esta bien:
if (B4 == 8 and B0 == 5) V[B1] = V[B1] & V[B2];


Nota rapida:
Operaciones Logicas: & (AND), | (OR), ~ (NOT)
Operaciones Booleanas: && (and), || (or), ! (not)
ETkoala escribió:
Alber_h escribió:PD: Una pregunta sobre esta linea:
if (B4 == 8 and B0 == 5) V[B1] = V[B1] AND V[B2];

Dando por hecho que V es un vector, ¿es de tipo booleano por eso de que haces un AND, o podría hacerse con otro tipo de datos?.

Gracias de nuevo! Salu2!


Era solo un ejemplo, en la parte 2 entraré mas al tema :P

pero bueno, La declaración del vector V es esta:
u8 V[16]; //u8 porque son registros de 8 bits, 16 posiciones porque hay 16 registros


Y sobre lo de AND, no es una operación booleana, sino Lógica..!
Ahora que lo dices, no se si se podia poner asi, pero así seguro que esta bien:
if (B4 == 8 and B0 == 5) V[B1] = V[B1] & V[B2];


Nota rapida:
Operaciones Logicas: & (AND), | (OR), ~ (NOT)
Operaciones Booleanas: && (and), || (or), ! (not)


Pues me apunto las operaciones logicas ya que no las habia usado nunca en programación. Lo que no tengo del todo claro es el tipo de resultado, ya que en la booleana o da 0 (falso) o da 1 (verdadero), pero en las logicas que seria? o 0 o cualquier otro valor?

Recuerdo bastante de logica, tanto de filosofia como de tecnología, pero en este aspecto no lo he tocado nunca y cuanto mas aprenda, mejor ^^.

Salu2!
Tontokienlolea está baneado por "Faltas de respeto"
Pues yo no entiendo nada ¬¬

Estudiando esto puedo hacer un emulador de PS2 pa' la wii? ¬_¬ XD XD XD
Gracias por el tuto!
PD: No...
ya veo que no le interesa demasiado a la gente, no espereis proximos capitulos


(recuerdo gente pidiendome este tutorial en ostros posts...)
ETkoala escribió:ya veo que no le interesa demasiado a la gente, no espereis proximos capitulos


(recuerdo gente pidiendome este tutorial en ostros posts...)


Eyyy eso no es verdad.. a mi me interesa un monton .. la pena es la falta de tiempo para poder hacer mis hobbies :(

En serio, a mi me parece impresionante a la par del PRIMER tuto que veo para hacer un emu ^^ yo quería hacer uno y aquí lo tengo .. asique por favor, pido perdón por la falta de "entusiasmo", pero piensa en que hay gente que no responde pero que si lo sigue ^^

salu2!
Se agradece el tutorial

Saludos
Me ha gustado.

Ahora una duda.

Supongo que para emular la maquina, habra que crear una funcion donde esten todos los opcodes de la maquina a operar (supongo que esta maquina es tan simple que solo tiene un microprocesador, ram y rom), de forma que se lee la rom y se empiezan a ejecutar las instrucciones que estan en la funcion, y dentro se hacen las operaciones, pero en el codigo de nuestra maquina)

Y todo esto teninendo por ahi todos los registros y actualizandolos de forma correcta, y sin contar con la salida de sonido ni de graficos :P

Saludos
Haz más...
...mis hilos tampoco los ha seguido mucha gente, pero , gracias a ellos, tenemos la traducción del LA y alguna más...
Genial hilo de introducción, muy currado. Al bookmark
11 respuestas