-[ 0x08 ]--------------------------------------------------------------------
-[ Java en moviles ]---------------------------------------------------------
-[ by FCA00000 ]-----------------------------------------------------SET-31--

Java en mviles
***************

Cont hace unos cuantos artculos cmo opera la mquina virtual Java y cmo
funciona el compilador .
Tambin hubo un apartado para explicar la manera de modificar una clase
Java sin necesidad de tener acceso al cdigo fuente original.

De nuevo voy a contar algo parecido, pero siguiendo en mi lnea de artculos
para mviles, ahora mostrar un poco cmo funciona Java en un telfono mvil.
Para los que entendieron el artculo anterior, ste posiblemente no les
proporcione nueva informacin, pero nunca se sabe.
Tambin quiero recomendar el genial artculo escrito en la e-zine 29A sobre
virus en Java. Proporciona una visin muy detallada del funcionamiento interno
con algunas ideas muy buenas.

Segn la ley espaola, hacer sto sin consentimiento del autor puede ser
un delito. Es ms, la simple posesin de ste artculo es un delito.
Si no quieres cometer una ilegalidad, no sigas leyendo y destruye este
fichero.

Hace bastante tiempo que existen en el mercado una gran oferta de dispositivos
pequeos con capacidad de ejecutar programas compilados en Java.
Esto incluye mviles, PDAs, reproductores de MP3, ...
Como ya era tiempo de que yo me adaptara a las tecnologas mas recientes, he
adquirido un telfono Siemens (cmo no) modelo M65.
Las caractersticas tcnicas son similares a las de otros modelos de la misma
gama: pantalla de 132x176 pixels, 16 Bits de colores, sonido polifnico MIDI-1,
vibracin, teclas y cursor, cmara, infrarrojos, MMS, puerto serie, ...
Internamente tiene un procesador ARM de 32 bits, 16 Mg de flash, 11 Mg de RAM,
stack Java de 1.5 Mg, y soporta MIDP-2.0 y CLDC-1.1 con soporte de WML y HTML
sobre WAP2.0 y GPRS Clase 10. Permite video h263 .
Esto lo convierte en un mvil bastante completo y muy capaz de ejecutar
aplicaciones Java con un gran conjunto de funcionalidades.

Dado que los mviles estn restringidos en tamao, memoria, potencia, y
velocidad, slo usan un conjunto reducido de libreras Java especifcas para
dispositivos pequeos, llamado J2ME - Java2 Mobile Edition.
Los sistemas soportados por el M65 son:
MIDP 2.0
CLDC 1.1
JSR 120 WMA 1.0
JSR 135 MMA 1.0
JSR 179 Location API
JSR 185 JTWI 1.0

El sistema base es MIDP 2.0 con el cual se pueden hacer cosas como cargar
dibujos desde ficheros, dibujar sprites en la pantalla, pintar decorados,
generar mapas hechos con iconos, crear formularios HTML con los elementos
tpicos (textos, botones, listas, botones para elegir, dilogos, fechas,
tipos de letras, ...) adems de generar sonidos, conectarse con la red, mandar
y recibir SMS, iniciar llamadas y otras muchas cosas ms.
En fin, que es bastante extenso.
Se ha puesto especial atencin al terreno de los juegos, haciendo que vayan a
una velocidad ms que aceptable.
Pero no quiero contar ahora cmo hacer juegos. Primero hay que aprender a
modificar juegos ajenos.

Lo primero es conseguir algn juego. En mi mvil vienen instalados 4 que estn
incluidos en el precio, as que tengo la correspondiente licencia para usarlos.

Tambin es posible meter nuevos juegos mandando mensajes a unos servidores, y,
previo abono, aparecen en tu mvil.
Otra opcin es buscar pginas de Internet que los tengan. Algunos juegos son
gratuitos, y otros ofrecen una versin de demostracin. Tambin existen otros
de pago, claro.
Finalmente, existen pginas web con juegos piratas, pero descargarlos de estas
pginas es ilegal y supone un delito. As que haznos un favor a todos y paga
por el software que uses. Es la nica manera de seguir adelante con la
industria y el desarrollo.
Existen por ah colecciones extensas de ms de 500 juegos.

Puesto que el M65 tiene puerto de infrarrojos, puedo transferir los programas
desde mi PC hasta el mvil todas las veces que deseo. Otra opcin es usar el
cable serie o USB.

Todo lo que necesito est disponible para Windows. Algunas aplicaciones tienen
versiones para otros entornos, pero lamentablemente no todas.

La primera herramienta que necesito es un descompilador de Java.
Yo uso "jad" hecho por Pavel Kouznetsov.
A veces uso el GUI llamado "DJ Java Decompiler" hecho por Atanas Neshkov.

Algo fundamental es un compilador de Java. Yo uso el JSDK 1.4.1 de Sun con
las extensiones de J2ME.
Existen tambin muy buenos entornos grficos para usar el compilador, pero
para este artculo no son necesarios.

La manera oficial de probar si las modificaciones funcionan son, por supuesto,
meter el programa modificado en el mvil. Sin embargo Siemens pone a
disposicin de todos los desarrolladores una herramienta llamada
SMTK - Siemens Mobile Tool Kit entre las cuales incluye un emulador de mvil.
Existen para muchas versiones de mviles, por supuesto hay una para M65.
El funcionamiento es sencillo: copia el programa modificado en un directorio
del disco duro, inicia el emulador, y carga dicho programa. La emulacin no
es 100% perfecta, y el emulador falla demasiado para mi gusto.
Pero siempre queda la opcin de usar el mvil real.

Para los mviles Nokia existe el NDS-Nokia Developers Suite for J2ME.
Si quieres probar que el programa original funciona perfectamente en todos los
mviles, deberas considerar esta opcin.
En general esto es muy til para los creadores de programas.

Otra utilidad es un editor hexadecimal.
Y un programa que sirve para sacar diferencias entre un archivo y otro, tanto
en modo binario como en texto. Yo uso WinDiff.

********************

Voy con el primer ejercicio.
El programa se llama Megablaster y es uno de estos arcades en los que naves
espaciales aparecen la parte alta de la pantalla y tu nave situada en la parte
baja debe destruirlas o esquivarlas.
No es que sea una idea innovadora, pero el programa est muy bien realizado y
es fcil de jugar.
Est realizado por la empresa italiana Microforum Games. Un programador, un
dibujante, algunos testers, y poco ms.

Lo primero es meterlo en el mvil: si usas Windows con infrarrojos, inicia la
aplicacion IrFTP, pon el mvil cerca del PC, elige el archivo del disco duro,
y envalo al mvil. Entonces aparecer una carpeta en la parte inferior
derecha, y pulsando el botn de dicho men, copia la aplicacin al directorio
que quieras dentro del mvil, No es posible jugar si no mueves antes el fichero.

Cuando empiezo a jugar voy pasando niveles y me van matando naves.
Me doy cuenta de que de vez en cuando obtengo una vida extra. Empiezo con 3, y
como soy muy malo jugando, las pierdo rpidamente.
As que voy a modificarlo para no perder vidas nunca.

Tengo que buscar una variable que se inicialice a 3, que se incremente algunas
veces, que se decremente otras, y que se compruebe en algun momento que vale 0.
El programa est en un fichero llamado Megablaster.jar de 84 Kb.
Lo desempaqueto con la aplicacion   jar  que se instala con el JSDK, o tambin
con el WinRAR.
El paquete completo se compone de:
-unos cuantos ficheros de texto en el directorio raz, con las intrucciones
 en varios idiomas.
-un directorio "icons" con slo un fichero   navetta.png   que puedo ver
 incluso con Internet Explorer
-un directorio "sound" con un fichero de msica  hotrod.mid  . Muy animada.
-otro directorio "pics\acc" con todos los grficos
-un fichero en  META-INF\MANIFEST.MF
-otro directorio "olympics" con varios ficheros *.class

El fichero META-INF\MANIFEST.MF es un texto en el que se indica la versin
mnima de APIs que necesita el programa. En este caso es MIDP-1.0 y CLDC-1.0 ,
con lo que mi mvil lo soporta prefectamente.
Tambin se indica cual es la clase que contiene la funcin que inicia el juego.

Pero el meollo del asunto est en 2 clases:  olympics\MainPRG.class  y
olympics\b.class

Dado que las clases Java se compilan, y luego es la mquina virtual la que
ejecuta el programa, es sencillo desensamblar un programa Java para obtener
algo a medio camino entre el cdigo original y un cdigo binario.
Para hacer la tarea de los "rompedores de programas" mas difcil, es comn que
antes de sacar el juego al pblico, el programa se pasa por otra aplicacin
llamada enrevesador (obfuscator) que simplemente hace el cdigo mas dficil
de entender.
Entre las tcnicas de "ofuscacin" hay una consistente en sustituir los
nombres de las funciones por otros consistentes en letras simples.
As, la funcin
PintaNave() se sustituye por a()
Como adems Java permite que las funciones tengan el mismo nombre, con tal de
que tengan distintos parametros:
SumaBonus(x) se sustituye por a(x)

En programas para mviles, este paso de enrevesamiento es obligado. Al reducir
los nombres de las funciones y las clases se ahorran algunos bytes que no
afectan al funcionamiento del programa pero hacen que ocupe menos espacio.
Incluso se ejecutan ms rpido.
Hay otro paso necesario y es la pre-verificacin de las clases.
La maquina virtual Java de los mviles debe ser pequea as que el
verificador de clases es mnimo, dejando esta tarea en manos del programador,
el compilador, y otra herramienta llamada pre-verificador.
Pero esto no afecta a la descompilacin de programas.

Lo primero que hago es desensamblar los programas con la utilidad   jad  .
Una clase de 25 Kb se convierte en un cdigo fuente de 45 Kb con 2.500 lineas.
Me pongo a buscar cundo algo se iguala o se compara con el valor 3.
En la clase MainPRG :
a) funcion _mthif(int i1, int j1)   ---->   if(i1 == 3)
b) funcion _mthnew()        ---------->   l = 3;
c) funcion _mthnew()        ---------->   if((_fldtry == 5) & (i <= 3))
d) funcion  a(String s1, int i1)    ---->   if(l1 < 3) l1 = 3;
e) _mthif(int i1)         ----------->   if(E[i1]._fldgoto == 3)
f) _mthif(int i1)        -------->   if(E[i1].a == 3)
g) _mthfor(int i1)     ------->   E[i1]._fldgoto = 3;
h) _mthlong(int i1)    ---->   if(i1 == 3) I.a(4, "/pics/acc/fondo_03a");
i) _mthnull(int i1)    ---->   _fldlong[i1]._fldfor += 3 + n;

Voy a analizarlos uno por uno.

En la rutina a) el valor de i1 se compara con 1, 2, 3, 4, y 5. Como no creo
que haya una lgica distinta dependiendo del numero de vidas, supongo que
sta no es la rutina que me interesa.
En b) hay muchas cosas que comento ms tarde.
En c) veo que tanto las comparaciones anteriores y posteriores involucran
      nmeros como 220, 765 , ...
En d) querra decir: si el numero de vidas ya es 3, no aadas vidas extra.
      Pero eso no ocurre, as que esta comparacin no tiene nada que ver.
En e) f) y h) creo que no tiene sentido mirar si el nmero de vidas es
      exactamente igual a 3.
En g) parece mas prometedor, pero esta funcin se llama con argumentos 0 y
      100, que no parece que tengan nada que ver.
      De todos modos la dejo en reserva por si acaso.
En b) veo que usa la variable l.
Esta variable se usa en:
i) _mthnew()       para hacer if(w > G) { l = l + 1; G = G + 50000; }
ii) _mthgoto(int i1)   para hacer if(l == 0)  k=0;
iii) _mthdo(int i1)    para hacer l = l - 1;

Por cierto, que hay otra funcion con distinto numero de argumentos:
_mthdo()
{
if(k == 0)
   I.a(1, I.Q, I.B, "GAME OVER", 0);
}

O sea, que la variable k dice cundo se acaba la partida.
Recordar que esta variable se ha puesto en _mthgoto(int i1)  

Vamos, yo creo que la variable   l   contiene el nmero de vidas.
En b) har que ponga      l = 4;
y ver si empiezo con 4 vidas.

Desensamblando con
jad -a MainPRG.class

obtengo
 k = 1;
 // 37 69:aload_0 
 // 38 70:iconst_1 
 // 39 71:putfield #32 <Field int k>
 l = 3; <-***********--******--
 // 40 74:aload_0 
 // 41 75:iconst_3  <-***********--******--
 // 42 76:putfield #35 <Field int l>
 d = 1;

Asi que intento cambiar
41 75:iconst_3 
por
41 75:iconst_4

Para ello lo desensamblo con  java -d
y veo que en la posicin 1FB7 tengo que cambiar el byte
0x06 , que significa iconst_3
por
0x07 , que significa iconst_4

Para verificarlo, desensamblo de nuevo y veo que efectivamente queda
l = 4;

Ahora llega el momento de comprobarlo. Meto el
MainPRG.class
dentro del Megablaster.jar  con WinRAR, y lo transfiero al mvil.
Inicio el juego, y veo que ahora tengo 4 vidas al empezar.
Bien, as que mis pesquisas eran correctas.

Una vida extra es una ayuda, pero no muy grande.
Podra sustituir la instruccin anterior por
iconst_100
para tener 100 vidas, pero hay un problema:
la instruccin iconst_4 se codifica como un nico byte: 07
Pero si quiero cargar un valor mayor de  6  debo usar la instruccin
iconst_NN
que ocupa 3 bytes. Como no puedo hacer hueco dentro del cdigo, lo mejor es
modificar el programa para no perder ninguna vida.

Existe otra rutina que usa la variable   l   en MainPRG.class
void _mthdo(int i1)
 {
 l = l - 1;
 // 0 0:aload_0 
 // 1 1:aload_0 
 // 2 2:getfield #35 <Field int l>
 // 3 5:iconst_1 
 // 4 6:isub 
 // 5 7:putfield #35 <Field int l>
 E[i1].a = 6;
 // 6 10:aload_0 
 // 7 11:getfield #13 <Field a[] E>
 // 8 14:iload_1 
 // 9 15:aaload 
 // 10 16:bipush 6
 // 11 18:putfield #135 <Field int a.a>
 // 12 21:return 
 }

Este es el nico sitio donde se decrementa la variable   l , seguramente
cuando un misil enemigo alcanza a la nave.
As que pretendo cambiar 
 l = l - 1;
por
 l = l - 0;

Es decir, cambiar
 // 3 5:iconst_1 
por
 // 3 5:iconst_0
Vuelvo a desensamblar con   java  -d   porque esta aplicacin me dice los
cdigos binarios, y veo que en la posicin 0x1F41 hay que cambiar el byte
0x04 que significa iconst_1
por
0x03 que significa iconst_0
Vuelvo a meterlo en el  Megablaster.jar  , inicio el juego, dejo que me
maten, y veo con satisfaccin que el nmero de vidas nunca decrece.
Ahora ya puedo jugar sin preocuparme.
Realmente el juego pierde todo el aliciente, pero mi objetivo era aprender
a hacer la modificacin, no el juego en s.

*************
Voy con otro caso.
Otro de los juegos que vienen con el mvil se llama Turrican2004 y es uno de
estos de scroll horizontal y vertical en los que un soldado va recorriendo
escenarios matando extraterrestres, con plataformas.
Los grficos son muy buenos y es entretenido. No he recorrido muchos niveles
porque es muy complicado para m. Pero ya digo que soy muy mal jugador.

Lo que me fastidia de este juego es que antes de empezar muestra durante 3
segundos una pantalla de la compaa que hizo el juego, y luego otra con el
logotipo de Siemens. Despues se para otros 2 segundos en una pantalla con
las instrucciones.
Y slo despus de esto carga el juego, lo cual lleva otros 5 segundos.
Mi objetivo es eliminar esas molestas pantallas de publicidad.
El programa Turrican2004.jar ocupa 328 Kb.
Al descomprimirlo genera 140 ficheros en
Turrican\*
La mayora tienen extensin *.ptrx y *.ptr_optb , que no s lo que contienen.
En todo caso parecen ficheros binarios.
Hay 70 ficheros con extensin *.png que contienen los grficos del programa.
Uno de los ficheros se llama
splashSIEMENS.png
que contiene la imagen de una de esas pantallas de publicidad. No ha sido
difcil encontrarlo, ?eh?

Mi primera tentativa, siguiendo la ley del mnimo esfuerzo, es borrar el
fichero o simplemente cambiarle en nombre. Esto cambir el tamao del fichero
empaquetado  Turrican2004.jar  pero en los programas para moviles el tamao
no se verifica. Bueno, se verifica si hay un fichero con el mismo nombre y
extensin  .jad
Dado que no existe  Turrican2004.jad  estoy seguro que que puedo cambiar el
tamao sin mayor preocupacin.
Lamentablemente con este cambio lo nico que obtengo es una excepcin tan grande
como un caballo que impide que el juego inicie correctamente.

Tambin hay 25 ficheros *.class en
Turrican2004\com\thq\Turrican\
que desensamblo rpidamente con
jad -a Turrican2004\com\thq\Turrican\*.class

y busco cual de ellos contiene la palabra "splashSIEMENS" :

Clase s.class
 public void b()
 {
  if(v)
   return;
  v = true;
  if(z)
   return;
  switch(s)
  {
  default:
   break;

  case 0: // '\0'
   try
   {
    v.bA = Image.createImage("/splashTHQ.png");
    v.ap = Image.createImage("/splashSIEMENS.png");
   }
   catch(Exception exception) { }
   break;
y muchas lneas ms

Esto significa que en la clase  v.class  hay un objeto  llamado  ap :
public static Image ap;
Ojo, no confundirlo con
public static int aP = -1;
Como ya he comentado antes, normalmente existen otros objetos con el mismo
nombre en otras clases:
a.class  -> int ap;
d.class  -> int ap;
o.class  -> int ap;

Desensamblo   v.class para ver dnde se usa y me encuentro con que   ap
simplemente est declarada en esta clase, pero no se usa.
O sea, que nicamente carga la imagen en la memoria; no la muestra.

Esto quiere decir que se usa desde otras clases.
As que busco dnde se usa    v.ap
Obviamente sale    s.class    pero tambin   q.class

Clase q.class
 public void a(Graphics g1, int i1)
 {
  if(v.o == 0L)
   v.o = System.currentTimeMillis();
  if(System.currentTimeMillis() - v.o <= (long)g) goto _L2; else goto _L1
_L1:
  L = true;
  if(p.a != null)
  {
   g1.setColor(0);
   g1.fillRect(0, 0, 132, 176);
   g1.drawImage(p.bC, 66, 0, 17);
   g1.drawImage(p.bs, 66, 0, 17);
   g1.drawImage(p.a, 0, 57, 20);
  } else
  {
   g1.setColor(0);
   g1.fillRect(0, 0, 132, 176);
  }
  g1.setColor(255, 255, 255);
  g1.fillRoundRect(16, 160, i1, 8, 8, 8);
  g1.setColor(75, 75, 175);
  g1.drawRoundRect(16, 160, 100, 8, 8, 8);
   goto _L3
_L2:
  if(System.currentTimeMillis() - v.o <= T ||
        System.currentTimeMillis() - v.o >= g) goto _L5; else goto _L4
_L4:
 ..............
_L12:
  Thread.yield();
  Thread.sleep(25L);
   goto _L3
_L10:
  if(System.currentTimeMillis()-v.o > ae && System.currentTimeMillis()-v.o < W)
  {
   g1.setColor(255, 255, 255);
   g1.fillRect(0, 0, 132, 176);
   if(v.ap != null)
    g1.drawImage(v.ap, 66, 88 - (v.ap.getHeight() >> 1), 17); <-******--******-
  } else
  if(System.currentTimeMillis() - v.o < (long)ae)
  {
   g1.setColor(255, 255, 255);
   g1.fillRect(0, 0, 132, 176);
   if(v.bA != null)
    g1.drawImage(v.bA, 66, 88 - (v.bA.getHeight() >> 1), 17); <-******--******-
  }
   goto _L3
  Exception exception;
  exception;
_L3:
 }


Lo que se extrae de esto es que se dibuja la imagen   v.ap   o   v.bA  en
funcin de la diferencia de tiempos entre System.currentTimeMillis() y  v.o ,
que es el tiempo calculado inicialmente cuando se entra en esta rutina.

Estos tiempos se comparan con:
T (linea _L2, a mediados de lnea)
g (linea _L2, antes de saltar a _L5) y justo antes de L1
ae (linea _L10, a mediados de lnea)
W (linea _L10, al final de la lnea)

Veo que podra poner al entrar en la rutina:
goto _L3
o tambin
return

Pero quizs esta rutina hace algo ms. En particular veo que usa p.a!=null, y
pone L=true  as que creo que lo mejor es tomar otro camino.

Las variables T, g, ae, W estn usadas en esta misma clase en el constructor q()
public q()
{
 super(false);
 N = false;
 Z = true;
 J = false;
 l = false;
 ae = 4000;
 W = 8000;
 T = 13000;
 g = 18000;
 s = 19000;
 ..........

Muy bien: todas las variables estn juntitas.
Los valores, escritos es hexadecimal, son:
 ae = 0x0FA0;
 W = 0x1F40;
 T = 0x32C8;
 g = 0x4650;
 s = 0x4A38;
En la clase   q.class   busco esos bytes y los encuentro a partir de 0x16CD

0x16CD: 11 0F A0
0x16D4: 11 1F 40
0x16DB: 11 32 C8
0x16E2: 11 46 50
0x16E9: 11 4A 38
Notar que en Java el byte ms significativo va delante.
Lo ms sencillo es cambiarlos todos a valores mas pequeos, por
ejemplo 258 = 0x0102
Parece un golpe a ciegas, pero estas cosas funcionan as, Si funciona a la 
primera, ?para qu voy a perder el tiempo?

Como antes, descompilo de nuevo la clase modificada para ver que los valores
son correctos.
Meto la clase en el Turrican.jar , lo transfiero al mvil, empiezo a jugar y
compruebo que las pantallas de presentacin ya no aparecen.
Por supuesto que sigue tardando un poco porque tiene que cargar todas las
clases del juego y los grficos, pero ahora es mucho ms rpido.

*************
En este mismo juego hay una modalidad para jugar una campaa: se empieza
por un escenario simple, y a medida que adquieres ms experiencia puedes
probar con otros escenarios.
Pero desde el comienzo no es posible acceder a los escenarios avanzados.
En el men de seleccin slo estan disponibles 4 niveles, mientras que hay
otros 20 que dice que estan bloqueados-LOCKED
Busco la palabra "LOCK" y la encuentro en la clase TurricanMidlet.jad :
public void startApp()
{
 if(c == null)
 {
  v.m = getAppProperty("MIDlet-Version");
  v.l = System.getProperty("microedition.locale");
  v.bI = getAppProperty("language_override");
  System.out.println("READ IN: " + v.bI);
  if(v.m == null)
     v.m = "V?.??";
  v.bK = getAppProperty("CHEAT_UNLOCK") != null;
  c = this;
  b = new q();
  b.setFullScreenMode(true);
  f = Display.getDisplay(this);
  f.setCurrent(b);
  e = new Thread(b);
  e.start();
  b.a();
 }

Esto es un tpico inicio de juego. Toma algunas variables del entorno, por
ejemplo para saber el idioma.

Otra de las propiedades se llama "CHEAT_UNLOCK" y debera estar en uno de
los ficheros dentro del Turrican2004.jar, posiblemente en META-INF\MANIFEST.MF
que contiene la variable "MIDlet-Version"
O quizas en Turrican2004.jad , el cual contiene otras variables tales
como "language_override"

Es decir, que los propios programadores han instalado una puerta trasera
que parece hacer algn tipo de trampa, quizs incluso
para poder acceder a los otros niveles sin necesidad de haber pasado los
anteriores. ?Y porqu no puedo usar yo la misma puerta?

La lnea
v.bK = getAppProperty("CHEAT_UNLOCK") != null;
quiere decir: si la propiedad  "CHEAT_UNLOCK"  est definida, haz    v.bK=true
Si no, haz   v.bK=false
Para seguir con el mtodo anterior, voy a ver dnde se usa la variable  v.bK :

La encuentro en q.class
public void run()
{
 n = 0;
 M.n();
 if(v.bK)
  M.a(true);
 .....
 }

O sea, que llamar al metodo a  del objeto M , pero slo si  v.bK=true
Como yo no voy a crear la propiedad "CHEAT_UNLOCK" , la solucin es cambiar
if(v.bK)
por
if(v.bK==false)
que es lo mismo que
if(!v.bK)

Desensamblando:
        if(v.bK)
    //*   4   10:getstatic       #69  <Field boolean v.bK>
    //*   5   13:ifeq            23
            M.a(true);
    //    6   16:getstatic       #18  <Field p M>
    //    7   19:iconst_1        
    //    8   20:invokevirtual   #70  <Method void p.a(boolean)>

la instruccin 
5   13:ifeq  (significa "si es igual")
la voy a sustituir por
5   13:ifne  (significa "si NO es igual")

o sea, en la posicin 0x17E0 pongo 0x9A en vez de 0x99

Transfiero el juego, accedo al men, y tengo todos los escenarios liberados !
Claro que los ms avanzados son demasiado difciles para m. Al menos he
cumplido el objetivo de modificarlo, que era lo que quera probar.

*************
Otro juego que tengo es AdamsAppleV3 hecho por la compaia SoftexDigital.
Es un juego en el que hay que mover plataformas hasta encontrar la salida.
Incluye 5 niveles pero hay que pagar para acceder a los niveles superiores.
El pago se realiza accediendo a una pgina web desde el mvil. Bueno, es el
propio telfono el que se conecta as que no hay que hacer mucho.
Con mi operador no es posible realizar estos pagos, as que sale un mensaje
al principio indicando que slo puedo jugar al modo bsico: 'Teaser' Level.
Por supuesto que como mi red no lo soporta, no puedo bajarme nuevos niveles.
Pero me gustara probar los 5 escenarios ya includos, no slo el primero.
Al menos, me gustara eliminar ese mensaje.

El fichero AdamsAppleV3.jar ocupa 62Kb y al descomprimirlo genera, entre
otros, 6 ficheros *.class en el directorio raiz.
El mensaje que se queja de que el operador no soporta el pago est en el
fichero AdamsAppleV3.class

public void startApp()
{
 try
 {
  if(q != null)
  {
  if(p)
  {
   n = true;
   i = q;
   a("Payment", "Payment not supported by the operator. You can Play
                 only 'Teaser' Level ", (byte)3);
   p = false;
  } else
  {
   a.setCurrent(q);
  }
  q.m = true;
  }
 }

As que comprueba si  p  tiene un valor o no.
Si tiene algn valor, se queja. O sea, que habra que hacer que  p  sea false.
Pero no encuentro la definicin de la variable   p   en esta clase.

En la cabecera veo que
public class AdamsAppleV3 extends b
Ah, esto quiere decir que puede estar en  b.class
Efectivamente
public b()
{
 .......
 try
  {
   D.checkOperator();
  }
 catch(SecurityException securityexception)
 {
  p = true;
 }
}
Muy bien: si hay algn fallo de permisos, entonces   p  se pone a  true.
Lo ms sencillo sera saber cuales permisos son los que faltan.
Si los programadores hubieran hecho un simple
System.out.println("Error=" + exception);
entonces yo sera capaz de saber si el problema es que la red no est
disponible, o que no tengo correcto el perfil de WAP, o que ha expirado mi
sesin. Lamentablemente no puedo modificar el programa lo suficiente como
para incluir un simple mensaje explicatorio.

Pero es fcil engaar al programa para que crea que puedo realizar pagos:
Tengo que cambiar
p = true;
por
p = false;

Desensamblando:
 {
 D.checkOperator();
 // 242 548:aload_0 
 // 243 549:getfield #10 <Field Payment D>
 // 244 552:invokevirtual #70 <Method void Payment.checkOperator()>
 }
 //* 245 555:goto 564
 catch(SecurityException securityexception)
 //* 246 558:astore_1 
 {
 p = true;
 // 247 559:aload_0 
 // 248 560:iconst_1 <-***********--******--
 // 249 561:putfield #72 <Field boolean p>
 }

esto es, cambiar 
248 560:iconst_1
por
248 560:iconst_0
o sea, en la posicin 0x1510 pongo 0x03 en vez de 0x04

Esta es una modificacin que no he podido comprobar en el emulador, ya que
ste es siempre incapaz de comunicar con la red. La excepcin no es
"SecurityException"  sino  "NotImplemented" , la cual no es interceptada
por el comando   catch.

Pero en el propio mvil funciona perfectamente y ya no se queja.

*************
En este mismo juego hay otra modificacin que me gustara hacer: el juego
consiste en mover bloques hasta que la protagonista (Eva) llega a la salida
y se encuentra con Adn.
No es tpicamente un laberinto, sino que se trata ms bien de mover los
bloques sabiamente.
Como no s la manera de colocarlos para conseguir el objetivo, decido que
es mejor manipular el programa para que no aparezcan bloques.
El mapa es de 14 columnas y 10 filas, segn veo en la pantalla del mvil.
Dado que no hay ficheros binarios que contengan los mapas, supongo que estn
dentro de las propias clases.
Tras mirarlas todas, descubro que en  d.class  hay una estructura:
public static final byte h[][][] = {
{
 {10,10,10,10,10,10,10,10,10,10,10,10,10,10 },
 { 2, 0, 0, 0, 4, 4, 1, 1, 0, 0, 0, 0, 0, 0 },
 { 1, 1, 3, 3, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
 { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 0, 0 },
 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0 },
 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
}
repetida de modo parecido 5 veces (los cuales podran ser los niveles)

Nota: los valores estn en decimal.

Bueno; no tiene 10 filas sino 8. Quizs la fila de abajo y la de arriba son
siempre iguales.
En la pantalla del juego hay 2 trofeos (corazones) en la segunda lnea.
Comparndolo con esta matriz, deduzco que se corresponden con el valor  4.
Anlogamente el valor 5, que slo aparece una vez, debe de ser un pequeo rbol.
Y el valor 6, que est en la fila 7, columna 13, debe de ser el dibujo de Adn
que est al otro lado del muro (valor 1) 
El valor 2 que aparece en la fila 2, columna 1 debe de ser el dibujo de Eva.
Para hacer que el juego sea realmente sencillo de terminar, simplemente
destruyo el muro que me impide el paso en la fila 7, columna 12, justo
antes del dato '6'.

Al llegar la hora de modificar el fichero   d.class   me llevo la sorpresa
de que los valores no estn as seguidos: 0x0A, 0x0A, 0x0A, 0x0A ... como
correspondera a una secuencia de bytes, sino que cada uno ocupa 5 bytes:
0x59 0x03 0x10 0X0A 0x54 
0x59 0x04 0x10 0X0A 0x54 
0x59 0x05 0x10 0X0A 0x54 
0x59 0x06 0x10 0X0A 0x54 
Por eso supongo que Java guarda los elementos como "objetos byte", y a cada
instancia le asigna un nmero nico.
Una prdida de espacio, desde mi humilde opinin.
No slo eso, sino que algunos nmeros ocupan menos bytes. El descompilador
hace todo el trabajo de organizarlos y yo no tengo que preocuparme.
Slo anotar cuidadosamente cules bytes deseo cambiar.

Para cambiarlo, sustituir en la posicin 0x43A7 el valor 0x04, que
significa "muro" , por 0x07 , que significa "corazn"

Como siempre: modifico la clase, la meto en AdamsAppleV3.jar , lo transfiero
al mvil, y lo pruebo.
Ahora el primer nivel es un simple paseo.

****************
Bueno, como ha quedado comprobado, modificar los programas Java para mviles
es posible con un poco de tiempo y conocimientos simples de aprender.
Si es legal, moral, o engorda, no es tarea ma juzgarlo.

*EOF*