manuales:plugins:manual_del_programador_de_plugins [Superglús]
 Superglús   Sistema de autoría de aventuras conversacionales Inicio



Nota Importante

La programación de plugins de Superglús no está pensada para no programadores, esta gúia da unos pasos básicos sobre como realizar plugins que presupone que el programador tiene conocimientos de programación en algún lenguaje ensamblador. No recomendamos al usuario de Superglús que sólo pretende hacer una aventura que intente realizar nuevos condactos plugin, sino que los pida a alguien que pueda hacerlos.

Introducción

Una de las características de Superglús es la capacidad de expanderse mediante condactos y librerias plugin, que evitan que sólo los autores de Superglús puedan extender el sistema. En los siguientes puntos se realizará una introducción al método que deberá utilizarse para realizar unos plugins, asi como una básica explicación de parte de las librerías pgl.

Ficheros .plu, cabeceras

Los ficheros .plu son ficheros de texto que contienen la definición de un condacto o librería plugin. Dichos ficheros tienen una primera línea que es considerada la cabecera, que indicará que tipo de información le sigue.

En el caso de una librería la primera línea debe ser:

;LIB

Lo cual indica que lo que sigue es una librería de funciones. Una librería no implementa un condacto en concreto, sino determinadas funciones que luego podrán ser usadas por condactos. Es decir, si por ejemplo una serie de condactos plugin requieren el calculo de una raiz cuadrada, no parece muy sensato repetir la rutina de raiz cuadrada en todos ellos, por lo cual parece mas adecuado crear una librería que incluya la funcion de raiz cuadrada.

Tras el ;LIB se puede poner cualquier cosa, y se recomienda que se ponga el nombre de la librería, aunque realmente no es necesario:

;LIB Ejemplo

En el caso de un condacto la cosa se complica, el formato de la linea de cabecera es:

;CND <nombre> <tipo> <parametro1> <parametro2> <parametro3> <tipo_resultado>

Donde <nombre> es el nombre del condacto, como se deberá teclear, <tipo> es una letra ‘A’ si es una accion y ‘C’ si es una condición. Le sigue el tipo de los tres parámetros del condacto, que se detalla en la tabla siguiente, y el tipo de resultado del condacto, que se detalla en la página subsiguiente:

__Tipos de parámetros__

0	No hay parámetro
1	Flagno
2	Valor
3	Porcentaje
4	Objno
5	mesno
6	Sysmessno
7	Pronombre
8	Locno
9	Locno+
10	Adjetivo
11	Adverbio
12	Preposición
13	Nombre
14	Cadena entrecomillada

Nota: es ilegal marcar el primer parámetro como de tipo 0 (no existe) y no hacerlo con el segundo, y de igual manera con el segundo y el tercero.

__Tipos de retorno__

0	Nada, condacto normal
1	Descripción, como OK o DESC
2	Fin, como END
3	Fin de Tabla, como DONE
4	Condicional, como QUIT

Por ejemplo:

;CND NOP A 0 0 0 0

indica un condacto de tipo acción, llamado NOP, sin parámetro y sin ningún retorno especial.

;CND ZONE C 8 8 0 0

indica un condacto de tipo condicion, llamado ZONE, con dos parámetros de tipo locno (el tercero no existe), y sin ningún retorno especial.

Ficheros .plu, cuerpo

En el caso de las librerías lo que sigue a la cabecera simplemente es código ensamblador que será añadido al programa, y se supone que normalmente serán funciones o variables globales.

En el caso de los condactos el cuerpo consiste en código glulx también pero debe contener al menos una funcion llamada acc_xxxx o cnd_xxx, dependiendo de si es una condición o una acción lo que se ha definido. Para los ejemplos anteriores debería haber por tanto una funcion acc_nop y otra cnd_zone.

:acc_nop
dc.b 0xc1 0x00 0x00
return 0

:cnd_zone
dc.b 0xc1 0x04 0x02 0x00 0x00
jgt {0}.l (:flag038).l 0
jlt {4}.l (:flag038).l 0
return 1

Nociones básicas de ensamblador Glulx

Se recomienda la lectura de las especificaciones Glulx para conocer con detalle el ensamblador de Glulx, pero aquí se dan unas básicas nociones:

  • Etiquetas: texto precedido de dos puntos. Ejemplos: :bucle o :acc_zone. Se recomienda que las etiquetas correspondientes a un condacto comiencen todas por el nombre del condacto para evitar repeticiones. Glulxa es un ensamblador muy básico y no detecta algunos errores que se manifestarán en tiempo de ejecución.
  • Indicar un valor: n.x, siendo n el valor y x el tipo: Ejemplos: 4.l → 4, long (32 bits) ó 3.b → 3, byte (8 bits)
  • Direccionamiento indirecto: Ejemplo: (:objetos).l. Obtiene el valor almacenado en la dirección indicada entre paréntesis
  • Direccionamiento a pila: Ejemplo: {0}.l. Accede a la pila, siendo {0} el último valor apilado, {4}.l el siguiente, etc.
  • Cabeceras de funciones: Todas la funciones tienen una cabecera en glulx, del estilo dc.b 0xc1 0×04 0×02 0×00 0×00. Solo decir que es importante el tercer valor, que indica el número de parámetros de la función, sumado al numero de variables locales. Es decir, que si nuestra función tiene dos parámetros, y además vamos a necesitar dos variables locales, tendrá que poner 0×04, en lugar de los 0×02 que hay en el ejemplo.
  • Acceso a las variables locales a funciones y parámetros: El último parámetro apilado estará en {0}.l, el siguiente en {4}.l, etc. A partir del ultimo apilado los siguientes será las variables locales. Es decir, que si hay dos parámetros y dos variables locales las variables locales estarán en {8} y {12}.
  • Los parámetros pueden variarse si de desea, aunque evidentemente se pasan por valor, aunque también evidentemente se puede pasar por valor una dirección.
  • Retornos de funciones: Se hacen mediante return: return 0, return 1, return {0}.l,etc. También en las instrucciones de salto, si se salta a 0 o a 1 en lugar de a una etiqueta o dirección, realmente se está haciendo un return 0 o 1 condicionado. Por ejemplo: jz {0}.l 0

Detalles de interés de las librerías .pgl

Las librerías pgl se incluyen en todos los ejecutables ulx generados. NO deben ser modificadas, salvo para corregir un bug, o que se sepa muy muy bien lo que se hace:

  • Inicio.pgl: Contiene la inicialización de la pila, que podemos aumentar si quisiéramos. Por ejemplo si hubieramos hecho una librería plugin con alta necesidad de pila (¿recursividad?¿grafos?¿listas?).
  • Vriables.pgl: contiene la variables globales de Superglús y alguna constante, como por ejemplo por donde se hace el split de la pantalla gráfica en glk, la tabla de conversión de caracteres,etc.. Además contiene la tabla de flags y la tabla de vectores de interrupción (ver este concepto más adelante).
  • Interpre.pgl: es el motor del intérprete de Superglús, contiene los bucles principales de ejecución de Superglús, la entrada de texto, respuestas, etc. También incluye funciones generales que luego serán usadas por los condactos.
  • Condacto.pgl: incluye la implementación de todos los condactos, resulta muy interesante examinarla para saber hacer condactos plugin.

Generación del fichero ULA

Cuando el compilador del glulx genera el fichero ULA, genera una parte correspondiente a la ejecución de los procesos, a la que añade una serie de definiciones de datos (objetos, mensajes, localidades, etc.). Esto es luego unido a todos los fichero .pgl y a todos los ficheros .plu, aunque el compilador en realidad crea un fichero llamado plugin.pgl a partir de los plugin y luego une todos los ficheros .pgl.

En dicho fichero .ULA están los datos de los objetos, que merecen ser explicados

Objetos

A partir de la etiqueta :objetos y ocupando 7 longs (32 bits) cada uno, incluye:

OffsetDato
0Numero del nombre
1Numero del adjetivo o 255 = sin adjetivo
2Localidad actual
3Peso
432 atributos de objeto bajos
532 atributos de objeto altos
6Direccion del texto descripción

Tras esta tabla están las variables :numero_ultimo_objeto, :numero

Mi extensión requiere que se graben cosas en las partidas grabadas. ¿Cómo?

Algunos condactos llaman dentro de su código a rutinas que pueden realizar extensiones del condacto (o no). Para ello la funcion call_int comprueba que el valor en la tabla de interrupciones de la interrupción que sea es cero, en cuyo caso no hace nada, y en caso contrario hace una llamada a la subrutina sita en la dirección indicada. En principio esta pensado para permitir que se extiendan SAVE y LOAD, de modo que un condacto o librería plugin pueda poner sus propios datos y grabarlos/cargarlos al grabar/cargar partida.

Se supone que para la existencia de una extensión por interrupción se debe hacer lo siguiente:

  1. Crear una rutina de inicialización, a modo de condacto, que el programador tendrá que poner. Dicho condacto toma el valor del puntero de interrupción, lo guarda en una variable interna y substituye el puntero por un puntero a una rutina de extensión.
  2. La rutina de extensión es entonces llamada a la hora de ejecutarse el condacto, y su misión extendida debe realizarse, y después llamar a la rutina que hubiera antes en el puntero, a no ser que el puntero fuera cero. De este modo se permiten extensiones concatenadas.

En la carpeta plugins de Superglús está la samplelib y algun ejemplo que puede dar nuevas ideas.

 

manuales/plugins/manual_del_programador_de_plugins.txt · Última modificación: 2010/01/27 10:50 por csanchez71