English " /> English " />

pspemu (II)

21 Jan 2010

English

I have continuing coding the emulator. It is true that the previous version was already emulating homebrew, and the interface was pretty cool. But the total absence of testing from the beginning, made that version to totally fail.


Why?

Emulation was buggy. Bugs that were not happening for a known reason, and that happened executing way too large program. In addition, I was executing hem using the debugger included in the emulator. Yeah, it was pretty, but debugging step by step something that you don’t know what it is, it was super anti-productive.

Each small problem required to invest a lot of time. By them I had a lot of time, but still I was a single person.

The additional problem was that even if I located the problem, nothing prevented from that bug reappearing againin the future after a refactoring, even if I was testing each time I made changes.

I remember that a lot of times after changing something, I tried a couple of homebrews and I though that that was not negatively affecting. But later, I was aware that it caused a problem after tried another ones, and I had to review all the changes between revisions that I “thought” was causing the problem.

And this is not going to happen again even if I’m a single person, at least not that much.

Why?

Because I’m coding using TDD. From the very beginning.

And I’m not going to make a single step without preparing and thinking about the testing first, without implementing it first and without improving it little by little.

This will allow me to not design anything without having testing in mind. The first version had nothing about testing in mind, and doing it at this point was virtually impossible.

This approach allows me to detect regressions instantly. It has happened already to me that after doing even a small change that I thought that it couldn’t affect at all, and the unittesting noticing me that I missunderstood something or that the design was not good.

I think I commented this already, but the most complex testing I had to do was the CPU testing. It was a huge win to create an assembly module. Testing must be clear and mainteinable, and this is allowing me to do just that.

Theoretical Roadmap:

Even if i t is hard to know how will it evolve, and probably I will change this slightly over the time; have an initial vision of how it should be done is something possitive.

I have already most of the integral instructions of the MIPS R4000 (in addition to some from Allegrex) implemented and even if not everything is unittested, mostly of it is. And I will work into completing it further.

Next steps would be to create a disassembler and improve the assembler as much as possible.

Once both things are ready, I will do the same with the GPU. I will decide how to implement it later, but I bet I will have to mock somehow the opengl calls. Maybe using D’s alias to not hit the performance. I will also do offscreen performance tests for the testing. Rendering into an invisible screen and later checking the pixels of the output; partially or completely. The idea is to design the GPU so it is possible to see a whole GPU frame and to identify on screen the different textures and rasterizations. Similar to what no$gba does.

From the HLE, I implemented a couple of file containers: PBP and PSF. I will implement the ELF model and I will create a simple loader later. After that I will possible create a real test outputing to a simple window.

Technically speaking I bet I will end using DSSS to compile and DWT as windowing framework (it also compiles to linux).

Once everything is clear, I will start to implement threading, and system libraries. In the same time I will probably make a graphic debugger as I initially did, but improving everything with a few things I have in mind. The register highlighting JPSPS did was something great, for example. The possibility of highlight some keys like IDA or Notepad++ do is also something I would want to do. And to see the GPU state is something I consider highly important too. I supporse I will use shaders to implement all the graphic part. And I think I will try OpenCL and Cuda too.

Spanish

He seguido avanzando con el emulador. La verdad es que la otra vez a las alturas de emulación de la cpu que llevo, el emulador ya estaba ejecutando homebrew, y tenía una interfaz bien bonita. Sin embargo, la ausencia completa de una concepción inicial de testeo, hizo que la primera versión fracasara estrepitosamente.

¿Por qué?

La emulación tenía bugs. Bugs que no estaban del todo claro por qué pasaba, y que localizaba ejecutando programas demasiado largos. Además los ejecutaba con el debugger que traía el emulador. Que sí, que era muy bonito, pero ir paso a paso depurando algo que no sabes lo que es, es de lejos muy improductivo.Cada pequeño problema suponía dedicar un montón de tiempo. Por aquel entonces tenía mucho más tiempo, pero seguía siendo una única persona.El problema adicional era que aunque localizase el problema, nada impedía que en un futuro, reestructurando código, se volviese a producir. Porque iba probando de vez en cuando conforme hacía cambios.Recuerdo que muchas veces cambiaba algo, probaba un par de homebrews y pensaba que no habían afectado negativamente. Luego, más tarde, me daba cuenta que sí cuando probaba otros y me tocaba revisar todos los cambios que había hecho entre las revisiones que “creía” que habían causado el problema.

Esto ya no va a volver a pasar pese a seguir siendo una persona, al menos no tan pronunciadamente.

¿Por qué?

Porque estoy haciendo TDD.Desde el principio. Y no voy a dar ningún paso más sin preparar y pensar seriamente el testing, sin implementarlo inicialmente y sin ir mejorándolo poco a poco.Esto me permitirá no diseñar nada sin el testing en mente. La primera versión no tenía testing en mente, y hacerlo a esas alturas era prácticamente imposible.Me está permitiendo detectar regresiones al instante. Me ha pasado ya varias veces de hacer un cambio incluso pequeño pensando en que no iba a afectar para mal, y el unittesting avisarme de que había malinterpretado algo o de que algo había fallado en la concepción.

Creo que ya lo comenté, pero ahora mismo el testing más difícil conceptualmente era la prueba de la cpu.Fue un enorme acierto la creación de un módulo de ensamblado.El testing debe ser claro y ser mantenible, y esto me lo está permitiendo.

Roadmapa teórico:

Aunque es difícil saber cómo evolucionará el asunto y es fácil que acabe cambiando los pasos a seguir ligeramente; tener una visión inicial es algo positivo.

Ya tengo casi todas las instrucciones de enteros del mips R4000 (más algunas extensiones de allegrex) implementadas y aunque reconozco que no con todo el unittesting, sí con bastante. Y ahora trabajaré en completarlo antes de seguir.

Los siguientes pasos serán crear un desensamblador y mejorar todo lo posible el ensamblador.

Cuando estas dos cosas estén hechas, haré lo mismo con la GPU. Veré cómo lo implemento, pero creo que ahí ya me tocará “mockear” de alguna forma las llamadas a opengl. Quizá con “alias” de D por rendimiento.También haré pruebas de renderizado offscreen para el testing. Renderizar en una pantalla invisible y luego comprobar los píxeles de la salida; parcial o totalmente.La idea es diseñar la GPU de forma que sea posible ver un frame de GPU e identificar en pantalla las diferentes texturas y rasterizados. Muy a lo no$gba.

De HLE implementé ya un par de contenedores de archivos. PBP y PSF.Posiblemente implemente el modelo de ELF y cree un loader sencillo.Ahí posiblemente ya haga alguna prueba real con una pantalla simple.

A nivel técnico imagino que acabaré usando DSSS para compilar y DWT como gestor de ventanas (que también es compatible con linux).

Cuando tenga todo claro, me pondré con implementación de threading y librerías de sistema.A la par posiblemente haga ya un debugger gráfico como el que hice inicialmente. Pero mejorando todo con algunas ideas que tengo en mente. El resaltado de registros del jpscp es un gran acierto por ejemplo. La posibilidad de resaltar ciertas claves a lo IDA o a lo notepad++ también. Y ver el estado de la GPU es algo que considero altamente importante también.Imagino que usaré shaders para implementar toda la parte gráfica. Y quizá pruebe también opencl o cuda.