Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Temas - Casidiablo

#1
Me da algo de nostalgia volver preparar un post para este sub foro al que tanto le tengo aprecio. Hace ya más de un año que no soy usuario activo del foro en general, pero esta es la única comunidad de la cual me siento parte, así que me complace estar por aquí de nuevo.

En este caso va un post de introducción a la programación con Android (que es básicamente programación en Java), que es básicamente una adaptación de todos las entradas que he hecho en mi página personal recientemente. Android es un sistema operativo que tiene una acogida cada vez mayor y que, según mi opinión, es el futuro del desarrollo de aplicaciones para dispositivos móviles. Así que ahí va un nuevo aporte después de tanto tiempo...

Introducción a la programación con Android

Android es un estupendo sistema operativo para dispositivos móviles basado en Linux, y que nos proporciona un completo SDK para desarrollar nuestras propias aplicaciones de una manera rápida y divertida.

En esta sección aprenderemos a instalar/configurar el SDK y el plugin para Eclipse.  Haremos el típico Hola Mundo, y explicaré un poco sobre la metodología de programación para esta plataforma. ¡Manos a la obra!

1. Instalar y configurar el SDK de android

Vamos a la página del Android SDK y descargamos la versión para nuestro sistema operativo. Yo uso Gentoo Linux, pero los pasos son prácticamente idénticos en Windows y en Mac. La última versión al escribir esta entrada es android-sdk_r06. Una vez que hayamos descargado el archivo, lo descomprimimos, entramos a la carpeta que se crea y ejecutamos (en Linux):

tools/android

En Windows:

SDK Setup.exe

Veremos algo como esto:


Hacemos clic en Available packages y desplegamos el árbol que aparece bajo Sites, Packages and Archives para instalar el API sobre la(s) que deseamos trabajar, y una vez la(s) hayamos seleccionado hacemos clic en Install Selected. En este caso he seleccionado el API 7 (para la versión 2.1 de Android), la documentación del API 7, los ejemplos del API 7 y el SDK del API 4 (para la versión 1.6 de Android). Es importante elegir las APIs adecuadas teniendo el cuenta el tipo de dispositivo para el que estamos desarrollando la aplicación. Escogí en este caso el API 4 puesto que el equipo sobre el que pruebo los programas (HTC Tattoo) viene con Android 1.6 (Donut) [más información sobre las versiones y sus codenames]. Por supuesto, si desarrollas con el API 4 tus programas tienen un 98% de probabilidades de correr sobre las versiones más recientes de Android sin modificación alguna.


Una vez haya terminado de descargar e instalar las APIs podemos crear un dispositivo virtual sobre el que probaremos nuestras aplicaciones. Hacemos clic en Virtual Devices al lado izquierdo, luego sobre el botón New... y configuramos el dispositivo:


Como puede apreciar en la imagen de arriba, debe poner un nombre al dispositivo, seleccionar el API sobre el que va a trabajar, darle un tamaño a la memoria ROM, escoger un tipo de pantalla y algunas configuraciones avanzadas que no se tratarán en este tutorial. Una vez tengamos esto, hacemos clic en Create AVD y si todo sale bien veremos algo como esto:


2. Instalar y configurar el plugin para Eclipse

Para este paso, necesitaremos Eclipse 3.5 (Galileo, recomendado) o 3.4. Abrimos eclipse, vamos a la Window -> Install New Software...


Hacemos clic en el botón Add... para añadir el repositorio de Android ( https://dl-ssl.google.com/android/eclipse/ ):


Clic en OK y ahora seleccionamos los plugins a instalar, y seguimos el proceso de instalación:


Una vez instalado, reiniciamos Eclipse y veremos que se han añadido algunos iconos extra en la barra de herramientas, y que además podemos crear proyectos para Android.

3. Hola Mundo en Android

Ahora vamos a crear un nuevo proyecto y aprender un poco más sobre cómo funcionan las aplicaciones para Android.  Hacemos clic en el botón de creación de proyectos Android (o File... -> New Project -> Android Proyect):


Veremos el asistente de creación de proyectos para Android en donde debemos especificar: el nombre del proyecto (HolaParce), el API para el que vamos a desarrollar (1.6 en este caso), el nombre de la aplicación (Hola Parce en este caso), el nombre del paquete (se recomienda que sea un paquete nombrado con el estándar de Java, es decir, un dominio invertido), seleccionamos Create Activity y le damos un nombre (que cumpla las especificaciones de un nombre de clase en Java), y por último seleccionamos la versión mínima del API que deberán tener los dispositivos que corran nuestro aplicativo:



¡Clic en Finish y listo! Ahora podemos probar la aplicación... hacemos clic derecho sobre el Proyecto, seleccionamos Run as... -> Android Application. Se cargará el emulador y después de un par de minutos podremos ver nuestra aplicación:


4. Entendiendo el funcionamiento básico de las aplicaciones en Android

Las aplicaciones en Android funcionan bajo el esquema de "Actividades". Una actividad presenta una interfaz gráfica (escrita en XML) que permite al usuario interactuar con la aplicación. Cada aplicación tiene varias actividades que se van mostrando al usuario según este las vaya necesitando. Una actividad llama a otra cuando sea necesario, y cada una de las actividades que se vayan mostrando se almacenan en una pila; es decir, cada vez que la aplicación lo requiera inserta una nueva actividad en la pila y, cuando esta ya no se necesite, se hace un push sobre esta lo cual deja en descubierto la actividad que estaba debajo. Importante leer esto para tener claro cada uno de los aspectos fundamentales de las aplicaciones Android.

Ahora, veremos detalladamente qué ocurrió en los pasos que seguimos arriba. Por ejemplo, al crear el proyecto se generan algunos archivos automáticamente. Veamos que hace cada uno de ellos...

Dentro del directorio res se han creado algunos subdirectorios:


  • drawable-hdpi, drawable-mdpi, drawable-ldpi en donde se almacenan las imágenes que va a utilizar nuestra aplicación. La diferencia entre ellas es que debemos colocar las imágenes que aparecerán según el tipo de pantalla del dispositivo. En drawable-hdpi se colocarán las imágenes para dispositivos con alta resolución (High) y en drawable-ldpi (Low) pondremos las imágenes para dispositivos con pantallas pequeñas.
  • values contiene inicialmente el archivo strings.xml, que es donde declaramos las cadenas de texto que usará nuestra aplicación. No es obligatorio definir todas las cadenas de texto allí, pero es bastante recomendable hacerlo. En este caso simplemente contiene la definición de una cadena de texto (llamada hello), que es la que se muestra al ejecutar la aplicación:
Código (xml) [Seleccionar]
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, HolaParce!</string>
<string name="app_name">Hola Parce</string>
</resources>



  • layout contiene los archivos XML que representan interfaces gráficas. Si echamos un vistazo al archivo generado (main.xml) veremos algo como esto:

Código (xml) [Seleccionar]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
</LinearLayout>



  • Los layouts son XML estrictos, así que deben comenzar con el encabezado <?xml version="1.0" encoding="utf-8"?> y todas las etiquetas abiertas deben ser debidamente cerradas.
  • Los LinearLayout representan contenedores de widgets (algo similar al JPanel de swing en Java). Es decir, es la manera de organizar cada grupo de elementos de la interfaz gráfica.
  • En este caso, dentro del contenedor solo tenemos un TextView (que sería algo así como un JLabel de swing en Java).
  • Sea cual sea el elemento que pongamos en el layout, debemos especificar su anchura (android:layout_width) y altura (android:layout_height). Para cada parámetro podemos usar el valor fill_parent o wrap_content. fill_parent hará que el widget ocupe todo el tamaño posible, mientras que wrap_content hará que ocupe el menos posible.
  • El parámetro android:text permite asignar un texto al TextView. En este caso se usa @string/hello que indica que se usará una variable llamada hello. Esta variable puede ser encontrada en el archivo strings.xml dentro del directorio values. También podríamos especificar el texto directamente, por ejemplo: android:text="Hola parcero!"

  • Como tal vez se dio cuenta, es posible editar los archivos XML gráficamente o con el editor de textos de Eclipse.

    Dentro del directorio gen se encuentra un archivo llamado R.java. Este archivo NO debemos modificarlo ya que es Eclipse quien se encarga de poner el código allí dentro. Este archivo sirve básicamente para enlazar las cosas que hagamos en XML con la programación en Java. Por ejemplo, se crea una referencia a la variable hello creada en el archivo strings.xml. Esto permite que podamos referenciar dicha variable desde Java (esto se explica con más detalle abajo).

    Bajo el directorio src se creó un paquete y dentro de él un archivo en Java que es nuestra primera actividad (fíjese cómo la clase creada extiende la clase Activity del paquete android.app):

Código (java) [Seleccionar]
package net.casidiablo.holaparce;
import android.app.Activity;
import android.os.Bundle;
public class HolaParce extends Activity {
/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}


Veamos en detalle cada línea:


  • Línea 1 define el nombre del paquete.
  • Líneas 2 y 3 importamos las clases que necesitamos para correr la actividad.
  • En la línea 4 podemos ver que la clase exitiende a Activity.
  • En la línea 7 redefinimos el método onCreate de la clase Activity, el cual es ejecutado al momento de iniciar la aplicación. Note que no es necesario tener un método main; en Android se define una actividad principal que será ejecutada al iniciar la aplicación (más adelante veremos donde se configura esto).
  • En la línea 9 se usa el método setContentView que define cual de las interfaces gráficas creadas en el directorio layout serán usadas. Como parámetro usamos la variable R.layout.main. Esto es algo confuso al principio así que lea atentamente: R, como vimos anteriormente, es una clase generada por Eclipse automáticamente cada vez que creamos nuevos componentes para la aplicación; dentro de ella se crean clases estáticas con variables enteras que representan cada uno de estos componentes (main.xml es entonces una variable entera llamada main, dentro de la clase estática layout, que a su vez se encuentra dentro de la clase R.java). Por ejemplo, para usar la variable hello desde Java, tendríamos que usar una referencia de tipo R.values.hello.

Por último, tenemos el archivo AndroidManifest.xml. Todas las aplicaciones deben tener este archivo y no debe ser renombrado. En él se especifican las opciones generales del programa, como el paquete principal, la actividad que deberá ejecutarse al iniciar la aplicación (y deben incluirse allí TODAS las actividades que se van usar), el icono a usar, los permisos, etc.

Código (xml) [Seleccionar]
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.casidiablo.holaparce"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".HolaParce"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="4" />
</manifest>


5. Operaciones avanzadas: acceder al dispositivo por consola y obtener una shell

Como sabemos, Android está basado en Linux, y como tal posee una interfaz de linea de comandos que podemos acceder usando las herramientas del sdk. Esto lo podemos hacer tanto para dispositivos virtuales, como el de este ejemplo, como para dispositivos reales. En este caso lo haremos con el dispositivo virtual que creamos para el ejemplo. Es tan sencillo como ejecutar esto en consola (en Linux):

tools/adb -s emulator5554 shell

Lo que hacemos con el comando anterior es indicarle al adb que queremos abrir una shell del dispositivo con serial emulator-5554. Para ver los dispositivos conectados actualmente y sus seriales usamos el comando adb devices. Si todo va bien veríamos algo como esto:

funtoo@larry tools % ./adb -s emulator-5554 shell
# ls
sqlite_stmt_journals
cache
sdcard
etc
system
sys
sbin
proc
init.rc
init.goldfish.rc
init
default.prop
data
root
dev


Desde dicha shell podemos hacer bastantes cosas, pero la más interesante para mi, es poder usar el SQLite3 para acceder a las bases de datos de las aplicaciones que creemos, lo cual nos permite una depuración mucho más rápida.

Depuración de aplicaciones en Android

Siguiendo con la serie de entradas sobre Android, aprenderemos a depurar de una manera sencilla las aplicaciones que escribamos. Muchas veces, al ejecutar la aplicación obtenemos un mensaje de este tipo:


Cuando estamos desarrollando aplicaciones normales en Java, usualmente imprimimos mensajes en consola que contienen la información de las excepciones que capturamos, y que nos permiten detectar los errores. En Android tendremos hacer uso de la clase Log, que genera logs  (¡capitán obvio al rescate!).

Su uso es bastante simple. Como ejemplo usemos este programa que arrojaría un famoso NullPointerException:

Código (java) [Seleccionar]
package net.casidiablo.ejemplo;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class EjemploInvertir extends Activity {
@Override
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.interfaz_grafica);
String x = null;
try {
x.length();
} catch (Exception e) {
Log.d("Al inicio", "El error es: "+e.toString());
}
}
}


En este caso se usó el método d de la clase Log, el cual genera mensajes de tipo DEBUG. Existen otros como v, para VERBOSE, e para ERROR, etc. La lista completa la encuentras en el API de la clase.

Para leer el registro de errores desde Eclipse vamos a Window -> Show view -> Other... Dentro del cuadro de diálogo que se abre seleccionamos Android -> Logcat:


Espero que les sea de ayuda. No duden en comentar sus dudas o sugerencias.
#2
Hola a todos... creo que nunca había posteado en esta sección, así que espero hacerlo bien.

La cosa es la siguiente. Estoy estudiando acerca de las vulnerabilidades de las claves WEP, por lo que estoy jugando con mi AP.

Lo que he podido hacer

Si pongo mi tarjeta en modo monitor, y capturo paquetes con el airodump-ng mientras esté usando la red con otro equipo (descargando un archivo pesado), se generan los suficientes IVs como para descifrar la clave WEP. Esto no tiene ningún misterio, y ni siquiera necesito la inyección.

Para el siguiente ejercicio, quería intentar obtener la clave mientras la red no estuviera en uso, o tuviera muy poco. Para ello, fue necesario recompilar los drivers de mi tarjeta siguiendo estos  pasos:

http://casidiablo.net/compilar-drivers-iwlagn-inyeccion-trafico-cracking-wep/

para habilitar la inyección de paquetes. Y aquí vienen los problemas...

Lo que NO he podido hacer

Pongo la tarjeta en modo monitor, y luego abro una sesión con el airodump para capturar los paquetes. Luego hago un test de inyección, y todo parece funcionar:



Pero cuando deseo hacer un fake authentication (aireplay-ng -1 0 -e NUMICOM -a XXXXXXXXXX -h 00:21:5c:06:35:73 wlan0), me aparece el típico error:

Attack was unsuccessful. Possible reasons:

    * Perhaps MAC address filtering is enabled.
    * Check that the BSSID (-a option) is correct.
    * Try to change the number of packets (-o option).
    * The driver/card doesn't support injection.
    * This attack sometimes fails against some APs.
    * The card is not on the same channel as the AP.
    * You're too far from the AP. Get closer, or lower
      the transmit rate.


Veamos...

    * Perhaps MAC address filtering is enabled. Es mi AP, y la configuración es esta:



    * Check that the BSSID (-a option) is correct. El BSSID es correcto
    * Try to change the number of packets (-o option). ???
    * The driver/card doesn't support injection. los tests dicen que sí.
    * This attack sometimes fails against some APs. le intenté con otro, y lo mismo.
    * The card is not on the same channel as the AP. están en el canal 6. El router lo tengo en el canal 6 y la tarjeta también (2.437 GHz).
    * You're too far from the AP. Get closer, or lower the transmit rate. Está en el cuarto de al lado.

¿Alguien podría decirme qué más puedo hacer? He intentado además Des-autenticar a uno de los clientes conectados. Según la teoría, el cliente debería desconectarse y en la reconexión le capturo los IVs. Pero no :P no captura nada, y encima de todo el cliente ya no se puede conectar normalmente; me toca reiniciar el AP y luego de ello el cliente puede volver a conectarse.

El caso es que intenté no venir a pedir ayuda, pero dado que llevo dos días y no he podido, pues me rindo.

Un saludo, y gracias por leer.

Datos adicionales

Uso Gentoo Linux con kernel 2.6.27. Los drivers son los últimos (compat-wireless-2009-01-12), y le aplique correctamente los parches para habilitar la inyección. Mi AP es un Linksys WRT54GS. La versión del aircrack es 1.0 rc1. Al ejecutar lsmod:

Module                  Size  Used by
iwlagn                 71820  0
iwlcore                84480  1 iwlagn
mac80211              162608  2 iwlagn,iwlcore
cfg80211               39088  3 iwlagn,iwlcore,mac80211


El lspci de mi tarjeta:

02:00.0 Network controller: Intel Corporation Device 4229 (rev 61)
Subsystem: Intel Corporation Device 1100
Flags: bus master, fast devsel, latency 0, IRQ 377
Memory at f4000000 (64-bit, non-prefetchable) [size=8K]
Capabilities: [c8] Power Management version 3
Capabilities: [d0] Message Signalled Interrupts: Mask- 64bit+ Queue=0/0 Enable+
Capabilities: [e0] Express Endpoint, MSI 00
Capabilities: [100] Advanced Error Reporting <?>
Capabilities: [140] Device Serial Number 73-35-06-ff-ff-5c-21-00
Kernel driver in use: iwlagn
Kernel modules: iwlagn
#4
Java / MOVIDO: mi primera ves
1 Agosto 2008, 23:46 PM
#5
PHP / Cómo crear permalinks agradables
28 Junio 2008, 00:23 AM
Umm... esto lo escribí ya hace un rato, pero que más da (además que hace mucho que no aporto nada al foro). La idea de este artículo es mostrar un sencillo ejemplo de cómo hacer que los links de nuestras aplicaciones web sean "bonitos". De tal manera no tendríamos links como estos:

http://www.sitio.com/index.php?accion=consultar&objetivo=personas

Sino algo estéticamente más agradable como:

http://www.sitio.com/personas/

¿Qué necesito?

Es necesario tener en cuenta los prerrequisitos para poder hacer esto. Para este ejemplo voy a suponer que la aplicación la estás haciendo sobre el servidor Apache, y que estás programando en PHP+MySQL. Necesitas:


  • Manejar la mayor parte del trabajo con el archivo index.php. Esto más que un requisito es un consejo. Cuando estés desarrollando aplicaciones en PHP es recomendable que la mayor parte del sistema tenga que ser procesado inicialmente por este archivo, el cual se encargará de manejar todas las peticiones y utilizar los módulos que se necesiten. Esto, por supuesto, NO quiere decir que TODO el código vaya dentro del archivo index.php; una buena práctica es separar el código en módulos y llamarlos con funciones como include o require.
  • Es necesario tener instalado el mod_rewrite, el cual se utilizará desde un archivo .htaccess. El ModRewrite es un módulo para Apache que por lo general se configura (definir reglas) en el archivo httpd.conf, pero es posible poner una configuración ModRewrite en cualquier directorio de nuestro servidor web dentro del archivo .htaccess.
  • Puesto que de acuerdo al string que pasemos en la URL se debe determinar qué hacer, es necesario hacer algo de esto:

    • Hacer que dentro de la base de datos la llave primaria de la tabla a consultar sea una cadena de texto, ó
    • Hacer otro campo en la tabla de MySQL aparte de la llave primaria

Ejemplo
Para nuestro ejemplo necesitamos un servidor Apache con ModRewrite, PHP y MySQL. Lo primero es crear la base de datos, así:

Código (sql) [Seleccionar]
create database ejemplo;
create table contenidos(
id int(5) primary key auto_increment,
titulo varchar(50),
contenido varchar(1000),
slug varchar(50));


Luego creamos una carpeta dentro del htdocs de apache, en donde pondremos los archivos de nuestro ejempo (mkdir /opt/lampp/htdocs/ejemplo). Hecho esto, lo siguiente es crear el archivo .htaccess, en el cual indicaremos las reglas del ModRewrite. En nuestro ejemplo tenemos algo como esto:

Código (apache) [Seleccionar]
# Esto es un comentario
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /ejemplo/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /ejemplo/index.php [L]
</IfModule>


Una explicación breve de este .htaccess:


  • En los archivos .htaccess es posible hacer comentarios anteponiendo el simbolo numeral (almohadilla como dicen en España)
  • <IfModule mod_rewrite.c>: Esta instrucción funciona como un if, que verifica si el ModRewrite está instalado.
  • RewriteEngine On, activa el ModRewrite.
  • RewriteBase /ejemplo/, asigna el directorio base donde trabajará el ModRewrite
  • RewriteCond %{REQUEST_FILENAME} !-f y RewriteCond %{REQUEST_FILENAME} !-d, la instrucción RewriteCond funciona como una condición que en caso de ser verdadera hará que se ejecute una regla (RewriteRule) del ModRewrite. Funciona con expresiones regulares. En este caso lo que estamos verificando es si la petición se trata de un archivo (-f) o directorio (-d) que no (!) existe, en cuyo caso ejecuta la RewriteRule de abajo. Pero ¿para qué esto? Dado que las peticiones que hacemos usando URL bonitas no existen físicamente en el servidor, podemos aprovecharlas para indicar que dichas URL las manejará el archivo index.php, es decir, si por ejemplo hacemos una consulta como:
    http://www.sitio.com/link-agradable
    y en dicho servidor no existe ninguna carpeta o archivo que tenga el nombre link-agradable, el control de dicha petición se enviará al archivo index.php.
  • RewriteRule . /ejemplo/index.php [L], ejecuta la regla que en este caso hace que el control de la aplicacion pase al archivo index.php, el cual se encargará de analizar la URL y realizar las operaciones adecuadas. La instrucción [L] hace que cualquier otra regla por debajo de esa linea no se cumpla.
  • </IfModule>, cerramos nuestro if.
Vamos ahora con nuestro archivo index.php:

Código (php) [Seleccionar]
<?php
   
//URL base de la aplicacion
   
$base "http://localhost/ejemplo/";
   
//Crear la conexion a la base de datos
   
$conexion mysql_connect("localhost""root""");
   
mysql_select_db("ejemplo"$conexion);
   
//Si se requiere unicamente el index
   
if(("http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']) == $base ||
      
basename($_SERVER['REQUEST_URI']) == "index.php")
      
$contenido "Lo que vaya en el index por defecto";
   else {
      
$id $_GET["id"];
      
//Si es una URL fea-asquerosa...
      
if(!empty($id))
         
$consulta mysql_query("SELECT contenido FROM contenidos WHERE id = $id"$conexion);
      
//Si es una URL bonita...
      
else
      {
         
//Obtener el nombre clave
         
$slug basename($_SERVER['REQUEST_URI']);
         
$consulta mysql_query("SELECT contenido FROM contenidos WHERE slug = '$slug'"$conexion);
      }
      
//Si la consulta es correcta...
      
if(mysql_num_rows($consulta) > 0)
         
$contenido mysql_result($consulta00);
      
//Informar del terrible error
      
else
         
$contenido "Lo que est&aacute;s buscando no existe :P ";
   }
?>

<html>
<head><title>Un ejemplo</title></head>
<body><?php echo $contenido ?></body>
</html>



       
  • Línea 3: es recomendable para este tipo de aplicaciones (y para casi todas en general), que tengamos una URL fija definida para nuestra aplicación. En este caso almacenamos el string  http://localhost/ejemplo/ en la variable  $base.
  • En las líneas 5 y 6 creamos la conexión a la base de datos.
  • En el if de la línea 8 verificamos si la petición HTTP es para la raiz de nuestro proyecto (llamar simplement al index.php), de lo contrario...
  • En las líneas 12 y 14 verificamos si se trata de una petición GET normal, en la que pasamos pares variable-valor dentro de la URL. En cuyo caso se realiza una consulta a la base de datos tomando en cuenta las variables GET (línea 15).
  • Si la peticion está formada como una URL bonita, creamos una variable llamada $slug que contiene el nombre base de la URI (línea 20), es decir, si la peticion es http://www.sitio.com/link-agradable, el nombre base de la URI es link-agradable. Posteriormente, en la línea 21 hacemos una consulta en la base de datos buscando un registro que contenga dicho slug.
  • En la línea 24 verificamos si la consulta ejecutada anteriormente contiene registros, en cuyo caso pone el contenido en la variable $contenido. Sino, se mete en esa variable un mensaje que dice que no se encontró el registro.

Hecho esto, nuestra aplicación tendrá el siguiente comportamiento:

La aplicación por defecto:



Una consulta a la antigua (URL fea):



Una consulta estéticamente más bonita:



Cuando no encuentra un registro:



Enlaces

P.d. El código es SOLO de ejemplo. Si hacen algo muy parecido podría ser vulnerable, por ejemplo, a inyecciones SQL. En sus aplicaciones tengan cuidado con eso.
P.d. Sobra decir que pueden hacer lo que quieran con el mini-tutorial (copiar, modificar, etc.) con o sin ánimo de lucro. Siempre y cuando se referencie la fuente ;)
#6
Juegos y Consolas / Como se llama este juego?
28 Mayo 2008, 23:34 PM
Hola...

Quisiera "jugar un jueguito" que jugaba en la infancia (en mi Family), por cosas de nostalgia y eso, pero no recuerdo su nombre. Podría alguien ayudarme?

La descripcion del juego es:

* Es de esos que el control era cuadrado, y solo tenia los botones A, B, y direccionales (lo digo mas que todo para que recuerden lo viejo que es)
* Uno es un soldadito con una pinche pistolita
* Los graficos no son buenos... bueno, para la epoca eran buenos XD
* El soldadito se podia montar en tanques y disparar y matar y hasta el putas
* Veias todo el terreno y todo el cuerpo del muñequito mientras ibas caminando (generalmente hacia arriba). La "camara" era como si estuvieras viendo desde el cielo.

Y pues no recuerdo mas... Alguien lo recuerda?
#8
Java / MOVIDO: Ayuda con el spoiler
17 Enero 2008, 15:18 PM
Java != javascript. El tema ha sido movido a Dudas Webmasters.

http://foro.elhacker.net/index.php?topic=196119.0
#9
Hola a todos...

Tengo un sistema de información hecho en MySQL y accesado desde PHP. La cosa es que me gustaría que cuando se cumpliese una condición en la base de datos, (específicamente, cuando una fecha sea igual a X), se enviára automáticamente un correo a cierta persona.

La cosa es que no tengo idea de que hacer... alguna vez leí acerca de los Triggers, pero no se si sirvan en este caso. También prodría hacer alguna aplicación a parte (ya no a nivel web, sino de escritorio) que consultara la base de datos una vez al día y se fijara si la condición se cumple o no...

Pero no sé cual es la mejor opción. Según sus experiencias ¿qué debería hacer? Lo otro es que la base de datos no se va a estar actualizando muy seguido, sino cada mes, por mucho.

Un saludo!
Y gracias por leer!
#10
La verdad no tengo ni idea de diseño gráfico, ni el uso de herramientas para la edición de imágenes. El caso es que tengo algunas imagenes en formato GIF y PNG, y me gustaría saber cómo puedo reducir el peso de las imágenes, sin afectar mucho su calidad.

Como uso Gnu/Linux solo cuento con el Gimp y con Inskape para editar las imágenes. ¿Alguien puede darme una mano?

Gracias.
#11
Me pregunta mi hermano que, cómo le puede poner música propia al Need for Speed - UnderGround 2?

Es decir, que cuando este conduciendo y tal suene algun mp3 que le indiquemos y no las emisoras que trae.

Nada solo eso... y no he pillado nada en el Google.

Un saludo!
#12
Hola...

Me gustaría que alguien me aclarara el siguiente error que me saca un programa que estoy haciendo en PHP:

Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at C:\xampp\htdocs\manuel\index.php:1) in C:\xampp\htdocs\manuel\index.php on line 3

Cierto es que si buscas en Google encuentras cientas de páginas donde ya se ha tratado el tema. Incluso aquí mismo se ha tratado... pero antes de que digan cualquier cosa, me gustaría que se fijen en el código que tengo:

El archivo es index.php, y solo tiene:

Código (php) [Seleccionar]
<?php
session_name("inmobiliaria");
session_start();
include("funciones.php");
?>


Ahí me saca el error. Lo más HIJUEPUTA de todo (perdonen la expresión pero estoy demasiado molesto), es que tengo otro archivo con lo mismo, y no arroja el error:

El otro archivo es temp.php y tiene lo mismo:

Código (php) [Seleccionar]
<?php
session_name("inmobiliaria");
session_start();
include("funciones.php");
?>


Ahora me pregunto... ¿cómo putas es posible que si son iguales los archivos, en uno saque error y en el otro no?

Gracias por leer.
#13
Juegos y Consolas / ¿Cómo se llama este juego?
11 Octubre 2007, 21:14 PM
Haber... la cosa es que necesito encontrar un juego que jugué (valga la redundancia) cuando era pequeño. Lo jugaba en esas máquinitas tipo NEO-GEO. De seguro alguno de ustedes lo ha jugado alguna vez... paso a explicarles lo que recuerda mi mente borrosa:


  • Era en máquinas tipo NEO-GEO, de esas que les echas moneda y hasta que te maten tienes que volver a echar.
  • Era de ese tipo de juegos en los que uno puede mover los personajes hacia adelante, atrás, arriba, abajo.
  • ¿Recuerdan un juego en el que uno iba avanzando y tenía que pegarles a unos "malechores" y a veces a unos dinosaurios? Pues ese no es, pero es uno parecido.
  • Solo se podían escoger 2 personajes (hombres). Uno de ellos se parece a un personaje que aparece en el juego de Spiderman I, de Play Station. Ese personaje tiene un traje negro, señido al cuerpo, y con una cadavera dibujada en el pecho.
  • Uno avanzaba con los personajes, le pegaba a los "malos", podía coger armas (palos, botellas, un lanza llamas, etc.), cogía sangre (por lo genreal eran pollos asados en el suelo).
  • Recuerdo que en el último nivel, aparecía un gordo enorme de traje blanco.
  • Además, al presionar tres o cuatro botones al mismo tiempo, el presonaje hacía una jugada especial (girando), pegándole a los que estuvieran a su al rededor (pero creo que quitaba sangre).

Nada, solo recuerdo eso. Si alguien me puede decir como se llama, se lo agradecería mucho.

Un saludo!
#14
Hola a todos,

Les comento mi problema... tengo el siguiente código fuente, que me sirve para capturar el código una página web en un archivo de texto:

Código (php) [Seleccionar]
<?php
$url
=$HTTP_GET_VARS["u"];
if(
$url!=null)
{
$url=ereg_replace("aquivaunputoampersand""&"$url);
$ch curl_init();
$fp fopen ("archivo.txt""w");
curl_setopt($chCURLOPT_URL$url);
curl_setopt ($chCURLOPT_FILE$fp);
curl_setopt ($chCURLOPT_HEADER0);
curl_exec ($ch);
curl_close ($ch);
fclose ($fp);
$gestor = @fopen("archivo.txt""r");
if (
$gestor) {
    while (!
feof($gestor)) {
        
$bufer .= fgets($gestor4096);
    }
    
fclose ($gestor);
}
}
?>


Se usa de la siguiente forma, por ejemplo:

http://www.pagina.com/programa.php?u=http://www.google.com.co

El programa funciona bien con páginas simples (como en el ejemplo anterior), pero en páginas que hagan una redirección no es posible obtener el código fuente , como por ejemplo en esta:

Código (php) [Seleccionar]
<?
header('Location: http://www.google.com.co');
?>


¿existe alguna manera de obtener el código fuente de la página? Obvianmente no el código fuente de esa página, sino de la página a la cual es redireccionada.

Un saludo!!!
#15
Umm, estoy intentando hacer unas operaciones con javascript, y resulta que al intentar esto:

javascript:if(!window.ActiveXObject){ActiveXObject=XMLHttpRequest;}var cxx=new ActiveXObject("Microsoft.XMLHTTP");cxx.open('GET',"http://www.google.com",false);var a=cxx.responseText;

Me sale este error:

Error: uncaught exception: Permiso denegado al llamar al método XMLHttpRequest.open

Solo me funciona si lo hago con servidores locales, pero con servidores externos no.

@Sdc: Me basé en aquel proyecto que hizo un mono (el que murió con el rayo)...
#16
Cómo crear interfaces gráficas con Look And Feel en Java

Java posee una API (Interfaz para porgramación de Aplicaciones) que es la encargada de manipular las interfaces gráficas hechas con Swing. Esta nos permite crear GUI's realmente bonitas. Pero primero necesitamos tener unos conceptos claros, como por ejemplo que es Swing y eso del Java look and feel (llamado a veces "Metal").

Los componentes de Swing están escritos en Java, sin ningún código de especificación de ventanas. Esto facilita la creación de interfaces gráficas sin tomar en cuenta el sistema de graficación de ventanas donde se trabaje, y simplificando el desarrollo de aplicaciones. Swing además soporta una arquitectura de visualización (Look And Feel). Ésta caracterí­stica dota a los usuarios con la habilidad de cambiar la apariencia de una aplicación sin reiniciarla y sin que el desarrollador se tenga que cambiar por completo su conjunto de subclases.

Java Look And Feel (de ahora en adelante J&F) es un API multiplataforma proporcionada por JavaSoft. Voy a ser breve, así­ que si necesitas información especí­fica puedes buscar en san google.
Java L&F implementa todas las funcionalidades básicas de Swing, pero tambén se extiende en otras áreas incluyendo:

  • Temas
  • Sliders (barras de selección de rangos)
  • Toolbars (Barras de herramientas)
  • Trees (arboles de contenido)
Ahora, y para ver de que estamos hablando vamos a tomar como ejemplo un programa hecho por los maestros del L&F: Michael Albers, Tom Santos, Jeff Shapiro y Steve Wilson.

El programa lo puedes encontrar en los demos que se encuentran en los JSDK. Vas a donde tienes instalado el SDK de Java y buscas la carpeta demo/jfc/Metalworks, allí­ encontrarás la aplicación que vamos a tomar como objeto de ejemplo.

Para ejecutar el programa que ya está compilado (Metalworks.jar), digitas desde una shell:

java -jar Metalworks.jar

Y lo que veras es un programa como este (ten en cuenta que según tu versión del SDK el programa puede cambiar o no estar; yo utilizo el J2SDK 1.5):


Como puedes observar es una interfaz gráfica realmente bonita y llamativa. Aunque es la que viene por defecto con el L&F en su versión 5. Puedes jugar con este programita que te dará más de una sorpresa agradable. Por ejemplo vas al menú Theme y seleccionas el que quieras, veras cosas como estas:



La interfaz de usuario cambia de aspecto sin necesidad de recompilar o reiniciar la aplicación, es decir, cambia en tiempo de ejecución. Pero lo que nosotros queremos es saber como hacer esto, veámos:


Creando un JFrame con el Look And Feel activado

Esto es muy sencillo de hacer. Lo único que tenemos que hacer es activar el Look And Feel, pasando true como parámetro al método estático setDefaultLookAndFeelDecorated de JFrame y de JDialog. Por ej.:

//Ejemplo1Look .java
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Ejemplo1Look extends JFrame
{
   public Ejemplo1Look()
   {
      super("Ejemplo 1");
      JButton boton = new JButton("Mostrar dialogo");
      boton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
               JOptionPane.showMessageDialog(null,
               "Y así­ se ve un cuadro de dialogo de error",
               "Mensaje",JOptionPane.ERROR_MESSAGE);
            }
         }
      );
      getContentPane().add(new JLabel("Asi se ve un Frame"),
         BorderLayout.NORTH);
      getContentPane().add(boton);
      setSize(200,80);
      setVisible(true);
   }
   public static void main(String args[])
   {
      JFrame.setDefaultLookAndFeelDecorated(true);
      JDialog.setDefaultLookAndFeelDecorated(true);
      Ejemplo1Look ventana = new Ejemplo1Look();
      ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }
}



Este programa tiene la siguiente salida:



Creando estilos visuales a partir de archivos de texto plano

Este es uno de los tantos métodos para crear estilos o temas y consiste en crear un archivo de texto plano, que contendrá la configuración de visualización. Un ejemplo sencillo puede ser este:

#Aquí­ puedes colocar comentarios
name=Payaso
primary1=200,0,66
primary2=0,0,255
primary3=0,255,0
secondary1=255,255,0
secondary2=0,255,255
secondary3=255,0,255
black=255,255,200
white=25,80,150


Puedes usar comentarios para documentar el tema; estos deben comenzar con el sí­mbolo numeral (#). Y la sintaxis del tema es nombreEtiqueta=valor. Vamos a ver que significa cada etiqueta:

name=Payaso indica que el tema se llama Payaso.
primary1=200,0,66 es el color del borde externo
primary2=0,0,255 es el color del borde interno y el foco
primary3=0,255,0 es el color de la barra de titulo
secondary1=255,255,0 color del borde de los botones, labels, etc
secondary2=0,255,255 color de los botones al estar presionados
secondary3=255,0,255 color de fondo de los botones, labels, etc
black=255,255,200 color de las letras sobre las cajas de texto, etc
white=25,80,150 color del fondo de las cajas de texto, areas, etc

El programa que utiliza este archivo de estilo es:

//Ejemplo2Look .java
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.io.*;
import javax.swing.plaf.metal.*;
public class Ejemplo2Look extends JFrame
{
   public Ejemplo2Look()
   {
      super("Ejemplo 2");
      JButton boton = new JButton("Cargar tema");
      boton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
               cargarTema();
            }
         }
      );
      getContentPane().add(boton);
      getContentPane().add(new JLabel("Así­ se ven las labels"), BorderLayout.NORTH);
      getContentPane().add(new JTextField("Y así­ las cajas de texto"), BorderLayout.SOUTH);
      getContentPane().add(new JScrollPane(new JTextArea("Area de texto")), BorderLayout.WEST);
      getContentPane().add(new JSlider(SwingConstants.VERTICAL, 0, 200, 10 ),  BorderLayout.EAST);
      setSize(400,200);
      UIManager.addPropertyChangeListener(new UISwitchListener((JComponent)getRootPane()));
      setVisible(true);
   }
   public void cargarTema()
   {
      MetalTheme miTema = null;
      try{
         InputStream flujoEntrada = getClass().getResourceAsStream("Tema.theme");
         miTema =  new PropertiesMetalTheme(flujoEntrada);
      }catch(NullPointerException npe) {System.out.println(npe);}
      MetalLookAndFeel.setCurrentTheme(miTema);
      try{
         UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
      }catch (Exception ex){
         System.out.println("Falló la carga del tema");
         System.out.println(ex);
      }
   }
   public static void main(String args[])
   {
      UIManager.put("swing.boldMetal", Boolean.FALSE);
      JFrame.setDefaultLookAndFeelDecorated(true);
      JDialog.setDefaultLookAndFeelDecorated(true);
      Toolkit.getDefaultToolkit().setDynamicLayout(true);
      System.setProperty("sun.awt.noerasebackground","true");
      try{
         UIManager.setLookAndFeel(new MetalLookAndFeel());
      }catch ( UnsupportedLookAndFeelException e ){
         System.out.println ("Metal Look & Feel no es soportada en esta plataforma");
         System.exit(0);
      }
      Ejemplo2Look ventana = new Ejemplo2Look();
      ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }
}


Esta es la salida del programa, y sí­, ya se que es horrible, pero es la única forma de mostrar bien para que es cada etiqueta:


Ahora, antes que se me olvide, tengo que aclarar algo. Para que el programa funcione perfectamente tenemos que usar dos programas creados por el maestro Steve Wilson: PropertiesMetalTheme.java y UISwitchListener.java.

PropertiesMetalTheme, es una clase que crea un flujo hacia el archivo de texto que contenga la configuración del tema, y carga las propiedades que se encuentren allí­. No voy a explicar en detalle el funcionamiento de esta clase ya que eso está fuera de los lí­mites de este artí­culo, y además es muy fácil de comprender.

UISwitchListener, es una clase que permite cambiar la interfaz de usuario en tiempo de ejecución, sin problemas inesperados.


Creando estilos visuales simples a partir de clases

Bueno, ahora vamos a ver una manera de crear estilos visuales a partir de un programa (una clase) hecho en Java. El primer programa que vamos a tomar como ejemplo es EstiloHalloween.java:

//Ejemplo simple de tema en clase
//EstiloHalloween .java
import javax.swing.plaf.*;
import javax.swing.plaf.metal.*;
import javax.swing.*;
public class EstiloHalloween extends DefaultMetalTheme
{
   public String getName() { return "Halloween"; }
   
   private final ColorUIResource primary1 = new ColorUIResource(204, 102, 0);
   private final ColorUIResource primary2 = new ColorUIResource(255, 0, 0);
   private final ColorUIResource primary3 = new ColorUIResource(255, 204,102);
   
   protected ColorUIResource getPrimary1() { return primary1; }
   protected ColorUIResource getPrimary2() { return primary2; }
   protected ColorUIResource getPrimary3() { return primary3; }
}


Como ven todo es muy fácil; simplemente declaramos una clase que herede de DefaultMetalTheme, y creamos tres objetos de la clase ColorUIResource que sean privados (private) y constantes (final). Cada uno vá a simbolizar un color para la interfaz de usuario. Si no comprendes bien es porque no has leí­do lo de primary1, primary2, etc. allí­ arriba. Los objetos ColorUIResource los inicializamos con tres números separados por comas que representan un color en formato RGB.
Por último declaramos tres métodos protected que retornen el valor de los  objetos ColorUIResource.

El programa que utiliza la clase EstiloHalloween es:

// Ejemplo3Look .java
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.plaf.metal.*;
public class Ejemplo3Look extends JFrame
{
   public Ejemplo3Look()
   {
      super("Ejemplo 3 - Halloween");
      JButton boton = new JButton("Mostrar dialogo");
      boton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
               JOptionPane.showMessageDialog(null,
               "Y así­­ se ve un cuadro de dialogo de alerta",
               "Mensaje",JOptionPane.WARNING_MESSAGE);
            }
         }
      );
      getContentPane().add(new JLabel("Asi se ve un Frame"), BorderLayout.NORTH);
      getContentPane().add(boton);
      setSize(200,80);
      setVisible(true);
   }
   public static void main(String args[])
   {
      MetalLookAndFeel.setCurrentTheme(new EstiloHalloween());
      try{
         UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
      } catch (Exception ex) {
         System.out.println("Falló la carga del tema");
         System.out.println(ex);
      }
      JFrame.setDefaultLookAndFeelDecorated(true);
      JDialog.setDefaultLookAndFeelDecorated(true);
      Ejemplo3Look ventana = new Ejemplo3Look();
      ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }
}


Como puedes ver estamos utilizando únicamente los tres colores primarios para interfaces gráficas (primary1, primary2 y primary3). La salida del programa es:


Pero ahora vamos a ver un programa que utiliza todas las combinaciones de colores; la clase es EstiloHalloween2:

// EstiloHalloween2.java
import javax.swing.plaf.*;
import javax.swing.plaf.metal.*;
import javax.swing.*;
public class EstiloHalloween2 extends DefaultMetalTheme
{
   public String getName() { return "Halloween"; }
   
   private final ColorUIResource primary1 = new ColorUIResource(204, 102, 0);
   private final ColorUIResource primary2 = new ColorUIResource(255, 0, 0);
   private final ColorUIResource primary3 = new ColorUIResource(255, 204, 102);

   private final ColorUIResource secondary1 = new ColorUIResource( 111,  111,  111);
   private final ColorUIResource secondary2 = new ColorUIResource(255, 204, 102);
   private final ColorUIResource secondary3 = new ColorUIResource(204, 102, 0);

   private final ColorUIResource black = new ColorUIResource(255, 255, 255);
   private final ColorUIResource white = new ColorUIResource(0, 0, 0);

   protected ColorUIResource getPrimary1() { return primary1; }
   protected ColorUIResource getPrimary2() { return primary2; }
   protected ColorUIResource getPrimary3() { return primary3; }

   protected ColorUIResource getSecondary1() { return secondary1; }
   protected ColorUIResource getSecondary2() { return secondary2; }
   protected ColorUIResource getSecondary3() { return secondary3; }
   
   protected ColorUIResource getBlack() { return black; }
   protected ColorUIResource getWhite() { return white; }
}


No explico esta clase ya que tiene la misma escencia de la primera, solo que, aparte de utilizar primary1, primary2 y primary3, utiliza secondary1, secondary2 y secondary3, y el color de fondo de las cajas de texto (white) y de las letras (black).

La aplicación que utiliza la clase EstiloHalloween2 es esta:

// Ejemplo4Look .java
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.io.*;
import javax.swing.plaf.metal.*;
public class Ejemplo4Look extends JFrame
{
   public Ejemplo4Look()
   {
      super("Ejemplo 4 - Halloween");
      getContentPane().add(new JButton("Los botones XD"));
      getContentPane().add(new JLabel("Así­ se ven las labels"), BorderLayout.NORTH);
      getContentPane().add(new JTextField("Y así­ las cajas de texto"), BorderLayout.SOUTH);
      getContentPane().add(new JScrollPane(new JTextArea("Area de\ntexto")), BorderLayout.WEST);
      getContentPane().add(new JSlider(SwingConstants.VERTICAL, 0, 200, 10 ),  BorderLayout.EAST);
      setSize(400,200);
      setVisible(true);
   }
   public static void main(String args[])
   {
      MetalLookAndFeel.setCurrentTheme(new EstiloHalloween2());
      try{
         UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
      }catch (Exception ex){
         System.out.println("Falló la carga del tema");
         System.out.println(ex);
      }
      JFrame.setDefaultLookAndFeelDecorated(true);
      JDialog.setDefaultLookAndFeelDecorated(true);
      try{
         UIManager.setLookAndFeel(new MetalLookAndFeel());
      }catch ( UnsupportedLookAndFeelException e ){
         System.out.println ("Metal Look & Feel no es soportada en esta plataforma");
         System.exit(0);
      }
      Ejemplo4Look ventana = new Ejemplo4Look();
      ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }
}


Esta es la apriencia del programa:


Y de nuevo: mil disculpas si se víé horrible, pero no soy diseíñador así­ que no me jodan XD.

Adjunto la versión en PDF
Y los ejercicios realizados (abajo)


Bien, espero que les haya gustado el artí­culo, y si estás buscando algo más avanzado puedes buscar entre la documentación en lí­nea de Java o en los demos del SDK. Y cualquier duda, sugerencia, insultos y demás, me pueden escribir al correo castidiablo@gmail.com, o por PM.

Umm, se me olvidaba algo: podeis hacer con el tuto lo que quieras: copias, modificaciones, ampliaciones, etc. ¿derechos de autor? mis polainas.

Saludos!!!
#17
Hacking / Sigo con proplemas [ettercap]
10 Octubre 2006, 21:30 PM

Pues el problema que supuestamente crei solucionado http://foro.elhacker.net/index.php/topic,142945.0.html aun sigue.

Resulta que efectivamente instalando el wincap desaparecen un monton de errores, pero solo si estás trabajando con Windows XP.

Pero si trabajo con Windows 2000 profesional, sigue apareceindo el mismo error.

Alguna sugerencia????
#18
Hola a todos...

Haber, ¿como empezar a desahogarme XD? Hace unos dias intenté quemar unas cosillas con el nero... pero aparecía un error todo extraño (algo así como DMA error - no recuerdo). Bien, pensé que era problema del cd.

Hoy con la misma quemadora borré un disco, y todo bien... pensé que ya no había problemas pero al momento de tratar de quemar sobre el mismo CD me sale el mismo error.

Así que decidí verificar si al menos servía para leer datos... y decidí hacer una copia del Ubuntu 6.06 LTS (original), meto el CD y comienza el proceso...... cuando depronto BOOOOOOM!!!!!!!!!!!!



No saben lo difícil que es obtener ese put0 cd de Ubuntu original aqui en Colombia.... maldita SEA!!!!!!!!


Las preguntas son.... ¿porqué pasó eso? ¿que es eso de DMA error? ¿como arreglo (destaparla y limpiarle los residuos) la quemadora yo mismo? Es que no tengo plata.

Saludos!!!
#19
Hola a todos...

Como puedo hacer en javascript para analizar el contenido de una página web que no sea el actual documento; me explico:

Por ejemplo tengo mi página http://mi.dominio.com/pagina1.htm y esta contiene una página común y corriente, pero necesito implementar en ella un código en javascript que pueda analizar otra página externa, por ej. http://otro.dominio.com/pagina2.html y pueda tener acceso a sus etiquetas y propiedades.

¿Es posible hacer esto?... ¿cómo?
#20

Si, ya sé que para crear codigo nativo se utiliza la bandera --aot. Al utilizar esto en linux en un archivo llamado programa.exe (por ejemplo), se crea un archivo llamado programa.exe.so. Pero vaya sorpresa me llevo, al darme cuenta que al intentar ejecutarlo me sale el siguiente error:


Violación de segmento

Pero, ¿què coñ0s es eso? Analicé el archivo con el comando file, y todo normal, el archivo programa.exe.so es un ELF de 32 bits. Inclusive, miré su código en assembler con el comando objdump, y parece estar bien.

Intenté probarlo en windows, y nisiquiera  puedo crear el archivo que estaría supuestamente en código nativo.

Espero vuestra ayuda....
#21

Hola a todos...

Pues estoy empezando con esto de .NET en linux y todo este rollo... y llevando en paralelo el aprendizaje de Java y C#, pero me llevo la sorpresa de que mono tiene compiladores para C#, y runtimes para Java... pero no un compilador para Java...

Cuando intento compilar un fichero de Java, con monodevelop, me sale lo siguiente: The Java addins has not been properly configured:


Como soluciono esto???[/color]
#22
Bueno, ya he posteado sobre los microcontroladores y sobre los circuitos que se pueden montar y eso; ahora que ya sabemos qué es un microcontrolador (exactamente los PIC 16C84 y 16F84), cómo probar programas simples en ASM y C, y tenemos los esquemas de los mismos para implementarlos en circuitos. Es hora de probar una tool que nos permitirá grabar los programas en nuestros PIC's y probar nuestros circuitos...

La tool que vamos a manejar es el ICProg (--descarga directa--) y las pruebas las he realizado con el grabador (o quemador) Te21se:

La puedes comprar en AP-ELEctronics ;)


En esta ocación vamos a configurar nuestra tool para que quede al pelo xD; lo primero descargarla, ahora copiamos la carpeta en algún lugar donde te quede cómodo abrir (c:\ por ejemplo). Ejecutamos el icprog.exe y posiblemente nos saldrá algo como esto (si es nuestra primera vez... eso se escuchó muy virginal xD):


Le damos ok, y tendremos lo siguiente (en algunos pc's da unos errores extraños, basta con cerrar la aplicación y volverla a lanzar):


Lo primero que haremos será configurar el idioma de la tool en "Español". Vamos al menu Settings->Options y picamos la pestaña Language.


Le damos ok, y ahora vamos al menú Ajustes->Tipo Hardware con lo que nos saldrá algo como esto:


MUY IMPORTANTE: Deberemos indicar correctamente el puerto COM al que vamos a conectar el cable. Ten en cuenta que si indicamos COM1 en ICPROG y conectamos el cable al COM2 no funcionará. En algunos ordenadores con módem interno, puede darse el caso que esté ocupando el COM1, y los puertos del ordenador sean el COM2 y el COM3.

En caso de errores en la grabación, se puede ir probando, bajando el valor de Retardo I/O. Aconsejo entre 4 - 7.

Ahora vamos a hacer una configuración general de nuestra aplicación; vamos a Ajustes->Opciones y colocamos todo como lo veremos a continuación:










Le damos OK y ya tenemos nuestro Icprog configurado ;)

Pasos a seguir para quemar nuestros PIC's

Voy a indicar algunas cosas que han de ser obvias para muchos de uds. que sí saben de electrónica... necesitas tener una tarjeta Piccard-1 (PIC16F84) o Piccard-2 (PIC16C84), junto con sus correspondientes circuitos integrados, un programador, el programa ICPROG y:

  • En el caso de PICCARD-1, dos archivos: uno .HEX para programar la PIC y el otro .BIN (en ocasiones también .HEX) para programar la EEPROM
  • En  el caso de PICCARD-2, un solo archivo para la PIC.
Nota: si no entiendes que es eso de la EEPROM, puedes hecharle un vistazo a este post ;)

Lo primero es insertar nuestro PIC en el zócalo adecuado del Te21se y en su posición correspondiente. Observa los chips de cerca, tienen una pequeña muesca en forma de media luna o de punto, que debe coincidir con la muesca de la misma forma de los zócalos del grabador, si los inviertes quemarás los put0s PIC's (no saldrá humo como en las películas xD, pero ya no funcionará más ;( ).

Una vez están correctamente insertados, conectamos el cable serie, por un lado al programador y por el otro a un puerto COM libre del ordenador. Ahora ejecutamos el programa ICPROG que ya deberemos tener bien configurado.

Indicamos que vamos a grabar el primero de los dos chips, el PIC16F84, con los siguientes pasos:

Ajustes -> Dispositivo -> Microchip Pic -> Mas -> PIC16F84


Ahora cargaremos el archivo que se va a grabar en el PIC, estos son los pasos:

Archivo -> Abrir Datos -> *.hex, (de los dos archivos hay que abrir el que tiene extensión .HEX puesto que el .BIN es para grabar el otro chip).

Esto se puede parecer a un editor hexadecimal, herramienta común entre los crackers. Una vez abierto, deberemos colocar las opciones Oscilador en XT y desactivar las opciones Bits configuración.


Listo!!!! Ahora solo no queda grabar la información del HEX en nuestros PIC's: Menu "Comando" -> "Programar todo":



Solución de Problemas

Este pequeño articulo de Solución de problemas frecuentes lo he pillado en un libro de Ap-Electronics. Dice así:

Si usando el programador no lee, no programa o genera errores de verificación (error de verificación en 0000H), se puede solucionar el problema en la mayoría de las ocasiones revisando los siguientes puntos:

  • El programador debe utilizarse desde un ordenador con Windows ME - 98 - 95. La familia Windows 2000 no soporta ICPROG.
  • Probar con un sólo elemento a programar o leer, en el zócalo correspondiente, es decir un PIC ó una EEPROM.
  • Probar con un sólo elemento a programar o leer, en el zócalo correspondiente, es decir un PIC ó una EEPROM.
  • Comprobar que la PIC y la EEPROM son los correctos, y han sido insertados con su muesca coincidiendo con la muesca del zócalo de programación, y que a su vez coincide con el PIN 1 en la serigrafía de la placa, marcado con un 1.
  • Comprobar que la PIC o la EEPROM se encuentra completamente insertado en su zócalo.
  • Comprobar que ha sido seleccionado en el menú el elemento que está programando en ese momento, es decir si se procede a programar un PIC16F876, el elemento seleccionado deberá ser el PIC16F876. En los anteriores pasos hemos indicado como seleccionarlo.
  • Comprobar que el menú Ajustes/Tipo Hardware (F3) se encuentra bien configurado.
  • La PIC y la EEPROM necesitan ser programados despacio, si su puerto está configurado a mucha velocidad esto puede originar fallos en la programación y verificación del mismo. Para reducir la velocidad de su puerto siga la siguiente secuencia de comandos con el ratón:

            Mi PC - Panel de control - Sistema - Administrador de dispositivos - Puertos COM y LPT - Puertos de comunicación COM1 ó COM2 - Configuración del puerto.

            El puerto puerto debe estar configurado de la siguiente manera:

                Bits por segundo: 9600 (ó menos en caso de errores)
                Bits de datos: 8 Paridad:
                Ninguna Bits de paridad: 1
                Control de flujo: Xon/Xoff

  • Al programar la PIC o la EEPROM, comprobar que el programa cargado y que se pretende programar en el integrado, tiene la extensión correcta, siendo generalmente *.HEX o *.BIN. Comprobar que el programa a programar en la PIC es el correcto y es el correspondiente al mismo, si intenta programar un programa de mayor tamaño a la capacidad del PIC, se producirá un mensaje de error.
  • Probar a utilizar en otro ordenador, ya que los programadores que se alimentan del puerto serie, son muy sensibles a la tensión que reciben desde el mismo y no todos los ordenadores son capaces de mantener la misma tensión durante el proceso de grabación.
Saludos!!!
#23
Diagramas y SeudoEsquemas para implementar los Microcontroladores PIC16X84 en circuitos reales o protoboards + Programas en ASM y C

¡¡¡Put0 título tan largo que me he inventado xD!!! Nada, decir que obviamente los programas no los he inventado yo, sino que son la recopilación de los "ejemplos práticos" más usados. Los he sacado de unos cuantos libros cuyo nombre no me sé (en realidad son unas fotocopias que encontré por casualidad). Y aclarar que los dibujos los hice yo en Visio, y que talvez tengan uno que otro fallo, la verdad es que me costó un huevo hacer esos put0s dibujos; en fín, si encontrais algún fallo me lo comunicas por privado. Sino conoceis como es este rollo de los Microcontroladores PIC, podeis hecharle un vistazo a este post: Introducción a microcontroladores PIC [simulando nuestro programas en ASM y C] (no te demoras sino 20 o 30 minutillos leyéndolo).


Primer Ejemplo: Explorando interruptores y encendiendo luces.

SeudoEsquema de Montaje

Descripción: Lee el número binario introducido mediante 3 interruptores conectados a la puerta A, luego suma 2 unidades a ese valor y visualiza el resultado mediante 4 diodos led conectados a la puerta B.

Programa en Assembler:

;----------------------------------------------------------------------------
    LIST    P=16C84         ;Comando que indica el PIC usado
    RADIX   HEX             ;Los valores se representar n en hexadecimal
;----------------------------------------------------------------------------
    PUERTAA EQU     0X05    ;La etiqueta "PUERTAA" queda identificada con
                            ;la dirección 0x05, que si corresponde con el
                            ;banco 0 es el valor de PUERTAA y si es del
                            ;banco 1 con el de TRISA.
    PUERTAB EQU     0X06    ;Equivalencia de la etiqueta PUERTAB
    ESTADO  EQU     0X03    ;Estado corresponde con el valor 0x03.
    W       EQU     0       ;Identifica W con el valor 0.
;----------------------------------------------------------------------------
    ORG     0               ;Comando que indica al Ensamblador la
                            ;dirección de la memeoria donde se
                            ;situar  la instrución siguiente
;----------------------------------------------------------------------------
    bsf     ESTADO,5        ;Pone a 1 el bit 5 de ESTADO para direccionar
                            ;la p gina 1 de la memoria de datos.
    movlw   0xff            ;W <-- FF(Hex)
    movwf   PUERTAA         ;W --> TRISA
    movlw   0x00            ;W <-- 0
    movwf   PUERTAB         ;W --> TRISB (Las líneas de PB salidas)
    bcf     ESTADO,5        ;Pone a 0 el bit 5 de ESTADO pasando a
                            ;acceder al banco 0.
   
    inicio movf PUERTAA,W   ;W <-- PUERTAA. Se introduce el valor binario
                            ;de los interruptores.
    addlw   2               ;W <-- W + 2
    movwf   PUERTAB         ;W --> PUERTAB. El valor de W sale por las
                            ;líneas de PB a los led.
    goto    inicio          ;Salta a la instrucción precedida por la
                            ;etiqueta de inicio.
    END



Programa en C:

#INCLUDE <16C84.H>
void main(void)
{
    int valor;              /* Valor temporal */
    int * p_puertaa= 0x05;  /* Puntero a PuertaA */
    int * p_puertab= 0x06;  /* Puntero a PuertaB */
   
    SET_TRIS_A (0xff);      /* 0xff --> TRISA */
    SET_TRIS_B (0x00);      /* 0x00 --> TRISB */
    do
    {
        valor = * p_puertaa;/* PuertaA --> valor  */
        valor += 2;         /* se incrementa valor en 2 */
        *p_puertab = valor; /* valor --> puertaB */
    }while(true);          /* Bucle infinito */
}



Segundo Ejemplo: Más interruptores y diodos led.

Esquema de Montaje

Descripción: Muestra por cinco diodos led en la puerta B la entrada que proporcionan cinco interruptores en la puerta A.

Programa en Assembler:

    LIST    p=16c84    ; Se usa el PIC16C84
    RADIX   hex        ; Se emplea el sistema de numeración hexadecimal
   
; ZONA DE ETIQUETAS-----------------------------------------------------------------------
    W    EQU    0      ; Cuando el destino es W, d = 0
    F    EQU    1      ; Cuando el destino es el registro f, d = 1
    PUERTAA EQU 0x05   ; La Puerta A (datos) ocupa la dirección 5 del
                       ; banco 0 y el registro de configuración la
                       ; dirección 5 del banco 1
    PUERTAB EQU 0x06   ; La misma etiqueta para el registro de datos y el
                       ; de configuración de la Puerta B
    ESTADO  EQU 0x03   ; El registro Estado ocupa dirección 3 de los dos bancos

; COMIENZO DEL PROGRAMA -----------------------------------------------------------------

    ORG    0           ; El programa comienza en la dirección 0 (Vector Reset)
    goto   inicio      ; Se salta a la etiqueta "inicio"
    ORG 5              ; Se asigna la dirección 5 a la siguiente instrucción
   
    inicio bsf ESTADO,5 ; Pone a 1 el bit 5 de Estado. Acceso al banco 1.
    clrf    PUERTAB     ; Se configuran como salidas las líneas de la Puerta B
    movlw   0xff        ; El registro W se carga con unos
    movwf   PUERTAA     ; Se configuran como entradas las líneas de la Puerta A
    bcf     ESTADO,5    ; Pone a 0 el bit 5 de Estado. Acceso al banco 0.
    bucle movf PUERTAA,W; Carga el registro de datos de Puerta A en W
    comf    PUERTAA,W   ; Complementa a 1 la entrada y la deposita en W
    movwf   PUERTAB     ; El contenido de W se deposita en el registro de datos de
                        ; la Puerta B
    goto    bucle       ; Se crea un bucle cerrado e infinito
   
    END                 ; Fin del programa


Programa en C:

#include <16c84.h>
#byte   puertaa = 05   /* Posición de la puerta A */
#byte   puertab = 06      /* Posición de la puerta B */
void main( void )
{
    int temp;
    set_tris_a( 0xFF );     /* Puerta A configurada para entrada */
    set_tris_b( 0x00 );     /* Puerta B configurada para salida  */
    do
    {
        /* La variable temporal es necesaria porque    */
        temp = ~puertaa;    /* la complementación se traduce en dos pasos: */
        puertab = temp;     /* a) Copia de puertaa en temp                 */
    }
    /* b) Complementación de temp                  */
    /* De no hacerlo así los LED parpadearían      */
    while( TRUE );/* Repetir ininterrumpidamente       */
}



Tercer Ejemplo: Contando y visualizando.

Esquema de Montaje

Descripción: Hace un conteo desde 0 hasta 0x5f y muestra en las patitas RB.

Programa en Assembler:

;----------------------------------------------------------------------------
    LIST    P=16C84
    RADIX   HEX
;----------------------------------------------------------------------------

    W       EQU     0x00    ; Comienzo del campo de etiquetas.
    F       EQU     0x01
    PUERTAB EQU     0x06
    ESTADO  EQU     0x03
    CONTA   EQU     0x0C
   
;----------------------------------------------------------------------------

    ORG     0               ; El programa comienza en la dirección 0 y
    goto    inicio          ; salta a la dirección 5 para sobrepasar
    ORG     5               ; el vector de interrupción.

;----------------------------------------------------------------------------

    inicio  bsf     ESTADO,5    ; Seleciona el banco 1
        movlw   0x00            ; Se configura PuertaB como salida
        movwf   PUERTAB
        bcf     ESTADO,5        ; Selección del banco 0
       
;----------------------------------------------------------------------------

    clrf    CONTA           ; CONTA = 0
    bucle1  incf  CONTA,F   ; CONTA + 1 --> CONTA
        movf    CONTA,W         ; CONTA se carga en W
        movwf   PUERTAB         ; W se carga en el registro de datos PB
        movlw   0x5f            ; W <-- 0x5f
        subwf   CONTA,W         ; CONTA - W --> W
        btfss   ESTADO,2        ; Explora Z y si vale 1 se produce "brinco"
    goto    bucle1          ; Si Z = 0 se vuelve a bucle1
     
    bucle2  goto    bucle2  ; si Z = 1 se produce un bucle infinito
    end


Programa en C:

#include <16c84.h> /* Tipo de PIC a usar */
#byte puertab=0x06
#byte conta=0x0C
void main(void)
{
    set_tris_b(0x00);    /* Configura la PB como salida */
    for (conta=0;conta<=0x5f;++conta)    /* Bucle que incrementa CONTA de 0 */
        puertab=conta;                   /* a 0x5f */
}



Cuarto Ejemplo: Controlando el tiempo.

SeudoEsquema de Montaje

Descripción: Programa que ilustra cómo realizar una temporización sin emplear interrupciones.

Programa en Assembler:

    LIST     P=16C84
    RADIX    HEX
; ------------------------------------------------------------------------

    PUERTAA  EQU  0x06
    OPTION   EQU  0x01
    ESTADO   EQU  0x03
    TMR      EQU  0x01
   
; ------------------------------------------------------------------------
   
    ORG   0    ; Inicio del programa en
               ; dirección 0
               
; ------------------------------------------------------------------------

    bsf    ESTADO,5     ; Banco 1
    movlw  b 1101 0110  ; Valor a cargar en
                        ; OPTION
    movwf  OPTION
    movlw  0x00
    movwf  PUERTAB      ; La Puerta B salida
    bcf    ESTADO,5     ; Banco 0
    clrf   PUERTAB      ; Las líneas de salida
                        ; de PB a 0
                       
    parpa bsf PUERTAB,7 ; Enciende el led RB7 = 1
    call  retardo       ; Llamada a subrutina de
                        ; RETARDO
    bcf   PUERTAB,7     ; Apaga el led, RB7 = 0
    call  retardo
    goto  parpa
   
    retardo clrf TMR0   ; TMR0 = 0 y empieza su
                        ; incremento
                       
    explora btfss TMR0,4; TMR0<4> = 1?
    goto   explora      ; No ha llegado TMR0 a 16d
    return              ; Ha llegado TMR0 al
                        ; valor 16d  y retorna
                        ; al programa principal
                       
    END


Programa en C:

#include <16C84.H>
#use delay( clock = 1000000 )  /* Especifica reloj de 1 MHz */
#byte puertab = 06              /* Dirección de la puerta B  */
void main( void )
{
    set_tris_b( 0x00 );
    puertab = 0;
    do
    {
        delay_us( 8700 );    /* Crea un bucle de espera de 8700 microsegundos */
        bit_set(puertab,7);  /* Enciende el LED */
        delay_us(8700);      /* Espera */
        bit_clear(puertab,7);/* Apaga el LED */
    }while(true);            /* Repetir siempre */
}



Quinto Ejemplo: Manejando Interrupciones.

SeudoEsquema de Montaje

Descripción: Refleja el estado de dos interruptores situados en RA0 y RA1 en RB0 y RB1 mientras hace parpadear un diodo en la línea RB7.

Programa en Assembler:

;----------------------------------------------------------------------------
   
    LIST    P=16C84
    RADIX   HEX
   
;----------------------------------------------------------------------------

    W    EQU    0
    F    EQU    1
    TMR_OPT EQU 0x01   ; TMRO en banco 0 OPTION en banco 1
    ESTADO EQU  0x03
    PUERTAA EQU 0x05   ; PA en banco 0 TRISA en banco1
    PUERTAB EQU 0x06   ; PB en banco 0 TRISB en banco1
    INTCON EQU  0x0B   ;
    CONTA  EQU  0x10   ; Contador auxiliar

;----------------------------------------------------------------------------

    ORG    0        ; Vector de Reset
    goto   inicio
   
    ORG    4        ; Vector de Interrupción
    goto   inter    ; Salta a comienzo de rutina de interrupción
    ORG    5
   
    inicio bsf  ESTADO,5        ; Selección del banco 1
    clrf   PUERTAB              ; Configura PUERTA B como salida
   
    movlw   b'00000011'         ; Configura RA0, RA1 como entradas
    movwf   PUERTAA
   
    movlw   b'00000111'
    movwf   TMR_OPT
   
    bcf     ESTADO,5            ; Banco 0
   
    movlw   b'10100000'         ; Se permite interrupción del
    movwf   INTCON              ; TMR0 y la globla (GIE)
   
    movlw   0x10
    movwf   CONTA               ; Se carga CONTA con 16 decimal
   
    movlw   0x0c
    movwf   TMR_OPT             ; Se carga TMR0 con 12 decimal
   
    bucle   btfsc   PUERTAA,0   ; Explora RA0 y brinco si vale 0
        goto    ra0_1           ; salta a RA0_1
        bcf     PUERTAB,0       ; Si RA0 = 0 sa saca por RB0 un 0
        goto    ra1x            ; A explorar RA1
       
        ra0_1 bsf   PUERTAB,0   ; Si RA0 = 1 se saca por RB0 un 1
   
        ra1x  btfsc PUERTAA,1   ; Examina ra1  y brinco si es 0
        goto    ra1_1           ; Salta  si RA1 = 1
        bcf     PUERTAB,1       ; Si RA1 = 0, RB1 = 0
       
        goto    bucle2
        ra1_1   bsf  PUERTAB,1  ; Si RA1 = 1 , RB1 = 1
    bucle2  goto    bucle       ; Bucle indefinido, se sale por la interupción
   
;----------------------------------------------------------------------------

    inter   decfsz  CONTA,1     ; RSI. Decrementa CONTA y brinco si vale 0
    goto    seguir
   
    conta_0 movlw   0x10        ; Si CONTA = 0 se carga
        movwf   CONTA
       
        btfsc   PUERTAB,7       ; Si RB7 = 0, brinco
        goto    rb7_1
        bsf     PUERTAB,7       ; Si RB7 = 0, se invierte
        goto    seguir
       
    rb7_1   bcf     PUERTAB,7   ; Si RB7 = 1 , se invierte
   
    seguir  movlw   b'10100000' ; Se restaura INTCON por desactivar las
        movwf   INTCON          ; interrupciones el procesador
        movlw   0x0c
        movwf   TMR_OPT         ; Se recarga TMR0 con 12
        retfie
       
        end


Programa en C:

#include <16c84.h> /* Selección del PIC a usar */
#use delay(clock= 4000000) /* Reloj de 4 MHz */
#BYTE puertab = 6
#define maximo 16 /* Constante: maximo = 16 */
byte conta;
/*--------------------------------------------------------------------------*/
/* SERVICIO DE LA INTERRUPCIóN */
#INT_RTCC /* Interrupción por desvordamiento del timer*/
clock_isr()
{
    short valor;
    short novalor;
    valor = bit_test(puertab,7); /* El bit valor es igual al contenido */
                                    /* de RB7 */
                                   
    novalor = !valor;
    if (--conta==0)
    {
        output_bit (PIN_B7,novalor); /* Voltea RB7 */
        delay_us (5);
        conta = maximo;
    }
}

/* PROGRAMA PRINCIPAL */
main()
{
    short ra0,ra1;
   
    set_tris_b(0x00); /* Se inicializa PB */
    conta=maximo;
    set_rtcc(0); /* Se inicializa el timer a cero */
   
    setup_counters(rtcc_internal,rtcc_div_256);
   
    enable_interrupts(rtcc_zero); /* Se permite int del tmr0 */
   
    enable_interrupts(GLOBAL); /* Se activa GIE */
   
    /* Rutina de control de los leds e interruptores: */
    do
    {
        ra0 =  input(PIN_A0);
        ra1 =  input(PIN_A1);
       
        output_bit (PIN_B0,ra0);
        output_bit (PIN_B1,ra1);
    }
    while(true); /* Bucle infinito */
}



Séptimo Ejemplo: Proyecto para manejar un display de 7 segmentos.

SeudoEsquema de Montaje

Descripción: Programa que visualiza un número del 1 al 7 en un display de siete segmentos en la puerta B dependiendo del valor binario de tres interruptores situados en la puerta A.

Programa en Assembler:

    LIST    P=16C84
    RADIX HEX
   
    w EQU 0
    f EQU 1
    PCL EQU 02
    PUERTAA EQU   05
    PUERTAB EQU   06
    ESTADO  EQU   03
    VALOR EQU 12 ; Registro auxiliar
   
; RUTINA PRINCIPAL: Lectura de los interruptores y c lculo del valor a visualizar

    ORG   0
    goto  inicio
    ORG   5               ; Para saltar el Vector de
                          ; Interrupción
   
    inicio bsf ESTADO,5   ; Selección del banco 1
        clrw
        movwf  PUERTAB    ; Puerta B salida
        movlw  0xff
        movwf  PUERTAA    ; puerta A entrada
        bcf ESTADO,5      ; Selección banco 0
        explora  movf PUERTAA,w  ; Se cargan los
                                 ; interruptores en W
        movwf VALOR     ; Se usa un registro auxiliar
        comf    VALOR,f   ; Invertir los niveles de interuptores
        clrw
        btfss   VALOR,0   ; Si RA0 = 1, brinca
        goto    bit_1     ; Salta a explorar el bit_1
        addlw   0x01      ; Si RA0 =1, se suma
        bit_1 btfss VALOR,1; Si RA1 = 1, brinca
        goto    bit_2     ; Salta a explorar el bit_2
        addlw   0x02      ; Si RA1 = 1, se suman 2
        bit_2 btfss VALOR,2; Si RA2 = 1, brinca
        goto    visual    ; Salta al módulo del display
        addlw   0x04      ; Si RA2 0 1, se suman 4
        visual  call  display ; Salta al módulo del display
       
; DISPLAY: Rutina de visualización del acumulador en el display de 7 segmentos

    movwf   PUERTAB       ; Al retornar de la subrutina
                          ; el valor de W se saca por la
                          ; Puerta B
    bucle  goto  bucle    ; bucle infinito
   
; TABLA DE CONVERSION---------------------------------------------------------

    display  addwf  PCL,f  ; pcl + W -> W
                           ; El pcl se incrementa con el
                           ; valor de W proporcionando un
                           ; salto
    retlw   0x3F           ; Retorna con el valor del
                           ; código del 0
    retlw   0x06           ; Retorna con el código del 1
    retlw   0x5b           ; Retorna con el código del 2
    retlw   0x4f           ; Retorna con el código del 3
    retlw   0x66           ; Retorna con el código del 4
    retlw   0x6d           ; Retorna con el código del 5
    retlw   0x7d           ; Retorna con el código del 6
    retlw   0x07           ; Retorna con el código del 7
   
    END


Programa en C:

#include <16C84.H>
#byte puertaa = 05  /* Posición de la puerta A */
#byte puertab = 06  /* Posición de la puerta B */
void main( void )
{
    int temp = 0, tabla[8]={ 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07 };
    int indice = 0;
    set_tris_a( 0xFF );   /* Puerta A configurada para entrada */
    set_tris_b( 0x00 );   /* Puerta B configurada para salida  */
    temp = ~puertaa;      /* Se complementa la entrada de PA   */
    if ( bit_test( temp, 0 ) ) indice += 1;
    if ( bit_test( temp, 1 ) ) indice += 2;
    if ( bit_test( temp, 2 ) ) indice += 4;
    puertab = tabla[indice];
}



Ejemplos básicos de programación de Microcontroladores PIC16X84 sin esquemas ni diagramas; enunciados de los ejemplos:


  • Control de un dispositivo desde dos puntos: Se desea controlar una lámpara, en este caso un diodo LED desde dos interruptores, de forma que cuando los dos interruptores están abiertos el LED está apagado. A partir de esta situación, cada vez que cambie el estado de un interruptor, el estado del LED bascula  (si está apagado se enciende y viceversa)
  • Semáforo programabe: Se simula un semáforo con 3 diodos LED. Se dispone de 2 interruptores que según la combinación que adopten originan una secuencia de encendido de las luces del semáforo.
  • Dado electrónico: Este programa simula el juego del dado. Un dado típico tiene 6 caras, en cada una de las cuales viene dibujado un número del 1 al 6. Cada vez que se presiona un pulsador se produce un número aleatorio entre 1 y 6, el cual se visualiza en un display de 7 segmentos.
  • Temporizador programable: Con 3 microrruptores se selecciona un valor entre el 0 y el 7 (binario), que representa un tiempo en segundos y que ser  visualizado por el display de 7 segmentos. Durante el tiempo que dura la temporización un LED rojo permanece activado, así como un zumbador. Al finalizar se desactivan ambos elementos y el display se pone a 0.
  • Alarma: Se tienen 3 detectores digitales, cada uno de los cuales provocar la activación de un LED, diferente en cada caso. Uno de los detectores ser  un optoacoplador y los otros 2 se simularán mediante 2 microrruptores. El programa consiste en poner en marcha un zumbador cuando la alarma salte por causa de la activación de cualquiera de los detectores. También se enciende el LED correspondiente al detector. La alarma sólo funcionará cuando el microrruptor I1 de conexión esté a nivel alto.
  • Ejemplo tomado de Internet: (Autor: David Tait, david.tait@man.ac.uk) Este programa ilumina una serie de leds en secuencia principio-fin-principio (algo así como las luces del "El Coche Fantástico).
  • Manejo del WatchDog (perro guardián): El objetivo de este programa es mostrar en la práctica el funcionamiento del Watchdog en el PIC 16c84. El programa entra en un bucle infinito del que sale tras cumplirse la temporización asiganada al watchdog, que en este caso ser n 36 ms, es decir 2 veces la temporización nominal.



En un futuro post talvez coloque un pequeño glosario de las instrucciones de Assembler para esta gama de microcontroladores, para los que no entienden mucho los códigos; por lo demás espero que les sea de ayuda ;) Y anexo también el archivo donde tengo los (seudo)diagramas en formato *.vsd (Visio), por si lo necesitan o quisieran modificar algún put0 dibujito de esos.

Saludos!!!
#24
EL PRIMER CONTACTO CON EL PIC16X84

De antemano disculpas por cualquier fallo en este escrito, ya que no es hecho por un "electrónico", sino por un aficionado que pretende ser algún día un programador. Y a todas estas, lo bonito del los microcontroladores no está (para mi) en el hardware sino en la programación.

Los temas a tratar son los siguientes:

    •Introducción al PIC16X84 (Pequeño, pobre, pero resultón)
    •Variantes del PIC16X8X
    •Diferencias entre el PIC16C84 con lo demás modelos PIC16X8X
    •La frecuencia de funcionamiento, el reloj
    •¿Para qué y cómo programar PIC's?
    •Primer ejemplo... Aprendiendo a Sumar (ASM)
    •Ejecutar nuestro programa (simulando con el Simupic'84)
    • ASM vs. C/C++; Eficiencia vs. Comodidad

Importante: es recomendado que la gente que esté interesada en la parte de electrónica revise todos los puntos... los que solo se interesan en la programación (que es en ASM y C), se pueden saltar a la parte de ¿Para qué y cómo programar PIC's?

Bueno... he aquí mi granito de arena. Considerando que mucha gente  no conoce o quisiera conocer acerca de los microcontroladores, me veo en la obligación de aportar un poco acerca de, en mi opinión, el microcontrolador más fácil de manejar y programar (la familia PIC16X84, es decir PIC16C84 y PIC16F84).
Mucha gente, me incluyo, cuando está comenzando en este mundillo ve a los microcontroladores y a la programación en ASM como algo raro y de otro mundo... cuando en verdad es algo realmente sencillo. Así que si estás interesado en aprender un poco de "electrónica" o "Programación en ASM" esto te puede ayudar a aclarar muchas dudas.

Menos charla, más acción:

Pequeño, pobre, pero resultón
Este "maravilloso" PIC pertenece a la familia de la gama media y dentro de ella es uno de los más pequeños; solo tiene 18 patitas. Además es el que dispone de menos recursos.

El resto de sus parientes tiene conversores AD y DA, comparadores analógicos, tensión interna de referencia, más líneas de E/S, más capacidad en sus memorias, varios temporizadores y un largo etcétera de dispositivos de los que el PIC16X84 carece.

Es "pobre" de mantenimiento... pero he escogido este PIC, en sus dos versiones C y F, porque cumple con los requisitos esenciales para enseñar a manejar los microcontroladores y para comenzar para diseñar proyectos. Es práctico, es sencillo y es económico, pudiéndolo considerar como el paradigma para su empleo en todos los pequeños proyectos que realizan los aficionados, los estudiantes y los que quieren progresar en sus conocimientos de lo fácil a lo difícil. Además si aprendes a manejar este PIC, migrar hacia los demás es muy sencillo.

La razón exclusiva por la que este PIC es tan "requerido", es por el tipo de memoria de programa que posee. El PIC16C84 posee una EEPROM de 1K palabras de 14 bits cada una. El PIC16F84 tiene la misma capacidad de memoria de instrucciones pero de tipo Flash. Ambos poseen una capacidad de 64 bytes EEPROM como memoria de datos auxiliar y opcional.

La memoria EEPROM y la Flash son eléctricamente grabables y borrables, lo que permite escribir y borrar el programa bajo prueba manteniendo el microcontrolador bajo el mismo dispositivo grabar y borrar. Esta característica supone una gran ventaja con la mayoría de los microcontroladores, que tienen como memoria de programa reescribible una tipo EPROM. Se graban eléctricamente, pero para borrarlas hay que exponerlas cierto tiempo a rayos ultravioleta, lo que implica tener que sacar el chip del zócalo para poderlo borrar.

Microchip ha introducido la memoria Flash porque tiene mayores posibilidades de aumentar su capacidad con relación a la EEPROM. Pero sin embargo la EEPROM soporta 1.000.000 ciclos de escritura/borrado frente a los 1.000 de la Flash.

Otra de las grandes ventajas del PIC16X84 (en cuanto a escritura, borrado y reescritura) es su sistema de grabación de datos, que se realiza en serie. Para escribir un programa en la memoria se manda la información en serie usando solo dos patitas: la RB6 para la señal de reloj y la RB7 para los bits de datos de serie. Bueno, no os asustéis con eso de los RB6 y RB7 que más adelante os lo explico.

A continuación la "Tarjeta de presentación de los PIC16X84" con sus datos personales más significativos:

Cita de: Ficha técnica de los PIC16X84Memoria de programa: 1Kx14, EEPROM (PIC16C84) y Flash (PIC16F84)
Memoria de datos RAM: 36 bytes (PIC16C84) y 68 bytes (PIC16F84)
Memoria de datos EEPROM: 64 bytes para todos lo modelos
Pila (stack): De 8 Niveles
Interrupciones: 4 tipos diferentes
Encapsulado: Plástico DIP de 18 patitas
Frecuencia de trabajo: 10MHz máxima
Temporizadores: Sólo uno, el TMR0. También tienen "Perro guardián (WDT)"
Líneas de E/S Digitales: 13 (5 Puerta A y 8 Puesta B)
Corriente máxima absorbida: 80mA Puerta A y 150mA Puerta B
Corriente máxima suministrada: 50mA Puerta A y 100mA Puerta B
Corriente máxima absorbida por línea: 25mA
Corriente máxima suministrada por línea: 20mA
Voltaje de alimentación (VDD): De 2 a 6 V DC
Voltaje de grabación (VPP): De 12 a 14 V DC


Variantes del PIC16X8X
Se comercializan varios chips correspondientes a la familia de los PIC16X8X, que atienden diversas características.

    1. Frecuencia máxima de funcionamiento
    2. Tipo de oscilador externo usado para generar la frecuencia de reloj.
    3. Margen de voltaje de alimentación[/list]

    Los modelos que tienen de intermedio la referencia C, F o CR admiten el rango de alimentación de voltaje estándar, que es el que oscila de 4 a 4,5 V DC como mínimo, hasta 5,5 a 6 V DC como máximo. Los modelos con las letras LC, LF o LCR intermedias admiten el rango de voltaje "extendido", que abarca desde los 2 V hasta los 6 V DC.

    La buena aceptación del PIC16C84 ha animado al fabricante Microchip a comercializar nuevas versiones. Ha diseñado cuatro nuevos modelos:


      •PIC16F84
      •PIC16CR84
      •PIC16F83
      •PIC16CR83

    Dos de ellos intercalan la letra F indicando así que la memoria EEPROM se ha sustituido por otra de tipo Flash. Los otros modelos la sustituyen por memoria ROM con máscara, pero todos ellos mantienen los 64 bytes de EEPROM para datos.


    Diferencias entre el PIC16C84 con lo demás modelos PIC16X8X

      1. La memoria de programa es de tipo Flash en los PIC16F8X y de tipo ROM en los PIC16CR8X
      2. El PIC16F84 y el PIC16CR84 tienen mayor capacidad de la RAM de datos. Disponen de 68 bytes en lugar de los 36 del PIC16C84.
      3. Se ha invertido la polaridad del bit de control PWRTE, que activa y desactiva un temporizador encargado de retrasar el funcionamiento del PIC al aplicarle la alimentación.
      4. Se ha incorporado un filtro a la entrada de la patita MCLR#, por lo que se requiere un pulso de mayor duración para generar el Reset.
      5. Se han mejorado muchas especificaciones eléctricas en los modelos F y CR.[/list]


      El aspecto externo
      Este PIC está desarrollado con tecnología CMOS de altas prestaciones y encapsulado en plástico con 18 patitas. Ok, ahora comento brevemente la misión de cada patita.

      VDD: Patita por la que se aplica la tensión positiva de la alimentación.
      VSS: Patita conectada a la tierra o negativo de la alimentación.
      OSC1/CLKIN: Patita por la que se aplica la entrada del circuito oscilador externo que proporciona la frecuencia de trabajo del microcontrolador.
      OSC2/CLKOUT: Patita auxiliar del circuito oscilador.
      MCLR#: Esta patita es activa con nivel lógico bajo, lo que se representa con el símbolo #. En pocas palabras con esta reseteas el PIC.
      RA0-RA4: Son las líneas de E/S digitales correspondientes a la puerta A. La línea RA4
      RB0-RB7: estas 8 patitas corresponden a las 8 líneas de E/S digitales de la puerta B. La línea RB0 multiplexa otra función, que es la de servir como entrada a otra petición externa de interrupción, por eso se le denomina RB0/INT.

      CitarLos PIC16X8X tienen un encapsulado de 18 patitas, dos de ellas soportan la tensión de alimentación, otras dos reciben la señal de oscilador externo y otra se utiliza para generar un Reset. Las 13 patitas restantes funcionan como líneas de E/S para controlar las aplicaciones.


      La frecuencia de funcionamiento, el reloj
      La frecuencia de trabajo del microcontrolador es sumamente importante para establecer la velocidad en el proceso de instrucciones y el consumo de energía.

      ¿Qué coños significa esto?... bien, paso a explicar. Por ej., cuando un PIC16X8X funciona a 10 MHz le corresponde un ciclo de instrucción de 400 ns... ¿por qué? Pues porque cada instrucción tarda en ejecutarse cuatro periodos de reloj, o sea, 4x100 ns. Ahhh se me olvidaba: cada instrucción se ejecuta en un ciclo, menos las de salto que se demoran el doble.


      Bueno muy bonito todo pero... ¿para qué y cómo programo microcontroladores?

      Muchas veces cuando nos metemos en el mundillo de la programación, nos preguntamos si los resultados de nuestra programación podrían ser más palpables, y a veces (por lo menos yo) ni nos imaginamos que podemos crear software que manipule Chips directamente.

      El para qué programar microcontroladores es muy sencillo. Por ejemplo, hoy en día, casi todos los aparatos funcionan con microcontroladores. Desde las puertas automáticas de un súper mercado, pasando por los controles de computadores, hasta la lavadora de mamá. Esto nos da a entender, a grosso modo, que el mercado de los microcontroladores es muy amplio y por ende apetecido; lo que se vuelve en una tentativa para comenzar conocer y manejar estos maravillosos dispositivos.

      Para el cómo he aquí una breve explicación de cómo se modela software para microcontroladores, los pasos a seguir son más o menos los siguientes:

        • Crear el algoritmo
        • Codificar
        • Compilar
        • Ejecutar y Depurar
        • Grabar
        • Montar

      Más o menos la explicación sería: diceñamos el algoritmo del programa que deseemos crear. En lo personal no me gustan los tales diagramas de flujo ni ninguna coñada de esas, si acaso el pseudo-código y listo.

      Codificar (o codear como dicen algunos) es la parte que más me gusta, y consiste en crear el código fuente del programa con el Block de Notas, el Edit, el Vim, el Emacs o cualquier editor de texto plano. Este archivo lo deberéis guardar con la extensión .ASM, ya te estaréis imaginando que la programación será en Assembler ¿no?

      Es muy común que uno oiga hablar del famoso Assembler... que ASM esto, que ASM lo otro, que ASM es difícil, que ahora es fácil, etc. Pero la verdad no le vemos mucho sentido utilizar este lenguaje (de bajo nivel) para programar (si acaso si nos interesamos un poco por él cuando sentimos curiosidad por el mundo del Cracking), ya que para eso está el C++, Java y los demás. Pues bien, llegó la hora de tratar de aprender un poco de este, y que deje de ser un bicho raro. Para ello desarrollaremos unos ejercicios, pero más adelante, ahora sigo explicando el modelado de software.

      La fase de compilación es muy similar a la que hay en lenguajes como C o Java, y consiste pasar el código por un "compilador" (en mi caso MPASM) que determinará si existen errores de sintaxis, y de lo contrario crea un archivo .HEX (es como cuando se crean .exe a partir de un código en C). La extensión es .HEX porque lo que hace es pasar el código a instrucciones en Hexadecimal (no exactamente, pero quedaros con ello mientras tanto).

      Bueno, después necesitamos verificar si en realidad nuestro software funciona. Pero NO resultaría muy viable pasar el software directamente a un Microcontrolador sin haberlo probado, por ello se han inventado los famosos "simuladores". Como os podréis imaginar lo que hacen estos programas es simular la ejecución del programa en el chip, para poder depurar los posibles errores de lógica. Para que vayas averiguando uno de los mejores simuladores es el Simupic.


      El proceso de grabación se hace a través de una quemadora de PIC's (en Colombia se le dice quemadora, en otros lados le dicen grabadora, tostadora y que se yo), que es un hardware que se conecta a un puerto serial de vuestra PC, y en donde se "incrusta" el microcontrolador a "quemar".

      El proceso de grabación se lleva a cabo, obviamente, a través de un software especial. En mi caso utilizo de ICProg... más adelante tal vez explique su uso.

      El montaje es en sí el proceso en el que colocamos nuestro chip en el circuito final, o en una protoboard de ensayos. Esto obviamente para que cumpla con las acciones que hemos programado.

      Primer ejemplo... Aprendiendo a Sumar
      Bueno, antes de codear tenemos que aprendernos algunos conceptos... no os desesperéis. Todos los computadores saben sumar y nuestro PIC16X84 también. Bueno, el caso es que solo saben sumar en binario, porque son máquinas electrónicas digitales. El sumador del PIC es capaz de sumar dos datos de 8 bits cada uno. Dicho sumador tiene un registro, llamado W (de trabajo), en donde aloja uno de los dos sumandos. El otro sumando debemos decir lo que vale o en que posición de memoria está.

      Antes de poner el enunciado del problema, miraremos las instrucciones que vamos a usar:

      Instrucción mov
      Esta instrucción es típica en todos los procesadores y su misión es transferir el contenido de un registro "fuente" (f) a un "destino" (d). En los microcontroladores PIC todos los datos residen en posiciones de memoria de datos y sólo el registro de trabajo W se salva de esta regla. Esto significa que mov puede mover tres tipos de operandos fundamentales:

        1. El contenido del registro W
        2. El contenido de una posición de la memoria de datos o registro.
        3. Un literal o valor inmediato que se incluye en el código máquina de la propia instrucción.

      Para gestionar los posibles operandos existen tres variantes de mov:

      movf f,d: Mueve el contenido del operando fuente, que es una posición de la memoria de datos, al destino, que bien puede ser W cuando d=0, o el propio fuente cuando d=1.

      movwf f: Mueve el contenido del registro W a la posición de la memoria de datos identificada por f. Realiza la transferencia W->f.

      movlw k: Mueve el literal k incluido en el código de la instrucción al registro W, k->W.

      Instrucción add

      addwf f,d: Suma el contenido del registro W con el de f y deposita el resultado en W si el valor de d=0, mientras que si d=1 lo deposita en f.

      addlw k: Suma al contenido del registro W el literal que acompaña a la instrucción y deposita el resultado en W (W+k->W).

      Bien, hasta aquí todo bien, pero sé que con aún no os queda claro y la mejor forma de aclarar todo lo que he intentado explicar es con un ejemplo:

      Enunciado del problema
      El ejercicio debe manejar tres posiciones de memoria de datos. En la dirección 0x0c (recordemos que las posiciones de memoria se manejan con números hexadecimales) se depositará el primer operando; en la 0x0d el segundo y en la 0x0e el resultado de la suma de los primeros operandos. Como valor para el primer operando se va a usar 5 y como segundo operando el 12.

      Nota: en muchas fuentes de información se manejan los números hexadecimales de otra forma... por ejemplo es lo mismo si ves: 0x0c, h'0c', 0c ó 0Ch. Esto nos indica que hay varias formas de  representar un numero hexadecimal, pero yo utilizo la forma en la que se antepone 0x porque es la más empleada, a demás de ser la que utiliza lenguajes como C/C++.


      Edición del programa
      Como ya lo había dicho, para editar un programa se puede usar cualquier editor de texto plano. Entonces creamos un archivo con el siguiente código, y lo guardamos como suma.asm:


      LIST P=16C84 ; Indica el modelo de PIC que se usa
      ; Es una directiva del Ensamblador

      ; Zona para etiquetas
      OPERANDO1 EQU 0x0c ; Define la posición del operando 1
      OPERANDO2 EQU 0x0d ; Define la posición del operando 2
      RESULTADO EQU 0x0e ; Define la posición del resultado

      ORG0 ; Comando que indica al Ensamblador
      ; la dirección de la memoria de
      ; programa donde se situará la
      ; siguiente instrucción

      movlw 05 ; 5->W (primera instrucción)
      movwf OPERANDO1 ; W->operando1
      movlw 02 ; 2->W
      movwf OPERANDO2 ; W->operando2
      movfw OPERANDO1 ; opernado1 -> W
      addwf OPERANDO2,0 ; W + operando2 ->W
      movwf RESULTADO ; W->resultado

      END ; Directiva de fin de programa


      A tener en cuenta: el uso de mayúsculas y minúsculas en este fragmento de código obedece a una serie de reglas o normas de estilo, comunes entre los programadores en ensamblador, que aunque no son obligatorias, facilitan la lectura del código fuente. Un resumen de las reglas empleadas es el siguiente:

        • Directivas de compilador en mayúsculas
        • Nombre de variables en mayúsculas
        • Nemónicos en minúsculas
        • Programa bien tabulado

      Solo por aclarar: los "punto y coma" ( ; ) después de cada instrucción se utilizan para comentariar el código. Es como el /* de C el # de Perl ó el // de C++ y Java. Finalmente guardamos nuestro archivo con la extensión .ASM y listo.

      Bueno todo muy bonito, pero como coños pruebo mi maldito programa ¿ehh? Púes bien para eso tendremos que valernos de un software especial, que nos compile el programa (que lo pase a instrucciones en hexadecimal; .ASM -> .HEX). Recomiendo el MPSIM de Microchip y el SIMUPIC de Microsystems Engineering. Lo que me lleva al siguiente capitulo.


      Manejando el Simulador SIMUPIC'84: el primer contacto
      El simulador SIMUPIC'84 es una herramienta que trata de facilitar la labor del programador del PIC. Como sabemos para crear un programa en ensamblador tenemos que recurrir a distintos programas; un editor, un ensamblador y un simulador. El SIMUPIC'84 trata de integrar todos en una sola herramienta, y agrega otras herramientas más, que facilitan el proceso de depuración entre otras.

      Para los que saben un poco del tema sabrán que este es un programa antiguo, pero es de los más fáciles de manejar por lo que lo he escogido. Lo primero que debemos hacer es bajarlo de Internet, entonces vas al google y lo buscas... ¿cómo, te da pereza? Ok, bájalo de aquí.


      Bueno, lo primero es descomprimirlo. Guardas la carpeta donde te quede más cómodo y ejecutas el archivo sim84.exe. Con lo que verás lo siguiente:


      Ok, ahora vamos a ver el funcionamiento básico del programa; primero hay que indicarle el nombre del fichero (.asm) con el que vamos a trabajar, esto lo hacemos dándole "enter" a la opción "Asignar Nombre". Vamos a trabajar con nuestro primer programa (el que hicimos arriba), por lo tanto debemos guardar ese archivo (suma.asm) en la carpeta donde tengamos nuestro simupic.


      Paso siguiente vamos a la opción "Llamar al editor". Esta opción nos permite crear un fichero nuevo (llamando al edit del Windows), o cargar un archivo ya existente (en este caso suma.asm).

      Hasta el momento solo hemos editado y cargado el código del programa en el simupic. Ahora debemos ensamblarlo (o compilarlo), por lo que vamos a la opción "Ensamblar". Es de aclarar que el "ensamblaje" lo hace un programa externo llamado "MPASM", pero nuestro simupic se encarga de llamarlo y utilizarlo por nosotros. Nos debe aparecer lo siguiente:


      En esa consola nos aparecen los posibles errores de sintaxis, y los molestos warnings. De momento solo nos interesa que no tenga errores, por lo que presionamos cualquier tecla para salir de esa ventana, y la siguiente que vemos es el reporte de los Warnings, simplemente salimos del edit.

      Recordemos que al ensamblar nuestro código fuente, lo que hacemos es crear un fichero .hex que contienes las instrucciones del fuente en hexadecimal. Por esto debemos cargar el fichero hexadecimal en el PIC (esta parte simula el momento en el que quemamos nuestro programa en un PIC de verdad). Vamos a la opción "Cargar fichero HEX" con lo que nos saldrá el siguiente dialogo:


      Fijémonos que al cargar el archivo .hex la parte inferior izquierda cambia:


      En esta parte podemos observar línea a línea el comportamiento de nuestro programa, y es de gran utilidad por que nos sirve como depurador.

      Ahora vamos a "simular" el programa, para analizar su comportamiento. Para ello vamos a configurar nuestro simulador para que nos muestre el comportamiento de las variables, es decir, qué valores toman al transcurrir el programa. Para ello vamos a la opción "Visualizar Registros" y después "Añadir registros":



      Y después seleccionamos "W (Acumulador)"... recordemos que el registro W (registro de trabajo) es donde almacenamos los datos que necesitemos manipular.


      Luego de esto nos aparecerá en la ventana superior derecha, el registro que hemos agregado y el valor que contiene:


      Es de aclarar que las variables y registros de nuestro PIC almacenan un byte, es decir 8 bits, por lo que las variables y registros que pongamos en esa parte, constarán de 8 números binarios. Si te estás preguntando qué coños es el tal PCL, explico; el PCL es un "apuntador" que le indica al PIC la posición de memoria donde se encuentra la instrucción (en binario) que se debe efectuar. Esto no es así exactamente pero por ahora nos basta.

      Pero en el programa tenemos tres variables (OPERANDO1, OPERANDO2, RESULTADO), que sería importante tener en cuenta para analizar el programa. Para añadirlas a la lista vamos a la opción "Visualizar Registros" y "Añadir registros", y seleccionamos la opción "Mediante Dir. Hex.":


      Allí debemos indicarle la posición en memoria en donde se encuentra la variable... recordemos el fragmento de código donde inicializamos las variables:

      OPERANDO1 EQU 0x0c ; Define la posición del operando 1
      OPERANDO2 EQU 0x0d ; Define la posición del operando 2
      RESULTADO EQU 0x0e ; Define la posición del resultado


      A la variable OPERANDO1 se le asigno la posición 0x0c; a la variable OPERANDO2 se le asigno la posición 0x0d; a la variable RESULTADO se le asigno la posición 0x0e.

      Por ello en el cuadro de dialogo que nos pide la dirección de memoria de las variables debemos digitar esas direcciones; pero no todas a la vez, sino "una por una":


      Observemos que no digitamos 0x0c sino 0c, ya que se asume que lo que vamos a digitar es un numero en sistema hexadecimal. Después le damos continuar y asignamos una referencia a esa variable, por ej. Op1:


      Repetimos la misma operación con las variables OPERANDO2 y RESULTADO, y nos fijamos que en la parte superior derecha tengamos algo como:


      Ahora sí vamos a "simular" nuestro programa, pero primero vamos a la opción "Opciones de simulación" y le damos "Reset en el PIC" (esto no creo tener que explicarlo); Ahora nos vamos a la opción "Trazar" para ver el comportamiento de nuestro programa. Analizamos un poco la primera instrucción a la que apunta PCL:


      Esta instrucción equivale a la instrucción movlw 05 de nuestro código fuente. Y le indica al PIC que acumule el valor 5 en el registro de trabajo W. Fijémonos como esto se ve reflejado a nuestra derecha:


      En el registro W tenemos 00000101 que es el equivalente de 5 en notación binaria. Ahora cada vez que demos un "enter" el programa va ir avanzando línea por línea (con el apuntador PCL). Ahora, analizaremos qué pasa cada vez que demos enter (cada item equivale a un enter):

        1. En el registro W tenemos 00000101 (5 en decimal); esto equivale a la instrucción movlw 05.
        2. (en el segundo enter) En el registro op1 tenemos 00000101 (5 en decimal), ya que almacenamos lo que tenía W en OPERANDO1 (referenciado por op1); esto equivale a la instrucción movwf OPERANDO1.
        3. En el registro W tenemos 00000010 (2 en decimal); esto equivale a la instrucción movlw 02.
        4. En el registro op2 tenemos 00000010 (2 en decimal), ya que almacenamos lo que tenía W en OPERANDO2 (referenciado por op2); esto equivale a la instrucción movwf OPERANDO2.
        5. En el registro W tenemos 00000101 (5 en decimal), ya que copiamos el contenido de OPERANDO1 a W; esto equivale a la instrucción movfw OPERANDO1.
        6. En el registro W tenemos 00000111 (7 en decimal), ya que sumamos el contenido de OPERANDO2 con W y el resultado lo almacenamos en W; esto equivale a la instrucción addwf OPERANDO2,0.
        7. En el registro res (que referencia la variable RESULTADO) tenemos 00000111 (7 en decimal), ya que le almacenamos lo que tenía W; esto equivale a la instrucción movwf RESULTADO.

      Cuando ya hemos ejecutado todas las instrucciones nos aparecerá un mensaje indicándonos que el programa ha finalizado:


      ASM vs. C/C++; Eficiencia vs. Comodidad

      Parte importante de este tutorial es hacer un paralelo entre la programación en ASM y en C/C++, ya que cualquier programa para un microcontrolador, además de codificarse en ASM, también puede ser codificado en C. Obviamente en C, al ser un lenguaje de "alto nivel", se dispone de una mayor comodidad a la hora de programar, pero ello conlleva un pequeño sacrificio en cuanto a tiempo de ejecución. Al grano, vamos a hacer el mismo programa que habíamos hecho en un principio (suma.asm) pero ahora en C (suma.c):

      /* Programa que suma el contenido de dos variables en memoria y almacena */
      /* el resultado en una tercera variable de resultado. Equivalente al     */
      /* ejercicio 1.                                                          */
      #include <16c84.h>
      void main( void )
      {
      int operando1 = 5, operando2 = 2, resultado;
      resultado = operando1 + operando2;
      }


      El programa ha sido compilado con el PCM de la casa Custom Computer Services que comercializa Microsystems Engineering y se ha empleado el SIMUPIC'84 para desensamblar su código y traducirlo a ensamblador. El resultado es el siguiente:

      00 movlw 00
      01 movwf 0x0a
      02 goto 05
      03 nop
      04 nop
      05 clrf 0x04
      06 clrf 0x03
      07 movlw 0x0c
      08 movwf 0x0e
      09 movlw 0x0d
      0A movwf 0x0f
      0B movlw 0x0e
      0C movwf 0x10
      0D movf 0x0e,0
      0E movwf 0x04
      0F movlw 0x05
      10 movwf 0x00
      11 movf 0x0f,0
      12 movwf 0x04
      13 movlw 02
      14 movwf 0x00
      15 movf 0x00,0
      16 movwf 0x11
      17 movf 0x0e,0
      18 movwf 0x04
      19 movf 0x00,0
      1A movwf 0x12
      1B movf 0x0f,0
      1C movwf 0x04
      1D movf 0x00,0
      1E addwf 0x12,0
      1F movwf 0x12
      20 movf 0x11,0
      21 movwf 0x04
      22 movf 0x12,0
      23 movf 0x00
      24 sleep
      25


      ¡¡¡Demonios, el código resultante está compuesto por 37 instrucciones!!! Esto es casi cuatro veces el programa que habíamos hecho anteriormente en assembler. Esto ya os dará una idea de lo que implica programar en C microcontroladores: tamaño en el programa y por ende tiempo de ejecución.
      #25
      Este tuto contiene:

      • Pequeña introducción a XUL
      • Nuestro primer programa en XUL
      • Un programa más complejo
      • Comunicándonos con el usuario
      • Otros widgets de XUL
      • Creación de Menús
      • RDF
      • El registro chrome
      • Modularidad en XUL
      • Nuestra primera extensión
      • XPI



      Pequeña introducción a XUL

      XUL es un lenguaje basado en XML para el desarrollo de interfaces de usuario multiplataforma del que se dice será la pesadilla de .NET de Microsoft. Su nombre deriva de las siglas de XML-based User-interface Language y fue creado por la gente del proyecto Mozilla apoyándose en su motor de renderizado, Gecko, que se encarga tanto del visualizado de webs como de la construcción de la interfaz de usuario.

      Si quereis saber más sobre XUL, podeis encontrar una lista de sus principales ventajas en el documento 'The Joy of XUL' y algún tutorial en sitios como XUL-Planet.


      Nuestro primer programa en XUL

      Para que veais por encima la estructura de un programa en XUL vamos a escribir un programa de tipo 'Hola Mundo', aunque como todos los programadores que se creen originales y rebeldes en lugar de un 'Hola Mundo' nuestro programa mostrará alguna frase geek; por ejemplo 'I know kung foo'.

      Usando un editor de texto cualquiera (¿que tal vim?) escribimos lo siguiente, teniendo cuidado con las mayúsculas y las minúsculas, ya que XML es case sensitive, y lo guardamos como foobar.xul por ejemplo:

      <?xml version="1.0"?>
      <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
      <!--Esto es una ventana-->
      <window id="ventana-principal" title="The Kung Foo Style" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
      <box>
      <button label="Matrix has you" onclick="alert('I Know Kung Foo');" />
      </box>
      </window>


      Si abrimos Mozilla o Firefox, nos vamos a Archivo→Abrir y seleccionamos nuestro fichero foobar.xul veremos algo similar a esto:


      Ahora que ya habeis visto la sencillez de XUL vamos a ir línea por línea para ver que es cada cosa. Con la primera línea, <?xml version="1.0"?> lo que hacemos es declarar este archivo como un archivo xml. Un documento XUL siempre tiene que empezar con esta línea, no tiene mas importancia.

      La segunda línea nos permite indicar que hoja de estilo queremos utilizar para definir el aspecto de la aplicación. Estamos hablando de documentos css como los que se utilizan para definir el estilo de una página web, si; mientras XUL define que widgets vamos a utilizar en nuestra aplicación se usa css para definir el aspecto que tendrán estos. En este ejemplo en concreto estamos importando global.css referenciado por chrome://global/skin/ (chrome:// es un tipo especial de URL, podríamos haber utilizado una hoja de estilos creada por nosotros si quisieramos tal como si fuera un documento HTML).

      En la tercera línea tenemos un comentario. Los comentarios siempre tienen que estar entre <!– y –> como define XML y es ignorado al interpretar el documento XUL.

      Debajo, en la cuarta línea, estamos creando una ventana nueva con <window>, cuyos atributos son id para darle un nombre y poder referenciarla mas tarde, title que indica el texto a mostrar en la barra de título y xmlns que indica el espacio de nombres a utilizar. Un espacio de nombres indica los elementos que se reconocen como válidos a la hora de interpretar el fichero; en este caso en concreto solo se reconocerán los elementos definidos en XUL, eso es lo que hace la URL http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul (notar el there is only xul).

      En la sexta línea tenemos una etiqueta box, por box model, el modelo de gestión del layout (como se colocan los objetos dentro de la ventana) que utiliza XUL. Probad a eliminar el <box> y </box>, vereis que la interfaz se descoloca.

      Dentro del box utilizamos la etiqueta button para crear un botón que tendrá como texto a mostrar 'Matrix has you', definido por el atributo label. Ese onclick le sonará a la gente que utilice javascript; lo que hace es que al pulsar sobre nuestro botón (onclick) muestre un alert con el texto que le pasamos como argumento. Como habreis imaginado esto completa el cuadro de las aplicaciones XUL (por ahora): XUL define los widgets de la aplicación, con css definimos el aspecto de estos y con javascript su funcionamiento.

      Por último cerramos la etiqueta window con </window>, tal como se hace con las etiquetas de HTML (XHTML es un subconjunto de XML, como lo es XUL, de ahí las semejanzas).


      Un programa más complejo

      Vamos a ver algún nuevo concepto sobre XUL. El programa que veremos esta vez es un poco mas complejo que el que vimos en la anterior entrega. Para empezar creamos una carpeta para el programa, por ejemplo c:\caffeine\ con una imagen de tipo gif con nombre aceptar y creamos nuestro fichero caffeine.xul dentro de ese directorio con el siguiente texto:

      <?xml version="1.0"?>
      <window id="ventana-principal" title="Ventana" width="400" height="200" screenX="20" screenY="20" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
      <box>
      <button id="boton1" class="dialog" label="Aceptar" image="file://c:\caffeine\aceptar.gif" accesskey="a"/>
      <button image="file://c:\caffeine\aceptar.gif" disabled="true" accesskey="c"/>
      <button/>
      </box>
      </window>


      Como veis tenemos la primera línea que indica que el documento es un documento XML. Al crear la nueva ventana en la siguiente línea vemos algún atributo que no conociamos aún: width que indica el ancho de la ventana en pixels, height que hace lo propio con el alto y screenX y screenY que nos da la posición inicial de la ventana en pixels.

      Dentro de la ventana como vemos se defininen tres botones. En el primer botón que declaramos, boton1, tenemos un atributo class que indica la clase de botón que es boton1 (nos sirve para definir estilos distintos en la hoja de estilo, si no sabes css no te interesa); un atributo image, para mostrar una imagen en el botón y el atributo acceskey que asocia un acelerador con el botón.

      El segundo botón que creamos tiene la peculiaridad de que no tiene texto (no tiene un atributo label), sino que simplemente tiene una imagen. Además esta deshabilitado con el atributo disabled y tiene como tecla de acceso directo 'c'. Por último el tercer botón ilustra el que se puede crear objetos que no tengan atributos. En este caso dado que no definimos un texto a mostrar y tampoco una imagen el botón estará vacio.

      Si hacemos doble click sobre el archivo caffeine.xul veremos algo parecido a esto:


      Como último apunte, fijaros en que he comentado que tenemos que abrir el archivo haciendo doble click sobre el en lugar de hacerlo desde Archivo→Abrir. Esto es así por que si lo hicieramos de la segunda forma tendríamos una ventana dentro de la ventana de nuestro navegador, con lo cual no se vería el efecto de cambiar el tamaño de la ventana o cambiar el título. Además como apunte, si utilizais Mozilla Firefox y al hacer doble click sobre el archivo .xul os dice algo parecido a 'c is not a registered protocol' teneis que cambiar la asociacion para los archivos xul de firefox.exe -chrome "%1" que será seguramente lo que tengais a firefox.exe -chrome "file:%1"//.


      Comunicándonos con el usuario

      En este tercer ejemplo sobre XUL vamos a construir una versión mas elegante del Hola Mundo que nos permita introducir el texto que queremos que salga en el alert. El código del programa es el siguiente:

      <?xml version="1.0"?>
      <window id="ventana-principal" title="Caffeine" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
      <vbox>
      <hbox>
      <label value="Texto a mostrar"/>
      <textbox id="miTexto" maxlength="10"/>
      </hbox>
      <button label="Mostrar" onclick="var texto=document.getElementById('miTexto');alert(texto.value);"/>
      </vbox>
      </window>


      Ejecutad el programa y lo primero que vereis es que la ventana no ocupa todo el espacio del escritorio aún cuando no hemos especificado un ancho y un alto. Esto es así por el layout manager de XUL que se encarga de calcular la posición y el tamaño de los elementos de la interfaz de forma que no haya problemas cuando el usuario cambie el tamaño de las ventanas, por ejemplo. El layout manager de XUL se basa en dos etiquetas principalmente que son <vbox> y <hbox>. Con vbox lo que hacemos es indicar al gestor que posicione los elementos que van a estar dentro de <vbox></vbox> uno debajo de otro; con hbox, que es equivalente al <box> que hemos usado en ejemplos anteriores, le indicamos que los coloque de izquierda a derecha. Combinando estas dos etiquetas, espaciadores y los elementos flexibles podemos crear layouts complejas.

      Si echamos un vistazo al código además de un vbox y un hbox de los que ya hemos hablado vemos dos cosas nuevas, el widget label y el widget textbox. Un label o etiqueta sirve para mostrar un texto en pantalla (un texto corto, para textos largos usariamos description) y el textbox o caja de texto para dar la posibilidad de escribir al usuario. El atributo value de label indica el texto que se mostrará. En el caso del textbox le damos un nombre con id, miTexto, ya que lo necesitaremos en el código javascript para obtener el texto que escribió el usuario en él. Además usamos el atributo maxlenght para indicarle que el máximo número de caractéres que pueden introducirse es 10.

      Como último apunte un vistazo al onclick del botón ya que aquí es donde ocurre toda la magia. Como ya vimos en el ejemplo del 'Hola Mundo', onclick define una acción que se ejecutará cuando se haga click sobre ese elemento; en este caso cuando se presione el botón mostrar se ejecutará el código javascript que le pasamos. No es el objeto de estas entradas el explicar javascript pero basta con saber que se declara una variable llamada texto que apunta al elemento de la interfaz cuyo nombre es 'miTexto' y después se crea una ventana alert con el texto que contenga este.


      Otros widgets de XUL

      Esta vez vamos a terminar de ver los widgets básicos de XUL, junto con los botones, las cajas de texto o las etiquetas que ya vimos anteriormente. El código del programa ejemplo es el siguiente:

      <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
      <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

      <tabbox orient="vertical">
      <tabs orient="horizontal">
      <tab label="Radiobuttons"/>
      <tab label="Checkboxes"/>
      <tab label="Listbox"/>
      <tab label="Imagenes"/>
      </tabs>

      <tabpanels>
      <radiogroup orient="vertical">
      <radio label="Cafe solo"/>
      <radio label="Cafe con leche"/>
      <radio label="Descafeinado"/>
      </radiogroup>
      <box>
      <checkbox label="Donuts"/>
      <checkbox label="Croisants"/>
      <checkbox label="Caracolas"/>
      </box>
      <image src="file://C:\widgets\mozilla.png"/>
      </tabpanels>
      </tabbox>

      </window>


      Las pestañas se declaran mediante la etiqueta tabbox. orient nos dice si la orientación, en este caso de las pestañas, será horizontal o vertical. Cada una de las pestañas esta compuesta por dos componentes diferenciados, las pestañas en si, que vienen definidas por una serie de etiquetas tab dentro de un elemento tabs y el contenido de las pestañas que se define dentro de tabpanels. Dentro de tabpanels habrá tantos elementos como pestañas definamos en tabs (esto no es necesariamente cierto pero vamos a simplificar) y se seguirá una correspondecia por orden de declaración a la hora de asignar el contenido que corresponde a cada pestaña. En este caso, por ejemplo, en la pestaña 1 tenemos un elemento radiogroup compuesto por varios elementos radio, en la pestaña 2 tenemos una serie de checkboxes que agrupamos en un box para que sea un solo elemento y en la tercera pestaña tenemos una imagen.

      Veamos ahora los otros widgets. En primer lugar, en la primera pestaña tenemos radiobuttons, que representan opciones excluyentes. Un grupo de radiobuttons se define con radiogroup y cada uno de los radiobuttons con radio, como podemos ver. Los checkboxes son opciones no excluyentes que se definen con la etiqueta checkbox. Por último las imágenes se definen con la etiqueta image que tiene como atributo la ruta a la imagen (src de source, fuente).


      Creación de Menús

      Antes de empezar con cosas mas serias vamos a ver como se implementan los menús en XUL.

      <?xml version="1.0"?>
      <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
      <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
      <menubar>
      <menu label="Archivo">
      <menupopup>
      <menuitem label="Nuevo"/>
      <menuseparator/>
      <menuitem label="Abrir"/>
      <menuitem label="Salvar"/>
      <menuitem label="Cerrar"/>
      </menupopup>
      </menu>
      <menu label="Editar">
      <menupopup>
      <menuitem label="Deshacer"/>
      <menuseparator/>
      <menuitem label="Copiar"/>
      <menuitem label="Cortar"/>
      <menuitem label="Pegar"/>
      </menupopup>
      </menu>
      <menu label="Ver">
      <menupopup>
      <menuitem label="Regla"/>
      <menu label="Fuente">
      <menupopup>
      <menuitem label="Arial"/>
      <menuitem label="Verdana"/>
      </menupopup>
      </menu>
      <menu label="Color">
      <menupopup>
      <radiogroup>
      <radio label="Rojo"/>
      <radio label="Azul"/>
      <radio label="Negro"/>
      <radio label="Verde"/>
      </radiogroup>
      </menupopup>
      </menu>
      <menuitem label="Pantalla Completa"/>
      </menupopup>
      </menu>
      </menubar>
      </window>


      menubar define la barra de menús. Dentro de menubar tenemos un conjunto de etiquetas menu que son las que definen las entradas de menú en si. Si al pulsar sobre el menú se va a desplegar una lista de submenús, entonces utilizamos menupopup y menuitem para cada uno de los submenús. En el caso de que no hubieramos agrupado los submenús (menuitems) en un menupopup se habrían mezclado todas las entradas en una sola, que no es lo que queremos. Además tenemos otro elemento que es menuseparator, que introduce una línea para dividir el menú en partes. Notar también que los submenús también pueden ser menús con varias entradas como vemos en el caso de fuente en que definimos un nuevo menú y no un menuitem. Como último comentario decir que en lugar de menuitems o menús, como entradas dentro de los menús también podríamos tener otros elementos como checkboxes o radiobuttons como vemos en el caso del menú color.


      RDF

      Vamos a hacer un inciso para hablar sobre RDF. RDF es un estándar de la W3C cuyo nombre deriva de las siglas de 'Resource Description Framework' y que es un subconjunto de XML, al igual que XUL, que nos sirve para expresar hechos (cosas que son ciertas, la información en forma de predicados que tenemos sobre el mundo real). Sería algo parecido a los predicados de Prolog. Por ejemplo, un predicado del tipo 'A Linus le gustan los pingüinos' en RDF podría expresarse como:

      <Description about="Linus">
      <le-gustan>pingüinos</le-gustan>
      </Description>


      La etiqueta Description sirve para representar uno o mas hechos, con un atributo about para indicar sobre quien es ese hecho, es decir, el sujeto del hecho. Description puede contener una o varias etiquetas hijas siendo cada una de ellas un predicado.

      <Description about="Linus">
      <le-gustan>pingüinos</le-gustan>
      <informatico>true</informatico>
      <linuxero>true</linuxero>
      <nacionalidad>finlandesa</nacionalidad>
      </Description>


      En este ejemplo definimos una serie de predicados sobre Linus, con una etiqueta definida por nosotros mismos para desribir ese predicado y con el valor entre las etiquetas.

      Ahora, ¿como expresariamos el hecho de que a Linus le gustan además de los pingüinos los sombreros o los camaleones?. Podríamos usar varios predicados le-gustan pero RDF nos proporciona un método mejor. En RDF se definen tres etiquetas que sirven como contenedoras: <Bag>, que define un conjunto de items; <Seq>, que define un conjunto de items ordenados y <Alt>, que define un conjunto de elementos que son alternativos, es decir, que se consideran equivalentes. Los elementos de un contenedor se encierra entre <li> y </li> (li de list, lista, al igual que la etiqueta de XHTML). Veamos un ejemplo:

      <Description about="Linus">
      <Bag ID="Gustos">
      <li>pingüinos</li>
      <li>sombreros</li>
      <li>camaleones</li>
      </Bag>
      <informatico>true</informatico>
      <linuxero>true</linuxero>
      <nacionalidad>finlandesa</nacionalidad>
      </Description>


      Ahora tenemos una lista de los gustos de Linus usando un Bag que sería equivalente a un predicado con varios valores. Para identificar el predicado que define este Bag usamos el atributo ID. Seq y Alt serían similares, tan solo cambia su significado.

      Para finalizar esta pequeña introducción a RDF vamos a ver un ejemplo completo para explicar un par de cosas que quedan en el tintero.

      <RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:BEBIDAS="http://www.caffeine.com/rdf#">

      <RDF:Bag about="http://www.caffeine.com/tipos-de-bebida">
      <RDF:li>
      <RDF:Description about="http://www.caffeine.com/infusiones/te">
      <BEBIDAS:nombre>Te</BEBIDAS:name>
      <BEBIDAS:precio>1,12</BEBIDAS:precio>
      </RDF:Description>
      </RDF:li>
      <RDF:li>
      <RDF:Description about="http://www.caffeine.com/infusiones/tila">
      <BEBIDAS:nombre>Tila</BEBIDAS:name>
      <BEBIDAS:precio>0,9</BEBIDAS:precio>
      </RDF:Description>
      </RDF:li>
      <RDF:li>
      <RDF:Description about="http://www.caffeine.com/cafes/solo">
      <BEBIDAS:nombre>Cafe solo</BEBIDAS:name>
      <BEBIDAS:precio>1,2</BEBIDAS:precio>
      </RDF:Description>
      </RDF:li>
      </RDF:Bag>
      </RDF:RDF>


      Lo primero que tenemos que comentar es la línea con la que comienza el RDF. Esta es similar al window de XUL en el que definimos que espacio de nombres vamos a utilizar. Usaremos RDF que está definida en tal URL y BEBIDAS que está definido en tal otra. Relacionado con esto, el RDF: que aparece antes de las palabras clave de RDF o el BEBIDAS: que aparece antes de los nombres de los predicados indica el espacio de nombres que estamos utilizando, es decir, RDF:li por ejemplo significa que nos estamos refiriendo a la etiqueta li que está definida dentro de RDF.


      El registro chrome

      Hasta ahora dividiamos un programa XUL en la interfaz en si, creada con XUL; el aspecto de los widgets, definido con CSS y la funcionalidad, programada en javascript. Sin embargo javascript no nos permite cosas como acceder al disco duro, de modo que si tuvieramos que limitar la funcionalidad de los programas basados en XUL a lo que podemos hacer con javascript, estos no tendrían demasiada utilidad.

      La solución a este problema nos viene dada en forma de una libreria escrita en código dependiente de la plataforma llamada XPCOM y una capa intermedia entre javascript y esta librería llamada XPConnect, que traduce los objetos XPCOM en objetos javascript que puedan ser manipulados en nuestro programa.

      El problema de esto es que la seguridad de Mozilla dejaría mucho que desear si cualquier script pudiera hacer cosas como borrar los archivos del disco duro. Aquí es donde vemos la utilidad de chrome.

      Como ya se comentó la url chrome:// se refiere al directorio chrome dentro del directorio de instalación de Mozilla/Firefox. Solo los scripts que se encuentren en este directorio tienen permiso para utilizar XPConnect, lo cual implica que para usar los objetos de XPCOM necesitamos instalar nuestra aplicación en chrome. Sin embargo no basta simplemente con mover nuestros ficheros a ese directorio, si no que tenemos que añadir una serie de entradas a installed-chrome.txt para que nuestra aplicación sea añadida al 'registro chrome' de forma que Mozilla pueda resolver las urls chrome:// al directorio en que esta instalada nuestra aplicación.

      Lo primero que tenemos que hacer es crear un archivo de tipo rdf llamado contents.rdf que proporcionará información a Mozilla sobre el nombre de la aplicación, el autor, la versión...

      <?xml version="1.0"?>

          <RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:chrome="http://www.mozilla.org/rdf/chrome#">

          <RDF:Seq about="urn:mozilla:package:root">
          <RDF:li resource="urn:mozilla:package:caffeine"/>
          </RDF:Seq>

          <RDF:Description about="urn:mozilla:package:caffeine"
          chrome:displayName="The Caffeine XPerience"
          chrome:author="Zootropo"
          chrome:name="caffeine"
          chrome:extension="true"/>

          </RDF:RDF>



      En este ejemplo displayName es el nombre completo para la aplicación; author el autor de la aplicación, name el identificador de la aplicación (como se referirá Mozilla a él, tiene que ser igual que el valor después de urn:mozilla:package:) y extension indica si la aplicación es una extensión, de forma que se mostrará en la lista de extensiones de Mozilla en el caso de que sea true (cierto).

      Una vez creado nuestro fichero contents.rdf lo copiamos a la carpeta de nuestra aplicación. Editemos ahora el fichero installed-chrome.txt que se encuentra dentro del directorio chrome, teniendo en cuenta cerrar antes el navegador, para registrar nuestra aplicación de forma que Mozilla sepa donde encontrarla. Al final del fichero añadimos por ejemplo para el caso de que el directorio de la aplicación sea caffeine/content/caffeine/ dentro del directorio chrome:

        content,install,url,resource:/chrome/caffeine/content/caffeine/

      Solo queda borrar el fichero chrome.rdf que contiene la información sobre las extensiones registradas en chrome para que vuelva a crearse cuando ejecutemos Mozilla/Firefox y tenga en cuenta nuestra aplicación. La información de cada una de las aplicaciones la recolectará basándose en installed-chrome.txt para encontrarla y en el contents.rdf que creamos para procesar el contenido de nuestra aplicación.

      Ahora deberíamos ser capaces de poder ejecutar cualquier archivo xul de nuestra aplicación (y por añadidura referirnos a cualquier archivo de nuestra aplicación) usando una url chrome de la forma:

        chrome://id-aplicacion/content/archivo.xul

      Por ejemplo para abrir el archivo foo.xul de la aplicación con id caffeine podríamos simplemente escribir chrome://caffeine/content/foo.xul


      Modularidad en XUL

      A la hora de organizar los ficheros de nuestra aplicación se sigue un estándar de facto en el que tenemos tres subdirectorios dentro de la carpeta de nuestra aplicación: content, local y skin.

      El directorio content incluye un subdirectorio con el nombre de nuestra aplicación que a su vez contiene todos los archivos xul de la aplicación, además de los archivos js con el código javascript de la aplicación y un fichero contents.rdf que nos dice entre otras cosas cual es el archivo .xul principal.

      En el directorio locale se incluyen una serie de subdirectorios con el código del idioma correspondiente, por ejemplo es-ES para castellano o en-US para inglés de estados unidos. Dentro de cada uno de estos directorios tenemos un subdirectorio con el nombre de la aplicación que incluye a su vez los ficheros DTDque sirven para separar la aplicación de los mensajes de esta para facilitar el proceso de traducción y un fichero contents.rdf.

      Por último el directorio skin contiene otro subdirectorio de nombre classic que incluye un directorio con el nombre de nuestra aplicación con los ficheros css que se utilizan para modificar el aspecto de la aplicación y un archivo contents.rdf.

      Hasta ahora el código javascript que hemos utilizado estaba incrustado dentro de los ficheros xul, en el siguiente ejemplo veremos como importar el código de un fichero js separado del código xul. Como simple comentario, el código css que hemos utilizado hasta ahora estaba almacenado en archivos css aparte como dicta la norma para conseguir modularidad; sin embargo, al igual que el código javascript, el código css puede almacenarse en un fichero aparte o incrustado dentro del propio archivo xul.

      <?xml version="1.0"?>
          <!DOCTYPE window SYSTEM "chrome://caffeine/locale/caffeine.dtd">

          <?xml-stylesheet href="chrome://caffeine/skin/caffeine.css" type="text/css"?>
          <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:nc="http://home.netscape.com/NC-rdf#">

          <script type="application/x-javascript"
          src="chrome://caffeine/content/caffeine.js"/>

          <button onclick="funcion();" label="&nombreBoton;" accesskey="&teclaAcceso"/>

          </window>


      La línea de script es la que se encarga de importar el código javascript desde el fichero javascript especificado de forma que podemos usar la función funcion() al hacer click en el botón aunque no la hallamos definido en este fichero. Podemos ver también la forma en que se importan los ficheros dtd con los mensajes de la aplicación en la segunda línea del código fuente. Hasta ahora no habíamos utilizado ficheros dtd, sino que incluíamos el texto de la aplicación imbuida dentro de esta; ahora con estos ficheros llevamos la modularidad de xul hasta el extremo, separando del código xul el funcionamiento, la apariencia y los mensajes.

      El uso de los mensajes que se definen en los DTDs podemos verlo en el label y la accesskey del botón, un símbolo ampersand, el nombre que le dimos al mensaje en el dtd y punto y coma. El fichero DTD para este programa sería:

          <!ENTITY nombreBoton "Mi Boton">
          <!ENTITY teclaAcceso "M">


      Para cada mensaje como vemos tenemos un !ENTITY, la segunda entrada de !ENTITY es el nombre del mensaje que se utilizará para referirse a él en el código XUL como ya vimos y el tercero el valor. En este DTD nombreBoton es "Mi Boton" pero podríamos tener otro DTD para el inglés en cuyo caso sería "My Button", etc, de forma que la traducción de la aplicación es mas sencilla al separar el código y los mensajes.

      Por último como ya dijimos cada uno de los directorios de la aplicación incluye un fichero contents.rdf para poder registrar ese directorio en el registro chrome. Veamos el caso del contents.rdf de los locales:

          <?xml version="1.0"?>
          <RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:chrome="http://www.mozilla.org/rdf/chrome#">

          <!-- Lista de todos los locales que incluimos, en este caso solo es-ES -->
          <RDF:Seq about="urn:mozilla:locale:root">
          <RDF:li resource="urn:mozilla:locale:es-ES"/>
          </RDF:Seq>

          <!-- Informacion sobre cada uno de los locales -->
          <RDF:Description about="urn:mozilla:locale:es-ES"
          chrome:displayName="Castellano (ES)"
          chrome:name="es-ES">
          <chrome:packages>
          <RDF:Seq about="urn:mozilla:locale:es-ES:packages">
          <RDF:li resource="urn:mozilla:locale:es-ES:caffeine"/>
          </RDF:Seq>
          </chrome:packages>
          </RDF:Description>

          </RDF:RDF>


      Y el contents.rdf de los skins:

          <?xml version="1.0"?>

          <RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:chrome="http://www.mozilla.org/rdf/chrome#">

          <RDF:Seq about="urn:mozilla:skin:root">
          <RDF:li resource="urn:mozilla:skin:classic/1.0" />
          </RDF:Seq>

          <RDF:Description about="urn:mozilla:skin:classic/1.0">
          <chrome:packages>
          <RDF:Seq about="urn:mozilla:skin:classic/1.0:packages">

          </RDF:Seq>
          </chrome:packages>
          </RDF:Description>

          </RDF:RDF>



      Estos dos contents.rdf no necesitan comentarios. Son muy parecidos al contents.rdf del directorio contents. Tan solo queda registrar en el registro chrome contents, locals y skins. Si recordamos en el anterior post sobre XUL al registrar el contents añadíamos a installed-chrome.txt una línea similar a esta:

        content,install,url,resource:/chrome/caffeine/content/caffeine/

      Si echamos un vistazo a las demás entradas en installed-chrome veremos que algunas comienzan con skin, otras con locale y otras con contents. Esto es lo único que tenemos que cambiar a la hora de registrar skins y locales, lo demás es similar, por lo tanto para nuestra aplicación de ejemplo tendríamos que añadir las líneas:

        skin,install,url,resource:/chrome/caffeine/content/caffeine/
        locale,install,url,resource:/chrome/caffeine/locale/es-ES/
        content,install,url,resource:/chrome/caffeine/skin/classic/caffeine/



      Nuestra primera extensión

      Ahora que hemos visto un poco por encima como funciona XUL vamos a ponernos un poco mas serios y vamos a crear una pequeña extensión para nuestro navegador. Por ahora algo sencillo como añadir una nueva entrada de menú al menú de herramientas de Firefox, que nos muestre un alert con la hora del sistema cada vez que se haga click sobre él. El proceso para Mozilla sería un proceso bastante parecido. Para ello tenemos que ver que son los overlays, cuya traducción al castellano sería algo asi como superposiciones.

      Lo primero vamos a recordar que toda la interfaz de Mozilla y Firefox esta hecha con XUL, por lo tanto será razonable suponer que en algún lugar tiene que haber un fichero xul que lo define. Y acertariais al hacer esta suposición. La interfaz del navegador esta definida en un archivo llamado browser.xul en el subdirectorio chrome dentro de la carpeta en la que esta instalado nuestro navegador, pero si entrais en esa carpeta para echar un vistazo al código no lo encontrareis. browser.xul esta empaquetado dentro de uno de esos archivos .jar que veis.

      Un archivo jar es simplemente un archivo .zip con la extensión renombrada. Podemos descomprimirlo con winzip u otro programa de compresión de archivos. Si descomprimimos browser.jar tendremos una carpeta browser que alberga una carpeta content en la que tenemos a su vez las carpetas browser y browser-region. Dentro de la primera se encuentra además del browser.xul al que nos referíamos otros archivos .xul, archivos js con código javascript y archivos css, hojas de estilo.

      Si abrimos el archivo browser.xul tendremos una ventana del navegador de Firefox pero con la peculiaridad de que no veremos las barras de herramientas, los botones u otros widgets de las extensiones que tengamos instaladas. Esto es así por que cuando abrimos una ventana del navegador estamos abriendo browser.xul, pero también otros archivos .xul que se superponen. Sería algo así como coger varios dibujos en papel cebolla y ponerlos uno encima de otro, algo así como las capas de Photoshop. Esto es lo que vamos a ver ahora, el overlay.

      Lo primero que tenemos que hacer es crear una carpeta para nuestra aplicación, por ejemplo 'hora' completando una estructura de directorios hora/content/hora. Dentro del directorio mas profundo de esta jerarquía creamos un archivo hora.xul con el siguiente código:

          <?xml version="1.0"?>

          <overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:nc="http://home.netscape.com/NC-rdf#">

          <popup id="menu_ToolsPopup">

          <menuitem
          oncommand="fecha=new Date(); hora=fecha.getHours(); minuto=fecha.getMinutes(); segundo=fecha.getSeconds(); alert(hora + ' : ' + minuto + ' : ' + segundo);" label="Mostrar Hora;"/>

          </popup>

          </overlay>


      Lo que estamos haciendo aquí es crear un documento XUL que solo contiene una entrada de menú dentro de un popup que queremos superponer sobre el navegador. La única diferencia con los ejemplos que hemos visto hasta ahora es que en lugar de definir una ventana definimos un overlay pero aparte del nombre no hay mucha diferencia. Simplemente indicamos a Mozilla que este no es un documento xul completo, si no que vamos a combinarlo con otro/s documentos xul.

      Ahora veamos como funcionaría el overlay con un caso sencillo antes de pasar a mayores. Supongamos un archivo XUL que importa el overlay que acabamos de definir; para ello usaría algo parecido a este código:

          <?xul-overlay href="chrome://hora/content/hora.xul"?>

      Lo que ocurriría entonces es que para cada elemento con un id definido en el archivo de overlay se buscaría el mismo elemento con el mismo id en el documento sobre el que queremos superponer. Antes de nada tendríamos que haber abierto el fichero browser.xul para ver donde se definen las entradas de menú del menú herramientas y cual es el ID de conjunto que las contiene. Ese trabajo ya esta hecho; como se puede ver en el código tenemos un elemento popup con id menu_ToolsPopup, aquí es donde está la clave.

      En el caso de que no se encuentre una instancia de ese elemento con ese ID entonces este elemento no se tiene en cuenta al hacer el overlay. Si por el contrario si se encuentra, entonces el elemento y todo lo que se defina dentro de este en el overlay pasará a superponerse al documento raíz, lo cual quiere decir que el elemento del documento raíz adquirirá todos los atributos que se definan en el overlay además de todos sus subelementos.

      En este ejemplo el documento raíz es el que se encargaba de añadir el overlay usando la etiqueta xul-overlay, sin embargo esto no nos es de utilidad en nuestro caso ya que no queremos tener que cambiar el código de browser.xul. La solución es hacer que sea el overlay el que diga a que documento se tiene que superponer. Esto podemos hacerlo añadiendo la información de los overlay a nuestro contents.rdf

          <?xml version="1.0"?>

          <RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:chrome="http://www.mozilla.org/rdf/chrome#">

          <RDF:Seq about="urn:mozilla:package:root">
          <RDF:li resource="urn:mozilla:package:hora"/>
          </RDF:Seq>

          <RDF:Description about="urn:mozilla:package:hora"
          chrome:displayName="Mostrar Hora 0.1"
          chrome:author="Zootropo"
          chrome:authorURL="http://zootropo.blogspot.com"
          chrome:name="hora"
          chrome:extension="true"
          chrome:description="Añade una opción al menú de herramientas para mostrar la hora actual.">
          </RDF:Description>

          <RDF:Seq about="urn:mozilla:overlays">
          <RDF:li resource="chrome://browser/content/browser.xul"/>
          </RDF:Seq>

          <RDF:Seq about="chrome://browser/content/browser.xul">
          <RDF:li>chrome://hora/content/hora.xul</RDF:li>
          </RDF:Seq>

          </RDF:RDF>


      Vemos que tenemos un par de listas nuevas, una referida a urn:mozilla:overlays en el que los elementos de la secuencia son los documentos sobre los que se va a hacer el overlay (en este caso el browser.xul para superponer a nuestro navegador) y otra secuencia con el archivo xul sobre el que hacemos el overlay como sujeto y como entradas de la secuencia los archivos xul a superponer.

      Borramos overlay.rdf como en el post anterior, añadimos una entrada nueva a installed-chrome.txt para el content de nuestra aplicación (no tendremos locale porque la única función javascript que utilizamos esta embebida en el archivo xul ni skin ya que no utilizamos ningún css) y reiniciamos nuestro navegador, tras lo cual tendremos una nueva entrada al final del menú de herramientas que nos permitirá ver la hora del sistema.



      XPI

      Ahora que ya hemos terminado nuestra pequeña extensión para Firefox vamos a ver como podemos crear un xpi para que se instale automáticamente. La extensión xpi viene de XPInstall donde XP se refiere a Cross (X) Platform o multiplataforma, es decir, que puede ser ejecutado en distintas plataformas (Windows, Linux, Mac OS,...).

      Un xpi es un simple archivo zip con extensión renombrada que contiene un fichero de instalación y los ficheros que componen la extensión. En el caso de las versiones anteriores a la 0.9 se utilizaba install.js como script instalador, ahora en cambio se utiliza un fichero rdf, install.rdf, pero podemos incluir ambos si queremos que la extensión se pueda instalar en la versión 0.9 y también en las anteriores.

      Un archivo install.rdf tendría un aspecto parecido a este:

          <?xml version="1.0"?>
          <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
          <Description about="urn:mozilla:install-manifest">
          <em:id>{eb78c871-3d9d-433f-b49b-12468119be89}</em:id>
          <em:name>Mostrar Hora</em:name>
          <em:version>0.1</em:version>
          <em:description>Muestra la hora del sistema en un alert al hacer click sobre la entrada de menu correspondiente.</em:description>
          <em:creator>Zootropo</em:creator>
          <em:homepageURL>http://zootropo.blogspot.com </em:homepageURL>

          <em:file>
          <Description about="urn:mozilla:extension:file:hora.jar">
          <em:package>/content/hora/</em:package>
          </Description>
          </em:file>
          <em:targetApplication>
          <Description>
          <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
          <em:minVersion>0.9</em:minVersion>
          <em:maxVersion>0.9</em:maxVersion>
          </Description>
          </em:targetApplication>

          </Description>
          </RDF>


      Tenemos primero una serie de predicados de información sobre nuestra aplicación que son los siguientes:

      • em:id que se refiere a un id único que podemos generar con esta utilidad de Microsoft y no al identificador de la extensión
      • em:name, el nombre de la extensión
      • em:version, la versión de nuestra extensión.
      • em:description, una descripción de la utilidad de nuestra aplicación.
      • em:creator, nombre del creador de la aplicación.
      • em:homepageURL, página web de la extensión.
      • em:optionsURL, ventana que se mostrará al hacer click sobre las preferencias.
      • em:aboutURL, ventana que se mostrará como About de la aplicación.
      • em:iconURL, icono para identificar la extensión.
      • em:updateURL, URL opcional para la autoactualización.
      Tenemos después un predicado em:file que agrupa información sobre los ficheros de nuestra aplicación, donde se encuentra content, skin y locale dentro del archivo .jar, y otro predicado em:targetApplication sobre el programa para el que está destinado nuestra extensión. em:id se refiere al id del navegador, en este caso Firefox y minVersion y maxVersion se refieren respectivamente a la versión mínima y máxima de la aplicación.

      Si no quereis complicaros podeis utilizar para crear los xpi un script creado por Ted Mielczarek que podeis encontrar en su página web. También podeis consultar la traducción del documento de Ben Gooder sobre install.rdf.

      Ahora que tenemos todos los archivos necesarios lo primero que tenemos que hacer es crear un archivo jar que incluya los archivos de nuestra extensión. Comprimimos en un mismo archivo zip las carpetas content, locale y skin de nuestra aplicación (o content solo si no hemos definido las otras dos). Cambiamos la extensión del archivo resultante a .jar de forma que nos quede un archivo hora.jar en este ejemplo y ya tenemos el archivo jar que empaqueta nuestra aplicación, nos queda empaquetar el .jar y el archivo de instalación en un xpi. Para eso creamos una carpeta chrome a la que movemos hora.jar y comprimimos en un .zip la carpeta chrome y el install.rdf (e install.js en el caso de que lo tengamos) y renombramos la extensión del archivo a .xpi.

      El archivo xpi resultante para que comprobeis como se instala automáticamente como cualquier otra extensión de firefox es este.


      Fuente Original: Mundo Geek
      Autorizado por el autor original: zootropo
      Licencia: http://creativecommons.org/licenses/by/2.0/
      #26

      Pues eso... la verdad es que hace como dos meses cuando veo algun post mio aparece esto:


      No habia reportado nada ya que la verdad no me interesa si tengo o no mensajes... pero ya me entró el bichito de la curiosidad ¿porqué pasa eso, ehhh?. He visto en otros foros SMF y no pasa esto. ¿a alguno de uds. les pasa?

      Saludos!!![/color]
      #27

      Pués se que ya se ha hablado del sistema de estrellas, y que el-brujo quitó esa vaina. Pero, no he visto un foro (en otra web) que tenga eso, y que deje que uno ayude a otros usuarios a incrementar estrellas.

      Talvez esa sea mi duda: ¿las estrellas se incrementaban de acuerdo a la cantidad de mensajes? o... ¿los demás usuarios hacian que las estrellas se incrementaran?

      Lo que pasa es que en la epoca en que existia eso no conocía esta web. Es más, nisiquiera tenía acceso a internet.

      Nada, solo eso. Si el post sobra, adelante podeis borrarlo. Solo que no me quiero quedar con la duda.

      Saludos!!!
      #28

      Pues por todos es bien sabido que existen usuarios Colaboradores y Moderadores, que se la pasan colaborando (valga la redundancia), y por ello recolectan bastante tiempo en las estadísticas. Por ejemplo el caso de Riven Ward, que a reunido como 80 dias conectado al foro, muy por encima de el famoso brujo.

      Pero hoy fisgoneando, me doy cuenta de que un usuario con el nick chapus, tenia como 2000 dias conectado. Esta es una cifra enorme, casi imposible, mejor dicho imposible. Además no tiene ni un post.

      Entonces mi pregunta es: ¿es un error del foro? o talvez ¿se está explotando un bug?. ¿quien me saca de la duda?.

      Por si las moscas, les dejo el link para las estadísticas del foro --Aquí-- para que se pillen mejor.

      Saludos!!!
      #29
      Nada, quería saber porqué se quito la opción de borrar (), para los usuarios sin privilegios.

      Saludos!!!
      #30
      Esto lo encontré por ahí y me pareció curioso:

      Se revelan las primeras imágenes de la llegada de este clásico personaje al Xbox 360.

      Hudson Soft ha liberado a través de la revista Famitsu, las primeras imágenes del juego Bomberman Act Zero, el cuál marca la llegada del clásico personaje a la nueva máquina de Microsoft.

      Este juego se situará en el futuro de la serie, teniendo un cambio estético importante, mostrandose como un juego más adulto. El título saldrá al mercado japones el próximo 25 de Mayo, haber como toman los japos el cambio de estética "cute" que siempre ha tenido el personaje, por algo más maduro.

      He aquí las imágenes:


      [/color]
      #31
      'God of War' se ha alzado con el premio al mejor juego del año que otorga anualmente la Academia de las Artes y las Ciencias Interactivas (AIAS). El videojuego de la PS2 se ha impuesto a 'Nintendogs', 'Call of Duty II', 'Guitar Hero' y al esperado 'Shadow of The Colossus', que sale a la venta mañana. 'Battlefield II' ha sido galardonado como mejor juego de ordenador del año.[/b]

      El juego desarrollado por Sony, que optaba a premio en 12 categorías, ha conquistado finalmente siete. Además del ya citado, ha sido seleccionado como mejor juego para consola, mejor animación, mejor música original, mejor diseño de sonido, mejor juego de acción y aventura y mejor personaje masculino por su protagonista, Kratos.

      [/center]

      Por otro lado, 'Guitar Hero', un videojuego en el que hay que convertirse en una estrella del rock, ha recibido el galardón al más innovador por su concepto de juego. También ha triunfado su banda sonora y su diseño, lo que le ha convertido en el mejor juego familiar del año.

      Pese a su gran tirón entre los usuarios, 'Nintendogs' se ha llevado una pequeña decepción. Estaba incluso nominado como mejor juego del año, pero sólo ha conquistado premios por su innovador sistema de juego y como mejor juego para una consola portátil.

      'Shadow of the Colossus' también se ha quedado a las puertas de varios premios, puesto que sólo ha podido lograr el otorgado a la mejor dirección de arte y mejor ingeniería visual.



      Más información en el foro: http://foro.elhacker.net/index.php/topic,108902.0.html
      #32

      La Academia de las Ciencias y las Artes Interactivas norteamericanas ha entregado los "Oscars" del mundo de los videojuegos.

      A través de un artículo publicado en Plastico.tv nos enteramos que el pasado 9 de febrero se entregaron los "Interactive Achievement Awards", para muchos los "Oscars" del mundo de los videojuegos.

      El listado de ganadores:

      Juego del año:
      - God of War (Sony Computer Entertainment America, Sony Computer Entertainment America-Santa Monica)

      Juego del año para PC:
      - Battlefield 2 (EA, Digital Illusions)

      Juego del año para Consola:
      - God of War (Sony Computer Entertainment America, Sony Computer Entertainment America-Santa Monica)

      Logro Excepcional en jugabilidad:
      - Guitar Hero (Red Octane, Harmonix)

      Logro Excepcional: Animación
      - God of War (Sony Computer Entertainment America, Sony Computer Entertainment America-Santa Monica)

      Logro Excepcional: Dirección de Arte
      -Shadow of the Colossus (Sony Computer Entertainment America)

      Logro Excepcional: Banda Sonora
      - Guitar Hero (Red Octane, Harmonix)

      Logro Excepcional: Composición Musical Original
      - God of War (Sony Computer Entertainment America, Sony Computer Entertainment America-Santa Monica)

      Logro Excepcional: Diseño de Sonido
      - God of War (Sony Computer Entertainment America, Sony Computer Entertainment America-Santa Monica)

      Logro Excepcional: Desarrollo de Historia y Personajes
      - Call of Duty: Big Red One (Activision, Treyarch)

      Logro Excepcional: Ingeniería en Jugabilidad (EMPATE)
      - Nintendogs (Nintendo, Nintendo EAD)
      - Guitar Hero (Red Octane, Harmonix)

      Logro Excepcional: Juego Online
      - Battlefield 2 (EA, Digital Illusions

      Logro Excepcional: Ingeniería Visual
      - Shadow of the Colossus (Sony Computer Entertainment America)

      Logro Excepcional: Diseño de Juego
      - Guitar Hero (Red Octane, Harmonix)

      Mejor Desempeño de Personaje : Masculino
      - God of War (Sony Computer Entertainment America, Sony Computer Entertainment America-Santa Monica)

      Mejor Desempeño de Personaje: Femenino
      - Jade Empire (Microsoft, Bioware)

      Juego Deportivo del Año
      - SSX On Tour (EA, EA Canada)

      Juego en Primera Persona del Año
      - Battlefield 2 (EA, Digital Illusions)

      Juego de Rol del Año
      - Jade Empire (Microsoft, Bioware)

      Juego de Peleas del Año
      - Soul Calibur III (Namco)

      Juego de Acción/Aventura del Año
      - God of War (Sony Computer Entertainment America, Sony Computer Entertainment America-Santa Monica)

      Juego de Carreras del Año
      - Need for Speed: Most Wanted (EA, EA-Vancouver)

      Juego Infantil del Año
      - We Love Katamari (Namco)

      Juego Descargable del Año
      - WIK: Fable of Souls (Microsoft, Reflexive)

      Juego Familiar del Año
      - Guitar Hero (Red Octane, Harmonix)

      Juego Simulador del Año
      - The Movies (Activision, Lionhead Studios)

      Juego de Estrategia del Año
      - Civilization IV (2K Games, Firaxis)

      Juego del Año MMORPG (EMPATE)
      - City of Villains (NCsoft, Cryptic Studios)
      - Guild Wars (NCsoft, ArenaNet)

      Juego Portátil del Año
      - Nintendogs (Nintendo, Nintendo EAD)

      Juego del año para Teléfono Movil
      - Ancient Empires II (Glu Mobile)
      #33

      Pués eso. Quisiera saber si existe un programa que me permita redimensionar varias imagenes.

      Es decir, por ej. tengo 75 imagenes, con tamaños que varian entre 1205 y 1650 pixeles. Por ej., una imagen de 1200x1650 px, otra imagen de 1205x1500, y así. Y quiero que todas queden del mismo tamaño.

      Sé que con el PhotoPaint de Corel, o con el PhotoShop de Adobe se pueden redimensionar imágenes, pero sería muy difícil cambiarles el tamaño una por una.

      Por esto necesito un software que redimensiones las imágenes de manera recursiva.

      Espero puedan ayudarme, un saludo y disculpen mi ignorancia. ;D
      #34
      El grupo de orientación parental estadounidense Family Media Guide (FMG) publicó esta semana una lista con los diez videojuegos más violentos actualmente disponibles en el mercado, así como las razones que los llevaron a enlistarlos.

      Su selección se basa en los índices de su filial PSVratings, que clasifica los lanzamiento de películas, programas de TV y juegos de video según el rango de violencia, sexo y obscenidades que contengan en níveles que van desde "gráfico" a "inexistente".

      Reproducida por la publicación especializada Gamespot, la lista de FMG dice incluir algunos de los "videojuegos más ultraviolentos jamás producidos" y va de la siguiente forma, sin un orden especial de 'preferencias':

      Resident Evil 4: "El jugador es un agente de fuerzas especiales enviado a recuperar a la hija secuestrada del Presidente. Durante el primer minuto de juego, es posible ver el cuerpo colgado de una mujer... con un tridente que le atraviesa la cara".

      Grand Theft Auto: San Andreas: "El jugador es un joven que trabaja para pandillas a fin de obtener respeto. Sus misiones incluyen asesinatos, robos y destrucción a todos los niveles imaginables. El jugador recupera su salud visitando prostitutas para luego recuperar su dinero golpéandolas hasta matarlas. El jugador puede causar tantos desastres como desee sin realizar progresos en la trama del juego".

      God of War: "El jugador se vuelve un guerrero sin compasión en su busca de venganza contra los dioses que lo engañaron para asesinar a su propia familia. Los prisioneros son quemados vivos y el jugador puede usar 'movimientos letales' para acabar con sus oponentes, como partir a una víctima por la mitad".

      Resident Evil 4:NARC: "El jugador escoge entre dos agentes antinarcóticos que intentan sacar una peligrosa droga desde las calles y acabar con KRAK, el cartel que la distribuye, mientras se expone a tentaciones que incluyen dinero y drogas. Para potenciar sus habilidades, el jugador consume drogas que incluyen marihuana, Quaaludes, éxtasi, LSD y "Liquid Soul", que le permite descabezar a sus enemigos".

      Killer 7: "El jugador toma el control de siete asesinos que deben combinar sus habilidades para derrotar a una banda de monstruosos terroristas suicidas. El juego eventualmente escala hasta un conflicto global entre los Estados Unidos y Japón. El jugador recolecta la sangre de sus víctimas para curarse a sí mismo, mientras debe cortarse las muñecas para rociar sangre y hallar pasajes ocultos".

      The Warriors: "Basada en una cinta de acción de los años 70 que impuso nuevos estándares de 'violencia artística', trata de una pandilla callejera que lucha en Nueva York para hacerse de un territorio propio. El jugador puede dar diversos comandos a su pandilla, incluyendo 'caos', que la lleva a destruir todo lo que encuentra a su paso".

      50 Cent: Bulletproof: "El juego está imaginativamente basado en el estilo de vida mafioso del rapero Curtis '50 Cent' Jackson. El jugador se involucra en tiroteos del hampa y saquea los cuerpos de sus víctimas por dinero para comprar nuevos discos de 50 Cent. Cabe destacar que la Oficina Calificadora de Películas y Literatura de Australia se negó a clasificarlo, prohibiendo el juego en todo el país al considerarlo "apropiado para nadie".

      Crime Life: Gang Wars: "El jugador es el líder de una sanguinaria pandilla callejera que pasa el tiempo peleando, reclutando nuevos hampones, saqueando y, desde luego, peleando más todavía. El jugador puede vagar por las calles y pelear o matar a cualquiera sin tener motivo aparente".

      Condemned: Criminal Origins: "El jugador es un cazador de asesinos en serie del FBI, en uno de los primeros títulos disponibles para la Xbox 360. El juego anima el uso de armas de mano sobre armas de fuego, permitiendo a los jugadores usar prácticamente todo en el entorno como arma. Los gráficos realistas proveen un nuevo nivel de detalle a las lesiones, especialmente los de 'movimientos letales'".

      True Crime: New York City: "El jugador es un policía de Nueva York buscando información sobre la misteriosa muerte de un amigo. El jugador puede incriminar en falso a civiles y extorsionarlos para conseguir dinero extra".

      Fuente: NoticiasDot


      Saludos....
      #35
      Diseño Gráfico / Imagen GIF
      2 Noviembre 2005, 00:09 AM
      Hola a todos....

      Necesito Saber como se hace una imgen animada (GIF). O sea, con que programa lo puedo hacer.
      No se si se puede con Macromedia, o CorelRave o qué, la verdad este no es mi mundo (Diseño), pero lo necesito para un programa.


      Saludos...
      #36
      Sugerencias y dudas sobre el Foro / Hora del foro
      25 Septiembre 2005, 23:57 PM
      Quisiera saber porque cada vez que entro al foro, se me cambia la hora en el computador. Se adelanta 7 horas.

      esto es normal????

      Saludos.....
      #37
      En verdad solo como sugerencia, me gustaría saber porque no borran a los usuarios que llevan mucho tiempo inactivos.
      Podrían mandarles un mail como advertencia, y darles un plazo, puesto que ahi muchos que se registran, y a los pocos dias se olvidan de la página.

      Solo para tenerlo bien limpio y organizado, todo por el bien de esta hermosa comunidad.

      Saludos...