Tutorial desprotección Nonamed

Cómo pasar juegos a diferentes archivos, herramientas, software.
Avatar de Usuario
AmstradGamer
Forero habitual
Forero habitual
Mensajes: 189
Registrado: Dom 08 Jun , 2014 10:08 am

Tutorial desprotección Nonamed

Mensajepor AmstradGamer » Sab 26 Jul , 2014 11:58 am

Hola.

Aunque soy bastante novato en la materia e incluso en el foro, pero dado que se me ha comentado un par de veces que lo hiciera y estoy siempre a favor de compartir conocimiento, voy a intentar exponer en forma de pequeño tutorial como desproteger Nonamed.

Es posible que alguna de las cosas que haga no lo sean de la mejor forma posible, desde luego seguro que las hay más fáciles. Mi objetivo era intentar hacer la desprotección haciendo uso solo del Amstrad, intentando evitar usar emuladores. Hace 30 años no había emuladores y ya se desprotegían juegos… ¿cómo lo hacían?

Si os parece, expongo cómo lo hice y luego si hace falta con aportaciones de otros lo vamos perfilando y/o mejorando.

En cualquier caso, espero que sirva de ayuda o primeros pasos a aquellos que, como yo hace unos días, tienen curiosidad por desproteger un juego y no saben por dónde empezar.

¿Qué necesitamos?
  • Un Amstrad CPC.
  • Un casette con el Nonamed o bien un CDT y alguna manera de reproducirlo en el CPC.
  • Un casette virgen o disco donde guardar la versión desprotegida.
  • Un desensamblador
  • Un copión o visor de cabeceras
  • Un mínimo de conocimientos de la máquina, de basic y ensamblador.
En mi caso voy a utilizar un CPC 464, el Nonamed original y como destino un disco de 3.5’’ formateado para datos que de paso me va a servir para estrenar mi recién ensamblada unidad de 3.5, conectada a través de la DDI-1. ¿A que ha quedado resultona?

Imagen

Como desensamblador podemos utilizar el incluído en el DEVPAC (MONA3), efectivo pero farragoso. En este paso podemos utilizar el emulador, va, pero porque sabemos que el proceso sería exactamente el mismo que usando el hardware real, solo que muchísimo más cómodo.

Por último podemos usar un copión o visor de cabeceras para obtener cierta información sobre los primeros bloques del juego.

Empezamos

Lo primero es analizar qué tenemos en la cinta original. Para ello lo mejor es cargar el juego y ver qué va pasando.

Si lo hacemos veremos que el juego está compuesto por lo siguiente:
  • Un bloque BASIC, salvado como protegido. Si hacemos un load no veremos su código al hacer list.
  • Otro bloque binario o código máquina, que es el que tiene el código de carga turbo.
  • Una carga turbo, correspondiente a la pantalla del juego.
  • Una carga turbo, correspondiente al juego.
Nuestro objetivo es no solo obtener el juego, sino también su pantalla de carga.

Vamos a ponernos manos a la obra.

Direcciones

El procedimiento que vamos a seguir para poder volcar nuestro juego de forma desprotegida es el siguiente:
  • Averiguar en qué parte de la memoria está cargado, es decir, dirección de carga y longitud.
  • Averiguar cual es la dirección de ejecución.
Para la pantalla es bastante sencillo, sabemos que la dirección de memoria donde empieza la pantalla es la &C000 y que esta ocupa 16KB, que es &4000 en hexadecimal.

Eso siempre va a ser así, si volcamos a cinta o disco los 16KB de memoria que empiezan en &C000 habremos almacenado una captura de pantalla. Es importante por lo tanto hacerlo cuando tengamos en pantalla aquello que queramos guardar, la pantalla de carga del juego.

Hay que ser cuidadosos y no escribir nada en pantalla antes de almacenarla, puesto que lo que guardaríamos sería lo que se ve justo en el momento de hacer el volcado.

Si bien para la pantalla tenemos claro que siempre estará ahí, en el caso del juego no sabemos ni donde se almacena exactamente, ni lo que ocupa, ni su dirección de ejecución. Aquí es donde debemos empezar a investigar.

El bloque BASIC

Puestos a empezar, hagámoslo por el principio.

Como he comentado el primer bloque del juego está programado en Basic, pero si lo cargamos con un load”” y hacemos list no veremos su código, puesto que está protegido.

Se me ocurrió que la manera más sencilla de ver que contenía este fichero era copiarlo con un copión que me lo devolviera de forma desprotegida.

Aquí cada uno puede utilizar el que mejor le venga, en mi caso utilicé el Bonzo Meddler, que me permite pasar a disco el fichero desprotegido a la vez que me muestra información en pantalla.

Imagen

Una vez cargado el fichero desprotegido vemos que su contenido es:

Código: Seleccionar todo

10 INK 0,0:BORDER 0:MODE 0:OPENOUT “c”:MEMORY 1999:CLOSEOUT
20 LOAD”!c
30 CALL 2000
Es decir, que lo único que hace es poner la pantalla en negro en modo 0, cargar el cargador binario en la dirección de memoria 2000 y ejecutarlo con un call.

Lo que sí es importante es que nos da la dirección de ejecución del cargador, aunque siendo sinceros, esta información la podríamos haber obtenido también a través del Bonzo o cualquier otro visor de cabeceras y ahorrarnos este paso.

Imagen

El bloque binario

Como hemos visto en la última captura, este bloque está escrito en código máquina. Necesitaremos por lo tanto un desensamblador para echarle un vistazo.

Ya que tenemos cargado el fichero nonamed.bas borramos la última linea (30 y enter) y modificamos la 10 para que no cambie el modo de pantalla ni la ponga en negro.

Código: Seleccionar todo

10 OPENOUT “c”:MEMORY 1999:CLOSEOUT
20 LOAD”!c
Ejecutamos. Esto cargará el código máquina del cargador turbo en memoria, pero no lo ejecutará.

Ahora podemos utilizar un desensamblador o un emulador, pero lo que tenemos que conseguir en cualquier caso es poder ver el código máquina que hay cargado a partir de la posición 2000 de memoria ó &07D0 en hexadecimal.

Aquí empieza la fiesta. Más que pretender entender linea por linea lo que hace el código, debemos utilizar un poco de intuición.

Lo que sabemos por el comportamiento que hemos observado mientras hemos realizado la primera carga del juego, es que este cargador lo que hace es cargar la pantalla del juego, luego carga el juego y lo ejecuta.

Si vamos siguiendo el código ensamblador pronto llegaremos a unas lineas de este estilo:

Código: Seleccionar todo

LD DE,#C000
LD BC,#4000
LDIR
Imagen

Como ya he dicho, yo no soy un experto, pero esos datos coinciden con lo que hemos comentado antes sobre la dirección de la memoria de pantalla y su longitud. Por lo menos hay algo que nos resulta familiar en el código.

Sabemos que lo siguiente que hace el cargador tras mostrar la pantalla de carga es cargar el juego en sí.

Las siguientes lineas de código tras la carga de la pantalla son:

Código: Seleccionar todo

LD IX,#1E3C
LD DE, #8811
¿Podrían ser estas, por analogía, la dirección de carga y longitud del código del juego?

Algunos datos útiles:

&1E3C = 7740
&8811 = 34833

7740 + 34833 = 42573 = &A64D

&8811 en decimal son unos 34KB, bien podría ser la longitud del juego…. Dejamos por lo tanto estos valores como candidatos.

Ahora debemos ir en busca de la dirección de ejecución del juego.

Lo más probable es que para ejecutar el código del juego el cargador “salte” a él con una instrucción JP, por lo que buscamos esto entre las direcciones 2000 y 2320, es decir, entre la &07D0 y &0910.

Si os fijais en la dirección de memoria &0832, unas pocas lineas más abajo de por donde íbamos, tenemos la instrucción JP #9FC6 que además está dentro del rango &1E3C – &A64D que haría válidos los candidatos que hemos localizado antes.

No estamos seguros del todo, pero… podríamos probar a ver si tenemos suerte.

Desprotector

Bueno, pues ya tenemos toda la información que necesitamos para desproteger el juego, aunque aún no estamos seguro de si los valores son los correctos.

La mejor forma de averiguarlo es probándolo.

Para hacer el volcado desprotegido del juego deberíamos hacer algo como:
  • Cargar el cargador normal del juego y ejecutarlo
  • Dejar que cargue la pantalla del juego
  • Dejar que cargue el código del juego
  • Impedir que se ejecute el juego y retomar el control
  • Salvar la pantalla del juego
  • Salvar el código del juego
  • Obtener el valor de las tintas
Una vez tengamos en formato desprotegido tanto la pantalla como el código del juego, necesitaremos hacer nuestro propio cargador, pero esto lo veremos luego.

De momento vamos a empezar por el final, por la obtención de las tintas.

Hay información sobre la pantalla que no tendremos a priori y que tendremos que averiguar. Básicamente es el modo de pantalla y las tintas.

El modo es sencillo de averiguar a simple vista, aunque además ya lo sabemos por el código del bloque basic, es modo 0.

Necesitamos una manera de obtener por lo tanto el valor de las 16 tintas asociadas a este modo si queremos que la pantalla de carga aparezca con los colores correctos.

Obtener el valor de las tintas usando un emulador es trivial. Simplemente miramos sus valores tras haber cargado la imagen y las apuntamos, pero como ya he comentado aquí queremos hacerlo sin ayuda de emuladores.

Existe una función de BIOS que permite obtener el valor de una tinta en concreto, es la &BC35, pero no podemos llamarla desde BASIC, bueno sí, pero no recuperar el valor devuelto.

Esta función, al ser llamada deja en los registros BC los valores de las tintas primaria y secundaria para la tinta indicada en el registro A.

Haremos un pequeñísimo programa en ensamblador que recupere el valor de una tinta dada y la deje en una posición de memoria conocida:

Código: Seleccionar todo

LD A, 0
CALL #BC35
LD (#A660), BC
RET
Con este pequeño programa recuperamos el valor de la tinta 0 en la posición de memoria &A660. Luego bastaría con leer el valor de esa posición de memoria para obtener el valor de la tinta, cosa que podemos hacer sin problemas desde BASIC con un PEEK.

Si ensamblamos el código máquina equivalente queda:

Código: Seleccionar todo

3E 00
CD 35 BC
ED 43 60 A6
C9
Dejamos aparcado de momento este código para obtener tintas y seguimos con el listado.

El resto de puntos de la lista es bastante sencillo, salvo lo de impedir que se ejecute el juego.

Sabemos que llegados a un punto, tras haber cargado el código del juego, el cargador de código máquina hace un JP a una dirección de memoria, lo cual hace que se ejecute el código del juego.

¿Qué pasa si sustituimos esa instrucción JP por un RET? Pues que volveremos al BASIC y tendremos el juego cargado en memoria y el control del ordenador para hacer lo que queramos, que será volcar el juego en cinta o disco.

¿Cómo podemos cambiar ese JP por un RET? Pues haciendo un poke del valor de código máquina del RET en la posición de memoria donde está el JP, que si recordais es la &0832.

Dicho y hecho, con un POKE &0832, &C9 lo tenemos. Este cambio debemos hacerlo después de haber cargado en memoria el cargador en código máquina, pero antes de ejecutarlo.

Bien, pues juntando todo lo que hemos comentado, nuestro programa desprotector quedaría de la siguiente forma.

Aclarar que tal como está, está pensado para volcar el juego en disco. En cinta sería prácticamente igual, pero habría que dejar hueco para nuestro cargador antes.

Bueno, creo que se entenderá.

Código: Seleccionar todo

10 |TAPE.IN:|DISC.OUT
20 MODE 0:BORDER 0:INK 0,0
30 OPENOUT"c":MEMORY 1999:CLOSEOUT
40 LOAD"!c"
50 POKE &832,&C9
60 CALL 2000
70 SAVE"!NONAMED.SCR",b,&C000,&4000
80 SAVE"!NONAMED.BIN",b,&1E3C,&8811,&9FC6
90 FOR n=&A650 TO &A659:READ a$:POKE n,VAL("&"+a$):NEXT n
100 FOR t=0 TO 15
110 POKE &A651,t
130 CALL &A650
140 PRINT PEEK(&A660)
150 NEXT t
200 DATA 3E,00,CD,35,BC,ED,43,60,A6,C9
La linea 90 carga nuestra rutina en ensamblador a partir de la dirección de memoria &A650.

El bucle que empieza en la linea 100 modifica el valor de &A651 en cada iteración, ya que es donde se almacena el número de la tinta para la cual queremos recuperar su valor.

Una vez tenemos el listado, por si acaso lo podemos guardar, por ejemplo como “unprotec.bas”.

En cualquier caso, rebobinamos la cinta, hacemos run del programa y damos al play.

Tras cargar el juego, éste se volcará en disco como NONAMED.BIN y su pantalla de carga como NONAMED.SCR. También nos mostrará el valor de las 16 tintas de la pantalla de carga. Las apuntamos.

Imagen

Ahora solo nos falta hacer un pequeño programa en BASIC para cargarlos y ejecutarlos.

Por cierto, como hemos tenido precaución de poner el código de obtención de tintas fuera del rango de memoria ocupado por el juego, haciendo un call &9FC6 podemos echar unas partidillas y comprobar que el juego está bien cargado.

Cargador

El código del cargador es bastante sencillo. Ponemos el modo de pantalla correcto, así como las tintas, cargamos la pantalla, cargamos el juego y lo ejecutamos.

Quedaría más o menos así:

Código: Seleccionar todo

10 MODE 0:BORDER 0
20 INK 0,0:INK 1,16:INK 2,26:INK 3,12:INK 4,24:INK 5,4:INK 6,8:INK 7,15:INK 8,20:INK 9,1:INK 10,2:INK 11,11:INK 12,25:INK 13,17:INK 14,3:INK 15,6
30 OPENOUT”C”:MEMORY &1E3B:CLOSEOUT
40 LOAD”!NONAMED.SCR”,&C000
50 LOAD”!NONAMED.BIN”,&1E3C
60 CALL &9FC6
Y si lo salvamos como “NONAMED.BAS” ya tenemos nuestro juego desprotegido y listo para funcionar.

He dejado el listado del cargador así para que quede más claro, pero una forma más compacta y elegante de hacer lo mismo podría ser:

Código: Seleccionar todo

10 MODE 0:BORDER 0
20 FOR n=0 TO 15:READ a:INK n,a:NEXT n
30 OPENOUT”C”:MEMORY &1E3B:CLOSEOUT
40 LOAD”!NONAMED.SCR”
50 RUN”!NONAMED.BIN”
60 DATA 0,16,26,12,24,4,8,15,20,1,2,11,25,17,3,6
Espero que mi primer tutorial en esta web sea del agrado y sobre todo de utilidad para muchos.

Cualquier comentario, aclaración o mejora será bienvenida. La idea es que al final tengamos algo claro y útil.

Saludos.
Última edición por AmstradGamer el Dom 27 Jul , 2014 7:06 pm, editado 1 vez en total.

Avatar de Usuario
sinclair200
Forum Addict
Forum Addict
Mensajes: 428
Registrado: Lun 21 Jul , 2014 12:21 pm
Ubicación: Madrid

Re: Tutorial desprotección Nonamed

Mensajepor sinclair200 » Sab 26 Jul , 2014 3:37 pm

Joer, y eso que dices no ser un experto......vaya envidia que me ha dado, yo lo mas, hacer algún programilla Basic, y de eso, hace siglos que no lo hago....Enhorabuena, por el tutorial y por el trabajo realizado.

Cuando te refieres que has conectado la disquetera de 3,5 al interface DDI1, es la controladora que lleva los chips de disquete que le faltan al CPC 464..no?
Yo he tenido la enorme suerte hace unos días de adquirir en Inglaterra la unidad externa de Amstrad con cable y controladora, me ha costado casi 70 euros, pero un capricho...no tiene precio...jajajaja

Imagen
SINCLAIR200

Avatar de Usuario
AmstradGamer
Forero habitual
Forero habitual
Mensajes: 189
Registrado: Dom 08 Jun , 2014 10:08 am

Re: Tutorial desprotección Nonamed

Mensajepor AmstradGamer » Sab 26 Jul , 2014 3:52 pm

Sí. Me refiero a eso mismo. Yo también me hice con una como la tuya, pero los discos de 3" que encuentro o son muy caros o no son fiables.

Esta semana he cogido una disquetera vieja, una caja de un cd externo y me he montado lo que se ve en la foto, sustituyendo a la unidad original de Amstrad.

Además he rescatado mi primer portátil, que tiene disquetera y me es sencillo pasar DSKs a disco con él, por lo que mi catálogo de juegos disponibles en disco se ha disparado. :)

Un saludo.

Avatar de Usuario
6128
Moderador
Moderador
Mensajes: 7900
Registrado: Lun 12 Dic , 2005 6:08 pm

Re: Tutorial desprotección Nonamed

Mensajepor 6128 » Dom 27 Jul , 2014 10:02 am

Muy bueno el tutorial. =D>
Ahora el que tenga morriña por desproteger cintas de carga sencilla ya no tiene excusa. Las multicarga ya son otra cosa.

Avatar de Usuario
LexSparrow
Master of The Forum
Master of The Forum
Mensajes: 1009
Registrado: Dom 18 Dic , 2005 3:17 am
Contactar:

Re: Tutorial desprotección Nonamed

Mensajepor LexSparrow » Lun 28 Jul , 2014 2:07 am

De los mejores posts que se han visto en Amstrad.es
END OF LINE


¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro


La Comunidad Española
ESP Soft, juegos para tu CPC Foro de Amstrad CPC Todos los juegos para CPC en un CD Web dedicada al Amstrad CPC (utilidades) Información útil para el CPC (talleres) Selección de juegos de Amstrad CPC Mundo CPC Pree Play then any Key CPC Basic