domingo, 26 de febrero de 2023

Grabando video en un diskette. Evolución de los formatos de video (AV1 y H266)

 ¿Quien no se acuerda de los diskettes? 

Por allá en los 90, era el dispositivo de almacenamiento por excelencia para compartir archivos, en una época donde los grabadores de CD eran caros, e Internet era lento (56kbps a traves del modem) y poco accesible.
Pues lo habitual era usarlo para compartir documentos de Word, Excel, pequeños juegos de PC, imágenes de baja resolución... Esto es debido a su limitado almacenamiento de apenas 1.38 MB.

Los más pros, a finales de los 90, consiguieron hacer algo inimaginable años atrás con el diskette: almacenar canciones enteras de casi 3 minutos gracias al revolucionario formato de audio MP3, eso sí, a 64kbps, lo cual es una calidad de audio pésima. Con una calidad aceptable de 128kbps se podía grabar 1 minuto y medio aproximadamente, que tampoco estaba mal.

Pues bien, ¿y que pasa con el vídeo? Cualquiera que le hubieses pedido grabar un vídeo en un diskette por entonces se habría reído de ti, y con razón. Y es que el formato de vídeo revolucionario por entonces, el MPEG, permitía grabar vídeo a 240p 1374 kbit/s. Esto significaría un vídeo de máximo 8 segundos con una calidad pésima.

A día de hoy, es claramente sabido que en una microSD del tamaño de una uña nos cabe lo equivalente a miles de diskettes, pero no solo han mejorado los dispositivos de almacenamiento en estos años, la codificación de vídeo también, así que... ¿Sería factible grabar vídeo en un diskette en 2023?

Repasemos la evolución de los códec de vídeo más populares:

* MPEG1 (VCD) - 1993
* MPEG2 (DVD) - 1995

* MPEG4 (DIVX) - 1999
* H264 (AVC) - 2004

* VP9 (Google) - 2012
* H265 (HEVC) - 2013

* AV1 (AOMedia) - 2018
* H266 (VVC) - 2020

Los he ordenado cronológicamente por orden de aparición, y los he separado por categorías, ahora os explicaré por qué:

* MPEG1 fue un formato revolucionario mucho mas eficiente que los previamente existentes como Cinepak, que permitió por primera vez grabar películas en un CD. Más tarde, con la aparición del medio físico DVD, apareció una variación llamada MPEG2 cuya única diferencia es que permitía un mayor ancho de banda, alcanzando con él los 480p.

* Mas tarde, y bajo el nombre de MPEG4, empezaron a mejorar el algoritmo. DivX fue el nombre con el que conocimos por primera vez esta compresión más eficiente. Siguieron mejorándolo, creando MPEG4 parte 2, o H263 para los amigos, compresión que permitió grabar vídeo en el móvil de forma eficiente por primera vez (formato .3GP). MPEG4 parte 10, o H264, no necesita presentación y es que desde su aparición ha sido el códec de vídeo por excelencia en el BluRay, televisión digital, streaming, cámaras de video y móvil,... En todo.

* Unos años después, no solo mejoraron aun más el H264 creando H265, sino que Google también se animó a crear un nuevo códec de vídeo VP9 (Sucesor de VP8), que usaría para los vídeos de su plataforma YouTube, ambos con una eficiencia similar, y mejor que H264, aunque no lo reemplazarían del todo debido a la alta popularidad que tuvo H264, y a que H264 se podía decodificar por hardware por esos años. El hecho de que el hardware capaz de decodificar H265 tardó en aparecer, hizo que su implantación en dispositivos fuese lenta y la gente siguiera utilizando H264.

* Finalmente, y recientemente han aparecido dos nuevos códecs de vídeo con una eficiencia aun mejor, AV1 de AOMedia, y H266. A día de hoy, AV1 esta despegando bastante bien, gracias a su enorme eficiencia, y es soportado por FFMPEG, VLC, navegadores web,... Mientras tanto, H266, a febrero de 2023, sigue siendo tan novedoso que aun no es compatible ni con FFMPEG, ni con VLC, ni practicamente con nada. Ambos desde mi punto de vista proporcionan una compresión de eficiencia similar.

A continuación tenéis una pequeña comparativa que he hecho de estos últimos códecs, tras codificar 1s de vídeo 540p a distintos tamaños. (PD: Quien adivine que película es, tiene premio)




Bueno, pues... ¿que resultados obtendríamos codificando AV1 en un diskette?

Para el audio usaré HE-AAC con audio mono, manteniendo los 44100 Hz eso sí.
HE-AAC es actualmente el mejor códec de audio existente para bajos bitrates, mucho mejor incluso que OPUS, que ya es decir. Usaré el mínimo bitrate que permite codificar HE-AAC con esta configuración, que es 16 Kbps y que sorprendentemente suena bastante mejor que los 64 kbps en MP3 de la época.

Mi plan es codificar un vídeo musical entero, a 480p (DVD) en vez de 240p (VCD). En busca de ideas para el vídeo, encontré que por alguna bizarra razón el clásico Crazy Frog - Axel F está disponible en YouTube en 4k, lo cual garantiza el máximo de calidad al re-escalar a 480p, ademas de ser un clásico de los 2000's.

Tras codificar el vídeo en AV1, lamentablemente solo me entró 1 minuto en el diskette, aunque pensándolo bien... ¡¡Es 1 minuto de vídeo a 480p en un p*** diskette!! Totalmente inimaginable en los 2000's.


Ya solo por curiosidad, quise comprobar cual es la máxima duración que podría caber en el diskette bajando la resolución a 144p, y usando la mínima calidad de imagen permitida por el encoder, ademas de bajar el audio a 32000 Hz y 12 Kbps. Tras encontrar un vídeo musical que duraba 5 minutos, lo codifiqué en AV1... ¡Y entró entero! No solo eso, sino que incluso sobraron 60 Kb en el diskette. El resultado es la siguiente aberración.


Sí, la calidad de imagen es horrible, aunque si nos paramos a pensar es parecida a la de algunos vídeos web existentes a finales de los 90's, sí, de esos que se reproducían con el Real Player.


jueves, 2 de febrero de 2023

Creando un computador mecánico programable de un reloj digital (sin electrónica)

 ¡Feliz 2023 frikazos!

Lo primero de todo, quería disculparme por adelantado por este post, ya que es una 💩 pero algo había que escribir en el blog para que no vaya cogiendo polvo.

Como sabéis, los primeros computadores de la historia no usaban electricidad, eran puramente mecanicos. Ej: La maquina "Bombe" para descifrar Enigma creada por Alan Turing, de la cual no hay mucho más que explicar ya que hay una peli y to' 



Pues bien, una tarde de aburrimiento me puse a pensar si habría una forma simple de crear un computador mecánico programable, con la suficiente "potencia" para implementar un reloj digital, de forma que hubiesen salidas mecanicas que se conectasen a cada uno de los segmentos de una pantalla de 7 segmentos. Lo que vendría siendo algo así:


Tras investigar posibles opciones, encontré una bastante interesante. Resulta que en los años 60 apareció un "juguete educativo" que era un computador mecánico totalmente programable (se nota que antes de que apareciese TikTok los niños eran más listos) llamado DigiComp I:



Esta maquina era capaz de implementar programas como un contador binario, o el juego del Nim, entre otros. Aquí podéis verla en funcionamiento con el programa del contador binario:




Como veis, es muy sencilla, y se puede replicar fácilmente con impresión 3D, gomitas, y alambre, como se muestra en esta web. También podéis probar su funcionamiento en este simulador online. Su único inconveniente... es que solo tiene 3 tristes bits :') Con eso sinceramente no se puede hacer una 💩.
Pero si nos fijamos bien, ¿Que limita la maquina a tener únicamente 3 bits, 3 condiciones de set, y 3 condiciones de reset? ¡Simplemente quisieron hacerla así de simple! Nada nos impide construir una versión que tenga 32 bits, por ejemplo, siguiendo exactamente la misma mecánica.
Y ahí es donde entro yo, empezando por crearme otro simulador, que en este caso permita escalar la maquinita. En esta ocasión elegí Excel, para variar un poco. Aquí podéis ver mi simulador con el tamaño del DigiComp I original:


Y ahora, simulando que conectamos las salidas a una pantalla de 7 segmentos, así se vería la implementación de un contador del 0 al 9:


Como podéis apreciar, la maquinita ha crecido un poco...
Originalmente tenia pensado crear un contador binario de toda la vida que al llegar a 9 regrese a 0, y de forma paralela, implementar lógica para convertir ese numero binario a los bits del 7 segmentos. Peeero, como podéis imaginar, aunque en DigiComp sería posible, aumentaría más su tamaño que si simplemente verificamos el valor anterior del 7 segmentos para calcular el próximo.

La implementación final, para un reloj de 24h sería la siguiente monstruosidad:


¡Seguro que funcionaría! Pero ahora a ver quien tiene huevos de fabricarlo.

FAQs:

P: ¿Donde puedo descargar el Excel con tu simulador?
R: Si a alguien le interesa descargar el proyecto, que me deje un comentario abajo y os dejo un enlace.

P: ¿Como se ajustaría la hora?
R: Literalmente se haría moviendo manualmente los segmentos con la mano, de forma que muestren la hora actual. Sí, sorprendentemente funcionaría haciendo eso.

P: ¿Que pasa cuando llega a las 23:59?
R: El siguiente valor será 00:00, ¿O que pensabas? No soy tan mal programador.

P: Yo quiero construir tu maquinita de la hora
R: ¡Buena suerte!

P: Te sobran "x", se podría optimizar.
R: No le he dado importancia a minimizar el numero de "tubitos", que son los que se usan para programar, ya que son piezas muy simples, e igualmente este proyecto es una 💩. Si que he intentado minimizar un poco el numero de bits, y el numero de condiciones de set y reset (columnas), que son los que harían crecer la maquinita.

P: ¿Que más opciones te planteaste para tu reloj digital, aparte de DigiComp?
R: Literalmente empecé a idear un computador mecánico capaz de ejecutar programas en Brainf*ck, y una version simplificada con direccionamiento de 1 bit que reemplazaría las instrucciones + y - (incrementar / decrementar) por 1 y 0 (setear bit a 1/0), pero sería demasiado lento, y una pesadilla de programar.

P: Sí, sí, muy bonito pero... ¿Puede correr Doom?
R: ¡Claro que sí nene! En un mundo paralelo

miércoles, 13 de abril de 2022

Invocando la API de Instagram: Como reaccionar con emojis customizados

Tal vez algunos recordareis cuando invocaba manualmente la API de Badoo hace unos cuantos años para realizar acciones que no estaban permitidas desde el frontend, como poner intervalos de edades no permitidos, descripciones extra-largas...

Pues en esta ocasión vamos a intentar hacer algo parecido con Instagram. Como sabréis, las reacciones a las historias que permite el frontend de Instagram son solo 8. Pero... ¿Y si os digo que podéis usar cualquier emoji, como mis famosas estrellitas? 
Para esto vamos a analizar la llamada a la API que realiza la versión web de Instagram cuando reaccionas a una historia:
Como veis, la llamada a la API tiene un último parametro "reaction_emoji" que puede setearse a cualquier cadena de texto de longitud 1 con un único emoji, a traves del debugger, por ejemplo.

Ocurre exactamente lo mismo con las reacciones a comentarios:
En este caso, lo más probable es que a traves del frontend solo podais reaccionar con el emoji del corazon ❤️. Este emoji por defecto aparece cuando en la llamada a la API el último parámetro para el emoji es una cadena vacía, nulo, o indefinido (el código esta ligeramente obfuscado). En esta ocasion, ademas he podido comprobar que la longitud de la cadena del emoji ¡puede setearse mayor que 1! este texto puede incluir varios emojis, espacios, y saltos de linea (no permite caracteres alfanumericos) aunque al usar varios caracteres, la reacion al comentario es posible que no se muestre correctamente.

Para terminar, si os ha gustado este post, os pongo unos links a videos de YouTube donde otros jaquers se aprovechan de vulnerabilidades ya parcheadas de la API para hacer otras cosas, como hacer crashear la app al abrir una historia:

https://www.youtube.com/watch?v=4jCetFetFQA




sábado, 26 de marzo de 2022

Buffer overflow en Los SIMS 2 (Nintendo DS)

El juego de Los SIMS 2 para Nintendo DS tiene un bug en uno de sus minijuegos que hace que el tamaño del bolsillo de objetos se haga negativo, o exceda el máximo de 6 objetos. Hasta el día de hoy despues de 15 años, ese bug era únicamente conocido por corromper partidas guardadas, haciendo crashear el juego, y la recomendación era no jugarlo.

Pero en mi caso, tras descubrir de la existencia de ese bug, pensé... Es un buffer-overflow, tal vez pueda usarlo a mi favor si lo investigo. ¿De verdad nadie lo había intentado antes? No estamos hablando de un juego homebrew del tío Paco jugado por 20 personas, estamos hablando de una leyenda como son los SIMS.

Pues resulta que explotando el bug correctamente, podemos escribir en las direcciones de memoria del juego que queramos (dentro de unos limites), o introducir los objetos con el identificador que queramos dentro del bolsillo, incluyendo objetos nunca antes vistos. Para no aburriros, lo he resumido en 2 vídeos, para que veáis que me lo he currao'


jueves, 3 de febrero de 2022

Practicando con Excel: Estadisticas COVID y juegos cutres

Pues hacía bastantes años que no usaba Excel para nada. De hecho creo que no lo usaba desde antes de la universidad, así que ya iba siendo hora de repasar un poco, ya que a fin de cuentas es una herramienta muy útil para administrar información, cálculos, y tal.

Lógicamente empecé repasando los estilos de celdas, luego pasé a las funciones (Que es la parte más interesante de el programa), luego estuve viendo como se podían obtener datos externos, las tablas dinámicas, y finalmente los macros en Visual Basic.

En resumen, que en una semana he pasado de ser un inculto del Excel a un semi-experto XD

Y bueno, y os preguntareis, ¿a que viene este post? Pues quería compartiros 5 de los proyectos que hice en Excel esta semana para practicar ya que creo que os podrían interesar. Los ordeno de mas simples a más complejos para que no perdáis la emosion al leer hasta el último momento:

1. Estadisticas del COVID en tiempo real (Descarga)

Tal cual, este archivo Excel (sin macros) tiene un origen externo de datos a un CSV de datos oficiales del COVID que se actualiza periódicamente en la URL https://cnecovid.isciii.es/covid19/resources/casos_tecnica_provincia.csv que Excel descarga al abrir el documento.

Como veis genera tabla y gráficos donde muestra el incremento de casos de COVID diarios, y el total acumulado en el periodo y provincia(s) que nosotros queramos filtrar




2. Juegos cutres
 (Descarga)

Los macros de Visual Basic ofrecen infinitas posibilidades para hacer y automatizar montones de cosas de forma programática en nuestros documentos. Quien se iba a imaginar para lo que las iba a usar yo..

2.1. SameGame

SameGame es un juego clásico de Linux, y Windows Mobile entre otras plataformas que algunos ya recordaremos. Es muy adictivo, así que gracias a esta versión podréis pasar horas en Excel intentando batir récords, y en el caso de que trabajes con Excel, tu jefe al verte pasar tanto tiempo con la aplicación de hoja de calculo te nombrara automáticamente empleado del mes!


Como podéis ver, tiene celdas para el ancho, alto, y número de colores que podéis cambiar a vuestro gusto y el tablero se adaptará automáticamente. Nota: Si termináis la partida sin pelotitas, ingresareis 1000 puntos extra.

2.2. Juego sin nombre 1

Bueno, pues el siguiente juego es una tontería, aunque pondrá a prueba tus reflejos. Se trata de que dentro de un área aparecerán bolitas de colores aleatorios cada vez que hagas click en la última que apareció, y tienes que estar pendiente de cual es la última que aparece, porque si haces click en la equivocada: Game Over.


2.3. Juego sin nombre 2

Pues este esta basado en un juego que tenía en un "Brick game", o sea, un Tetris baratos de esos. No tengo ni idea de si tendrá nombre. Tienes un área cuadriculada en la que cada vez que haces click en un cuadrito, se hará bit flip / xor / cambiaráDeBlancoANegroOViceversa en ese cuadrito y los adyacentes en el caso de que estos existan (si no haces click en un borde). El objetivo es, empezando con el área totalmente en negro, dejarla completamente blanca. Es más difícil de lo que parece, os hará pensar.




3. Excel retro-Music Player (Descarga)

Si crear juegos en Excel os pareció friki, mejor no veáis esto...



4. Reversi multijugador On-line (Descarga)

Y para ir terminando, si os parecieron frikis los juegos en Excel, este ya se lleva un premio... Se trata de una versión del Reversi que podéis jugar a través de internet en tiempo real con quien queráis compartiendo un "identificador de mesa".


Para compartir los movimientos en tiempo real de los jugadores, se conecta a la API de https://myjson.dit.upm.es/ la cual sin duda os recomiendo para vuestros experimentos y proyectos.


5. Bad Apple!! (Descarga)

Creo que sobran las explicaciones...


Y eso fue todo. ¿Cual es vuestro favorito?

domingo, 30 de enero de 2022

Aprender a hackear con Juan: 2 canciones en una (Audio oculto)

 ¡Feliz año nuevo 2021 y 2022 folouers!

A quien no le ha pasado (ironía) que de repente escucha una canción tan clásica como el Nothing Else Matters de Metallica en el altavoz mono de su movil, o en un ya obsoleto CD de audio (grabado por un mal amigo) y va a conectar los auriculares para escucharla mejor y... pum! toma pokazo del bueno!

Descarga aquí el MP3 trucado

Esto te podría ocurrir no solo en un moderno smartphone o reproductor de MP3 (tan fáciles de hackear) sino también en un reproductor de CDs de hace 30 años.

¿Que clase de brujería es esta? Os los explico ;)

Las canciones normalmente tienen dos canales estéreo: izquierdo y derecho, que suelen tener señales de onda casi idénticas. A la hora de reproducir estas canciones en dispositivos que solo tienen un altavoz (mono) lo que hacen es combinarlas obteniendo una sola. Esta operación es muy simple: simplemente calcula el promedio de la muestra de los dos canales en un momento dado. Pero ¿que pasa si creamos un audio "hackeado" en el que el valor de un canal es el inverso del otro? Al invertir un canal de audio, este sonará igual, pero al intentar reproducir el audio resultante en un único altavoz, el promedio de ambos canales siempre será 0 (cero), es decir... ¡No oiremos nada!

¿Y si a ese audio "silenciado" le añadimos de fondo otra canción sonando tan solo al 3% del volumen de la otra? Lo vereis mejor en Audacity:


Gracias por vuestros no-comentarios, mis seguidores inexistentes. Os quiero ❤️


jueves, 24 de diciembre de 2020

Mis proyectos abandonados ven la luz: JMusic y Flappy Adventure X

¡Feliz navidad followers! No me he olvidado de vosotros (bueno, un poquito sí) os dejo un post para acabar este increíble e inolvidable 2020 que estoy seguro de que vosotros también pensáis que ha sido el mejor año que hemos tenido nunca

Imagino que leísteis mi anterior articulo sobre mis proyectos abandonados JMusic y Flappy Adventure 3

Pues bien, ¿que ha pasao'?

JMusic:

Finalmente y gracias al tiempo libre de la cuarentena fue terminado antes de cumplir 1 año en desarrollo. No quedó muy distinta a la aplicación que visteis en el screenshot del primer articulo, y tal y como tenía planeado, se quedó para mi uso privado (de hecho la uso muy frecuentemente).

Flappy Adventure X:

Link al GitHub Descargar ISO PSX



No, no me he equivocado con el título. El proyecto de Flappy Adventure 3 tomó un cambio de rumbo para la que es la última aventura de Flappy (que ya era hora de terminar con la saga).

Todo empezó cuando me di cuenta, tras jugar de nuevo al primer Flappy Adventure web de 2015, de que la mecánica de plataformas 2D de Flappy tenía mucho potencial si se desarrollaba correctamente.

Flappy Adventure 2 es un gran juego, y lo seguirá siendo; pero un sucesor mas avanzado también en 3D conllevaría moverme a Unity, o hacer un mayor esfuerzo en Three.js.

Dicho esto, quise cumplir mi objetivo con FA3 de usar más objetos dinámicos pero en una versión 2D que me llevase menos tiempo desarrollar, y que me permitiese con una mayor calidad final. En esta ocasión ademas, quise volver a los orígenes de Flappy Adventure: las videoconsolas retro.

Pensé en la GameBoy Advance, con la cual ya había trabajado, en la Sega Genesis (descartada porque segúramente me tocase programar en ensamblador del 68000). Pero... ¿y por que no ir un paso más adelante y trabajar en un scroller 3D en una videoconsola de 5ª generación? (Sega Saturn, PSX, Nintendo 64). Descubrí (Y probé) un motor muy sencillo y facil de usar en C para la Saturn, que tenía fama de ser difícil de programar, pero me daba pereza en cualquier caso, y no hice na'... Hasta que me regalaron una PS1 chipeada... (El anterior post sobre ensamblador en PSX no fue casualidad)

La cosa había cambiado, iba a poder probar mi código en hardware real, y en una videoconsola que fue muy popular. Tras analizar los SDKs me quedé con el oficial: PSYQ. Pero la cosa solo acababa de empezar. Me iba a tocar aprender el hardware de la PS1: como trabajar con su GPU, su SPU, el lector de CD, las memory card, el GTE para los graficos 3D,...

Capitulo 1: Mis experimentos en PSX

Empecé con ejemplos chorras, como portar mi motor Voxel de GameBoy Advance a PlayStation, pero en esta ocasión con infinitos angulos de rotación. ¿¿Como?? (La PSX no va sobrada de potencia, y un motor software acaba con la poca que tiene)



Resulta que usando la GPU para dibujar la textura del mapa con rotación y escalado dentro de la VRAM, luego se puede enviar de nuevo a la CPU ¿Pero y que pasa con el mapa de profundidad? Un momento... No veis algo raro en la VRAM? Los pixeles de la textura que hemos mandado a la GPU, que supuestamente son colores de RGB555 de 15 bit, en realidad llevan 7 bits de una paleta de 128 colores, y los valores de 8 bit del mapa de profundidad.


¡La GPU aplica escala y rotación al mapa de profundidad! ¡Pero no es una textura, sino una matriz de alturas que luego enviamos de vuelta a la CPU!

Sí, he implementado un ejempo real de GPU computing en una videoconsola de hace 25 años. Aunque poco tiene que ver esto con CUDA.

Y bueno, tambien hice otros experimentos como detectar colisión en un poligono (muchas matemáticas). He aquí la m*** demo que hice, no me digais que no es hermosa:


Pero bueno, si quería hacer un entorno 3D de verdad necesitaría un motor grafico... Y ahi es donde realmente volví a crear un Flappy Engine desde 0, uno que me permitiera crear mis modelos en mi querido Google SketchUp. ¿Os he dicho ya que la PlayStation no tiene hardware para ordenar poligonos por profundidad y hay que apañarselas manualmente con el orden de los poligonos?


También creé mi propio editor de niveles, en el cual ademas del terreno y las monedas, se pueden añadir montones de objetos dinámicos con distintas propiedades. Definí mi propio formato de archivo para estos niveles de mi juego: *.LVL


Y bueno, el juego fue terminado bastante tarde, en marzo de 2021, porque lo cierto es que no me interesaba mucho ponerme a avanzarlo... Pero lo terminé, que es lo importante. A continuación para los curiosos os muestro 2 screenshots del juego en su versión beta de diciembre 2020 mostrando información de depuración.



lunes, 23 de noviembre de 2020

Tutorial hacking PSX: como usar el joypad analogico en los primeros juegos de la playstation

 Si alguna vez habéis decidido usar de nuevo vuestra PS-ONE y habeis puesto uno de los primeros juegos que salieron, os habréis dado cuenta de que si usáis el mando analógico, este no funciona. Al principio los juegos no tenían soporte porque este mando ni siquiera existía.

Entonces, ¿que pasa si queréis jugar estos juegos en hardware original y el pad digital os parece duro, o incomodo? En este tutorial de m...iercoles os enseñaré como hackear estos juegos, para que si teneis la PS con chip/swapdisk podais usar el stick analogico emulando al pad digital para mayor comodidad:

Pongamos como ejemplo uno de los juegos más vendidos, el de Tomb Rider. Al activar el modo analógico en el mando, la pantalla se oscurece, y el juego se pausa.

Tras analizar un poco que causa esto, vemos que hay una función en 0x80055514 encargada de leer la memoria mapeada al joypad, y setear un flag indicando si el dispositivo conectado es un joypad digital (0x80089580) y las teclas que hay pulsadas en este joypad digital (0x80089ca4). Vamos a modificar unicamente esta función:

Empezamos con el checkeo de joypad digital que hace que se oscurezca la pantalla cuando activas el modo analógico
Aquí vemos que se compara el id de dispositivo del joypad digital (0x04) con el id de dispositivo conectado, en este caso un joypad analogico (0x07). Por este motivo, la instruccion je no salta, setea el flag de joypad digital conectado a 0, y se salta todo el código encargado de leer las teclas.

Si cambiamos el salto condicional por uno incondicional, ahora al activar el modo analógico en el pad, el juego ya no se para y los botones funcionan (los sticks siguen sin hacer nada).
El código que sigue a continuación hace algunas cosas como comprobar que SELECT y START estan presionados simultaneamente, incrementando un contador que cuando llega a 0x31, setea un flag en memoria que termina el juego y vuelve a la pantalla de menu. Pero lo más importante, y a lo que vamos... setea distintos bits de r4 que indican las teclas que hay pulsadas, para luego escribir r4 en memoria.
Lo que voy a hacer es, antes de escribir r4 en memoria y retornar, añadir código en el que comprobamos otra vez si el mando conectado es analogico, y en ese caso leer los valores de los sticks, y si se han movido hasta cierto punto, setear los flags del pad digital con operaciones OR como se esta haciendo ya con los botones en el código de arriba.

Pero claro, para inyectar mi código necesito hueco.
"Dame hueco, que habiendo hueco ya sabre..." - Jose Mota
Pues nada, abrimos el PSX.EXE con un editor hexadecimal y buscamos hueco.

Aquí hay un hueco bien hermoso, no mu grande, pero suficiente. El EXE en este juego esta cargado a partir de 0x8000F800 así que le sumamos ese valor en el código.
Y ahora a picar código...
Ahora inyectamos el PSX.EXE modificado en la ISO original con vuestro programa favorito (yo uso psx-mode2, programa de origen español, como debe ser) y lo grabamos. ¡Y ya esta! ¿dudas? ¿comentarios? ok.




lunes, 11 de mayo de 2020

PhotoMean:

Prueba PhotoMean aquí.
Hace varios años ya hice un experimento en el cual me propuse mejorar la calidad de las fotografías realizando varias veces la misma foto, a lo que le puse el nombre de "superresolution". Este experimento no tuvo los resultados esperados, que eran incrementar la resolución aparente, pero si reducía bastante el ruido y mejoraba la calidad de las fotos.
Es por esto que he creado una nueva aplicación web que os permite hacer esto de forma automatizada: combinar varias fotos para obtener una de mayor calidad

Aquí teneis las fotos de ejemplo:

Foto original:

Foto con PhotoMean:

lunes, 30 de marzo de 2020

SQL-Experiments: experimentando queries alternativas en SQL

Como ya sabréis, el lenguaje SQL permite procesar los datos contenidos en una BDD ya sea a la hora de consultarlos, insertarlos, borrarlos, o actualizarlos.
Si queremos hacer con ellos operaciones más complejas, lo habitual es, una vez obtenidos en SQL procesarlos en Java, PHP,...
Pero... ¿hasta que punto podemos ejecutar algoritmos dentro de la propia query SQL?
Recientemente he creado un nuevo respositorio en mi Github donde subir algunos experimentos.

Para inaugurar el repositorio, he subido una query recursiva que permite ejecutar el algoritmo dinámico de Longest common subsequence problem que tambien podeis encontrar en HackerRank bajo el nombre de Commond Child. La query final para SQLite me quedó así de bonica:

WITH
INPUTS(I1,I2) AS (
 SELECT 'HARRY','SALLY'
 UNION ALL SELECT 'AA','BB'
 UNION ALL SELECT 'SHINCHAN','NOHARAAA'
 UNION ALL SELECT 'ABCDEF','FBDAMN'
),
RESULTS(I1,I2,X,Y,A) AS (
 SELECT I1,I2,0,1,'0000'
 FROM INPUTS UNION ALL
 SELECT I1,I2,
  CASE WHEN X=LENGTH(I1) THEN 0 ELSE X+1 END,
  CASE WHEN X=LENGTH(I1) THEN Y+1 ELSE Y END,
  CASE WHEN X=LENGTH(I1) THEN '0000' ELSE
  SUBSTR('0000'||(
   CASE WHEN SUBSTR(I1,X+1,1) = SUBSTR(I2,Y,1)
   THEN 1 + CAST(SUBSTR(A,1+4*(LENGTH(I1)+1),4) AS INTEGER)
   ELSE MAX(CAST(SUBSTR(A,1+4*LENGTH(I1),4) AS INTEGER),CAST(SUBSTR(A,1,4) AS INTEGER)) END
  ),-4,4) END || A
 FROM RESULTS
 WHERE NOT (X=LENGTH(I1) AND Y=LENGTH(I2))
),
FRESULTS(I1,I2,R) AS (
 SELECT I1,I2,CAST(SUBSTR(A,1,4) AS INTEGER) FROM RESULTS WHERE X=LENGTH(I1) AND Y=LENGTH(I2)
)
SELECT * FROM FRESULTS;
Sí os perdeis, tambien teneis otra query más simple que os permite generar un triangulo de pascal como en otro problema de HackerRank. La query es así de bonica:

WITH P(N,ROW,IT,REM) AS (
SELECT '1',1,1,''
UNION ALL
SELECT CASE WHEN REM='' THEN '1' ELSE N||' '|| --FIRST VALUE ALWAYS 1
 CASE WHEN instr(REM, ' ')=0 THEN REM  --IF REM ONLY HAS A NUMBER(1) CONCAT N THIS VALUE
 ELSE substr(REM, 1, instr(REM, ' ')-1) + --ELSE CONCAT SUM OF FIRST 2 NUMBERS OF REM
  CASE WHEN instr(substr(REM, instr(REM, ' ')+1),' ')=0 THEN substr(REM, instr(REM, ' ')+1) ELSE
  substr( substr(REM, instr(REM, ' ')+1),1,instr( substr(REM, instr(REM, ' ')+1),' ')-1) END
 END
END,
CASE WHEN REM='' THEN ROW+1 ELSE ROW END,
CASE WHEN REM='' THEN 1 ELSE IT+1 END,
CASE WHEN REM='' THEN N WHEN instr(REM, ' ')=0 THEN '' ELSE substr(REM, instr(REM, ' ')+1) END --POP FIRST NUMBER FROM REM / SET IT TO PREVIOUS N
FROM P
WHERE ROW<=15
)
SELECT N FROM P WHERE ROW=IT;

Y el resultado de ejecutarla es así de bonico:

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1
1 11 55 165 330 462 462 330 165 55 11 1
1 12 66 220 495 792 924 792 495 220 66 12 1
1 13 78 286 715 1287 1716 1716 1287 715 286 78 13 1
1 14 91 364 1001 2002 3003 3432 3003 2002 1001 364 91 14 1
Os recomiendo ver los enlaces de los problemas y del repositorio donde se explica como están implementados. Ahora sí, esto es importante followers:
¡Sugeridme más experimentos SQL en los comentarios! ;)

domingo, 29 de marzo de 2020

Remote-Clipboard: Compartiendo portapapeles entre varios ordenadores.

Proyecto Github aquí.
Hay mucha gente que trabaja con más de un ordenador a la vez, con maquinas virtuales, etc... Y uno de los problemas a los que se enfrentan es a copiar y pegar entre distintos equipos. Cada uno tiene un portapapeles distinto, y si haces CTRL+C en un ordenador, y CTRL+Z en el otro no obtendrás ese contenido... Hasta ahora.
Con mi nuevo proyecto Java, podéis compartir a través de un servidor el contenido de vuestro portapapeles cada vez que copiais o haceis CTRL+C y actualizar en tiempo real el portapapeles de todos los equipos conectados al servidor (Se envía cifrado con AES del bueno).
¿Dudas? ¿comentarios? Veo que no XD

martes, 17 de marzo de 2020

Obteniendo la colisión de videojuegos en PSX

Proyecto de Github aquí.

Recientemente me enfrenté al proyecto de reversing más complejo que he hecho hasta la fecha, pero antes de nada os pongo un poco en contexto:

Hace ya tiempo apareció en Youtube un canal llamado "GameHut", el cual trata sobre como se desarrollaban los videojuegos antiguamente, en especial en la epoca de la SEGA Saturn/Megadrive. El dueño del canal podría ser cualquier ex-programador de esa epoca... Pero no,  sorprendentemente se trata de Jon Burton, fundador y antiguo jefe de la compañía de videojuegos Travellers Tales.
Os animo a visitar su canal de Youtube ya que es muy interesante.
Curiosamente incluso llegó a ver mi video sobre la tech-demo de TT oculta que encontré, la cual según contestó en Twitter fue desarrollada por él mismo.
Bueno, la cuestion es que yo ya conocía algunos juegos de Travellers Tales, incluyendo los de PSX que estan basados sobre todo en peliculas de Pixar, y estando familiarizado con ellos, me dió la impresión de que compartian el mismo motor de alguna manera, y había algo que siempre había tenido curiosidad, y es... ¿Se puede obtener la colisión de estos juegos de alguna forma para hacerla visible?
Pues me llevó varios días de buscar estructuras de datos en la RAM del emulador relacionadas con la colisión, mucho ensamblador MIPS (Incluso llegué a mirar por encima el funcionamiento del coprocesador de la PSX) y bueno, aunque muchas veces mirar los datos de la RAM y cambiarlos arbitrariamente te da muchas pistas, el hecho de mirar lo que hacían las rutinas de ensamblador que accedían a esas direcciones me ayudó mucho.
Pues al final lo conseguí hacer, y efectivamente el motor de colisión es prácticamente el mismo en todos los juegos de TT, con algunos pequeños cambios entre alguno de ellos, por ejemplo: en TS2 y BLSC el motor es exactamente idéntico, y al contrario que en los juegos previos, los poligonos de colisión pueden ser o bien triangulos o bien cuadrilaterios (en los anteriores solo podían ser triangulos).

Travellers Tales Collision Viewer es una aplicacion Web (Javascript) que lee SaveStates del emulador PSXE y muestra los polígonos y objetos de colisión del nivel cargado en el momento de realizar el SaveState. Tiene soporte para todos los juegos de PSX desarrollados por Travellers Tales. Se muestra no solo la colisión del nivel final, sino también la de los polígonos de prueba que se usarían durante el desarrollo y testing del videojuego ¿A que me ha quedado bonico?



Polígonos de colisión de prueba de distintos tipos, situados fuera de los limites de uno de los niveles de TS2