[vc_row][vc_column][vc_column_text]

NestorBASIC versión 1.10

Por Néstor Soriano (Konami Man), Junio 2.004

1. ¿QUE ES NESTORBASIC?

NestorBASIC es un paquete de rutinas en código máquina, integrado en un único fichero, pensado para ser usado en programas BASIC. NestorBASIC proporciona, sin perder la compatibilidad con el Turbo-BASIC, la siguiente funcionalidad:

– Acceso a toda la memoria mapeada del ordenador (a toda la memoria libre en caso de tener DOS 2), hasta 4 Mb.

– Acceso a toda la VRAM, con intercambio de bloques de datos entre ésta y RAM.

– Almacenamiento de diversos programas BASIC en la memoria mapeada, con posibilidad de pasar de uno a otro sin perder las variables.

– Acceso a ficheros de disco y acceso directo a sectores, con lectura/escritura directamente a/de la memoria mapeada y VRAM. Búsqueda de ficheros, gestión de directorios.

– Compresión/descompresión de gráficos.

– Reproducción de música MoonBlaster. Carga de samplekits.

– Reproducción de efectos de sonido PSG.

– Ejecución de rutinas en código máquina situadas en la BIOS, en la SUB-BIOS, en la memoria normal del BASIC, en la zona de trabajo del sistema, o en un segmento de RAM mapeada.

– Ejecución de funciones de NestorMan y rutinas de InterNestor Suite e InterNestor Lite.

Todas estas funciones son accesibles a través de un único USR y una matriz entera de parámetros, por lo que pueden usarse sin problemas desde dentro de turbo bloques. De hecho, el propio TurboBASIC está incluido en el fichero de NestorBASIC, y se carga automáticamente al instalar éste.

NestorBASIC se instala en un segmento de RAM oculto al BASIC, y sólo requiere un espacio de unos 500 bytes en la memoria principal del BASIC para una rutina de salto. El resto de la memoria principal queda libre para el programa BASIC.

2. REQUERIMIENTOS Y CARGA

NestorBASIC funciona en cualquier MSX2/2+/TR con al menos 128K de RAM mapeada. En el caso del DOS 2 ha de haber al menos un segmento libre en el mapeador primario (dos si se van a usar los reproductores musicales. Ver sección 8 para más detalles).

Cargar NestorBASIC es tan fácil como hacer BLOAD»NBASIC.BIN»,R, sin necesidad de ningún CLEAR ni ningún DEFUSR ni antes ni después de la carga. Si no ha habido ningún error ha ocurrido lo siguiente:

NestorBASIC y el Turbo-BASIC se han instalado en sendos segmentos de RAM, quedando ambos listos para su uso.

– La memoria disponible para el BASIC se ha reducido en unos 500 bytes, que han sido ocupados por una rutina de salto al segmento del NestorBASIC.

– El primer USR [USR0(parámetro) o simplemente USR(parámetro)] apunta a la rutina de salto. Será el gancho de llamada a las funciones de NestorBASIC.

– Se ha creado la matriz entera P, de 15 elementos. Esta matriz se usará para pasar parámetros a y devolver los resultados de las funciones de NestorBASIC, excepto los códigos de error, que serán devueltos a través del comando USR (las funciones de acceso a ficheros y las de tratamiento de cadenas también usan una matriz de cadenas, que hay que definir por separado; más detalles en la sección 4). Los cinco primeros elementos de P han sido inicializados como sigue:

P(0) Número de segmentos de RAM disponibles, o código de error
P(1) Versión principal de NestorBASIC
P(2) Versión secundaria de NestorBASIC, en formato BCD (visualizar en formato hexadecimal) P(3) = Versión principal de MSX-DOS
P(4) Versión secundaria de MSX-DOS, en formato BCD (visualizar en formato hexadecimal)

El número de segmentos de RAM disponibles siempre será 5 como mínimo. Un número inferior indica un error que ha impedido la instalación:

0 El ordenador no tiene memoria mapeada, o sólo tiene 64K de memoria mapeada.
1 Error de disco al intentar leer NestorBASIC o el Turbo-BASIC del fichero.
2 No hay ningún segmento libre en el mapeador primario. Este error sólo puede aparecer bajo DOS 2.
3 NestorBASIC ya estaba instalado. Las variables han sido inicializadas.
4 Futuras aplicaciones (dedicado a mis fans).

Tras la instalación de NestorBASIC es posible reservar memoria para otras rutinas residentes mediante el procedimiento habitual, es decir, el uso de la instrucción CLEAR para especificar el inicio de la zona reservada. Sin embargo, debido a que NestorBASIC realiza cambios de slot/segmento en la página 2 y el intérprete BASIC sitúa la pila en una zona anterior a la zona de cadenas y a la zona reservada por el usuario, existe un límite inferior para la dirección a especificar en el comando CLEAR. En concreto, no se puede reservar memoria por debajo de la dirección indicada por la siguiente fórmula:

&HC000 + (MAXFILES+1)*267 + FRE("") + 100

También hay que tener tener en cuenta que la instrucción CLEAR, así como la carga de otro programa BASIC, borran las variables. En ese caso habrá que volver a definir la matriz de parámetros (DEFINT P:DIM P(15), esto ha de hacerse fuera de turbo-bloques) y, si es necesario, la matriz F (justo después del inicio del turbo-bloque en caso de usar turbo-BASIC) para poder seguir usando las funciones de NestorBASIC:

10 'save"autoexec.bas"
20 BLOAD"nbasic.bin",R:IF P(0)<5 THEN PRINT "Error!":END
30 CLEAR 100:DEFINT P:DIM P(15)
40 _TURBO ON(P())
50 DIM F$(1) 'Para las funciones de acceso a ficheros. Ver sección 4.
...
65000 _TURBO OFF
65010 RUN"next.bas"

10 'save"next.bas"
20 DEFINT P:DIM P(15)
30 _TURBO ON(P())
40 DIM F$(0) 'Si no se va a usar F$(1). Ver sección 4.1.
...
65000 _TURBO OFF

También hay que tener en cuenta que NestorBASIC siempre utiliza el primer USR como gancho de llamada, por lo que no debe modificarse. USR1 a USR9 quedan libres.

3. SEGMENTOS LOGICOS

3.1. QUE ES UN SEGMENTO LOGICO?

La memoria RAM mapeada de los MSX se estructura en segmentos de 16K. Cada slot de RAM contiene un número S de segmentos (0 a S-1), accesibles mediante su conexión al espacio de direccionamiento por medio de los puertos &HFC a &HFF, previo establecimiento del slot correspondiente.

Al instalarse, NestorBASIC busca toda la RAM mapeada utilizable (toda la existente en el caso del DOS 1, sólo la libre en el caso del DOS 2) y construye una tabla en la que constan todos los segmentos encontrados y el slot en el que se encuentran (bajo DOS 2, los segmentos son reservados antes). Cada pareja slot-segmento se identifica con su número de orden en la tabla. Este número se denomina número de segmento lógico, y permite al usuario manejar toda la RAM disponible de forma ordenada y sin preocuparse del slot o slots en que se encuentra.

Por ejemplo, supongamos un MSX con 128K de memoria interna (8 segmentos), y 1024K (64 segmentos) en un slot externo. Una vez instalado NestorBASIC en este ordenador, y suponiendo DOS 1, el usuario dispone de 72 segmentos lógicos numerados de 0 a 71, y no tiene más que indicar este número en las funciones correspondientes de NestorBASIC cuando quiera usarlos. En ningún momento se manejan números de slot o segmento «físico».

El rango de direcciones de un segmento lógico (simplemente «segmento» a partir de ahora) es &H0000 a &H3FFF. Si se especifican direcciones superiores serán transformadas al rango adecuado al ejecutarse la función, es decir, las direcciones &H4000-&H7FFF, &H8000-&HBFFF y &HC000-&HFFFF equivalen a &H0000-&H3FFF.

Todos los segmentos pueden ser leídos y escritos, pero existen importantes restricciones con respecto a los seis primeros:

– El segmento 0 contiene el propio NestorBASIC, y sólo queda libre para el usuario una pequeña zona al final del mismo. La dirección inicial de dicha zona puede averiguarse con la función 1 (ver listado de funciones).

– El segmento 1 contiene el Turbo-BASIC. Sólo puede ser modificado si no se va a usar el compilador.

– El segmento 2 está conectado a la página 2 (direcciones &H8000 a &HBFFF), siendo por tanto el que alberga el programa BASIC en ejecución y parte de las variables del mismo.

– El segmento 3 está permanentemente conectado a la página 3 (direcciones &HC000 a &HFFFF), y contiene la zona de trabajo del sistema y algunas de las variables del programa BASIC. Peligrosísimo escribir aquí sin estar seguro de lo que se hace.

– El segmento 4 es usado como buffer interno por algunas funciones de NestorBASIC. Puedes usarlo para almacenar tus propios datos siempre que no uses tales funciones. Consulta la sección 10 o el apéndice 1 para saber qué funciones usan este segmento.

– Si existe, el segmento 5 está inicialmente libre, y no es usado por NestorBASIC. Pero si se inicializan los reproductores musicales, éstos quedan cargados en este segmento. Ver sección 8 para más detalles.

El resto de segmentos quedan totalmente a disposición del programador.

ATENCIÓN: Los papeles de los segmentos lógicos 2 y 4 se han intercambiado con el paso de la versión 0.07 a la 1.00 de NestorBASIC. En la versión 0.07 y anteriores, el segmento 2 correspondía al buffer interno de NestorBASIC, y el 4 correspondía a la memoria para el BASIC en página 2.

Al usar las funciones de intercambio de bloques hay que tener cuidado de no sobrepasar la dirección &H3FFF al sumar la dirección de destino y la longitud del bloque a transferir (por ejemplo, no hacer una transferencia de longitud &H2000 usando como dirección de destino &H3000), ya que en estos casos se
invade el segmento 0 o el 3 y los resultados son impredecibles.

Nota: mediante la función 80 es posible hacer que NestorBASIC reserve menos segmentos de memoria de los que hay disponibles, lo cual es útil bajo DOS 2 cuando se usan simultáneamente otros programas residentes que también necesitan reservar memoria (por ejemplo el RAM disk o NestorMan). Ver la sección 10 para la descripción de las funciones.

3.2. USO DE LA VRAM COMO SEGMENTOS LOGICOS

Para facilitar el uso de la VRAM como almacén de datos, ésta también es accesible mediante el uso de segmentos lógicos: si NestorBASIC indica que hay S segmentos disponibles, los segmentos 0 a S-1 son RAM mapeada, y los numerados como S a S+7 o S a S+3 se refieren a la VRAM (según la capacidad del ordenador, 128K o 64K).

Volviendo al ordenador del ejemplo anterior, tras instalar NestorBASIC o tras usar la función 1 (ver listado de funciones) se obtiene P(0)=72. Entonces, suponiendo 128K de VRAM, los segmentos 72 a 79 se refieren a la VRAM.

La correspondencia entre segmentos y direcciones VRAM es tal que los segmentos con número más alto se refieren a las direcciones VRAM más bajas, de forma que los últimos segmentos corresponden a la zona de visualización en pantalla cuando se trabaja en modo texto o con sólo una página en modo gráfico. Esto evita al programador tener que estar atento para saltarse el segmento correspondiente a la zona de visualización.

Siguiendo con el ejemplo anterior, si el programa funciona en SCREEN 0 (sólo se usan las primeras 16K de VRAM), los segmentos disponibles para guardar datos son del 4 al 78. En cambio, usando SCREEN 7 y sólo la página 0 (las primeras 64K de VRAM usadas), el rango de segmentos utilizables es 4 a 75.

Por supuesto, también hay funciones específicas para acceder a la VRAM e intercambiar datos entre ésta y cualquier segmento, o un fichero.

ATENCIÓN: Los segmentos VRAM pueden usarse igual que los segmentos normales para almacenar datos y programas BASIC, y para realizar transferencias entre segmentos o entre un segmento y un fichero/sectores, pero NO para los siguentes propósitos:

– Compresión/descompresión de gráficos
– Ejecución de una rutina de usuario
– Ejecución de una interrupción de usuario
– Reproducción de una efecto de sonido PSG
– Reproducción de una música

Cualquier intento de usar los segmentos VRAM para estos fines hará que las funciones correspondientes devuelvan un error de segmento inexistente.

3.3. EL SEGMENTO 255

El número de segmento lógico 255 tiene una función especial. No se refiere a ningún segmento de RAM o VRAM en particular, sino a la memoria normal del BASIC, es decir, las direcciones &H8000 a &HFFFF (sin que se aplique aquí la restricción ni la conversión de direcciones de los segmentos normales), que contienen el programa BASIC, las variables y la zona de trabajo del sistema.
Esto es útil por ejemplo para intercambiar datos entre un segmento y una matriz:

1 'Traspaso de 10 bytes del segmento 7, dirección inicial &H1000,
2 'a la matriz de enteros D.
3 '(Ver descripción de las funciones)
4 '
10 DEFINT D:DIM D(4) '5 datos enteros = 10 bytes
20 P(0)=7 'Segmento de origen
30 P(1)=&H1000 'Dirección inicial de origen
40 P(2)=255 'Segmento de destino=memoria principal
50 P(3)=VARPTR(D(0)) 'Dirección inicial de destino=matriz D
60 P(4)=10 'Longitud
70 J=USR(10) 'Llamada a la función 10 (transferencia entre segmentos)

3.4. MAPA DE SEGMENTOS

Como resumen de esta sección, he aquí la lista de segmentos disponibles y su descripción. S es el número de segmentos devuelto en P(0) al instalar NestorBASIC o al usar la función 1.

0 Segmento de NestorBASIC
1 Segmento del Turbo-BASIC
2 Memoria del BASIC, página 2 (&H8000-&HBFFF)
3 Memoria del BASIC, página 3 (&HC000-&HFFFF)
4 Segmento buffer interno 5 a S-1: RAM Disponible para el programador (si S>5) Si se inicializan los reproductores musicales, éstos quedan cargados en el segmento 5
S VRAM, direcciones &H1C000-&H1FFFF (64K VRAM: &HC000-&HFFFF)
S+1 VRAM, direcciones &H18000-&H1BFFF (64K VRAM: &H8000-&HBFFF)
S+2 VRAM, direcciones &H14000-&H17FFF (64K VRAM: &H4000-&H7FFF)
S+3 VRAM, direcciones &H10000-&H13FFF (64K VRAM: &H0000-&H3FFF)
S+4 VRAM, direcciones &H0C000-&H0FFFF (no disponible con 64K VRAM)
S+5 VRAM, direcciones &H08000-&H0BFFF (no disponible con 64K VRAM)
S+6 VRAM, direcciones &H04000-&H07FFF (no disponible con 64K VRAM)
S+7 VRAM, direcciones &H00000-&H03FFF (no disponible con 64K VRAM)
S+8 a 254 No disponibles (si S+8<255)
S255 Memoria del BASIC (&H8000-&HFFFF)

3.5. ERRORES

Todas las funciones de acceso a segmentos y/o VRAM devuelven el error -1 si se especifica un segmento inexistente, si se intenta acceder a una dirección VRAM superior a &HFFFF en un ordenador con únicamente 64K de VRAM, o si se especifica un segmento de VRAM o el segmento 255 en funciones que sólo soportan segmentos normales.

4. ACCESO A DISCO

NestorBASIC incorpora funciones para el manejo de ficheros y el acceso a otras funciones de MSX-DOS, concretamente:

* Creación/borrado/renombrado/Búsqueda de ficheros.
* Lectura/escritura de ficheros a/desde cualquier segmento o zona de VRAM.
* Bajo DOS 2, movimiento y obtención/establecimiento de atributos para un fichero.
* Lectura/escritura de sectores a/desde cualquier segmento o zona de VRAM.
* Obtención/establecimiento de la unidad/directorio (bajo DOS 2) por defecto.
* Obtención de la capacidad y espacio libre de un disco.
* Bajo DOS 2, obtención de la capacidad/establecimiento del RAM disk.

4.1. LA MATRIZ F$

Para el paso de nombres de fichero y de directorio, estas funciones emplean una matriz de cadenas, F$. Cuatro de ellas (Búsqueda, renombrado y movimiento de ficheros, y tratamiento de una ruta de acceso) emplean dos cadenas, por lo que necesitan que F$ se haya definido con dos elementos [DIM F$(1)]. Las demás funciones sólo necesitan una cadena, por lo que si no se va a usar ninguna de esas cuatro funciones se puede definir F$ con un sólo elemento [DIM F$(0)]. Esto es especialmente recomendable en caso de usar Turbo-BASIC, pues dentro de los turbo-bloques cada cadena emplea 256 bytes de memoria, sea cual sea su longitud. también hay que tener en cuenta que la matriz F$ se ha de definir inmediatamente después del comienzo del turbo bloque:

1000 _TURBO ON(P())
1010 DIM F$(1) o DIM F$(0)
...
65000 _TURBO OFF

IMPORTANTE: Las variables de cadena definidas fuera de un turbobloque, al igual que el resto de variables, no son traspasadas al mismo, y se recuperan a su finalización. Por ejemplo:

10 A$="Fuera"
20 _TURBO ON
30 A$="Dentro":PRINT A$
40 _TURBO OFF
50 PRINT A$
run
Dentro
Fuera

NestorBASIC mantiene esta propiedad, pero las cadenas F$() requieren una precaución adicional. Si se ha usado la matriz F$ fuera del turbobloque y va a definirse dentro del mismo, hay que insertar la siguiente línea antes del CALL TURBO ON:

F$(0)=F$(0)+"":F$(1)=F$(1)+""

Esta precaución no es necesaria si no se tiene interés en conservar el contenido de F$ anterior al turbo-bloque, o si no se va a definir F$ dentro del mismo.

Otra limitación de F$(0) y F$(1) es que su longitud máxima es de 80 carácteres; los carácteres sobrantes serán ignorados por las funciones de NestorBASIC que tengan estas cadenas como parámetros de entrada. Todas estas limitaciones no se presentan para índices superiores a 1 si se define F$ con más elementos (es decir, es posible definir F$ con más de dos elementos y usar F$(2), F$(3)… normalmente).

4.2. ERRORES

Además del error -1, explicado en 3.5, las funciones de acceso a ficheros tienen también sus propios códigos de error.

Los siguientes errores sólo aparecen bajo DOS 1:

1: Error general del MSX-DOS 1. Puede deberse a varias causas:

– Fichero no encontrado.
– Nombre de fichero incorrecto.
– El fichero ya existe (al intentar renombrar un fichero).
– Unidad inexistente (formando parte de un nombre de fichero).
– Final de fichero encontrado al hacer una lectura del mismo.
– Disco lleno.
– Directorio raíz completo.
– Función no disponible bajo DOS 1.

Hay que tener en cuenta que bajo DOS 2 cada uno de los errores mencionados tiene un código de error específico, que en ningún caso es el 1.

2 Número de fichero incorrecto (no se ha asignado ese número a ningún fichero abierto).
3 Hay demasiados ficheros abiertos. El número máximo de ficheros que pueden abrirse simultáneamente bajo DOS 1 puede consultarse mediante la función 1.

Los siguientes errores son comunes al DOS 1 y al DOS 2, y tienen el mismo código que sus equivalentes BASIC:

60 FAT incorrecta.
62 Unidad inexistente (al intentar cambiar la unidad por defecto).
68 Disco protegido contra escritura.
69 Error físico en el disco.
70 No hay disco.

Los errores propios del DOS 2 son:

222 No hay memoria libre para crear el RAM disk o para abrir el fichero.
219 Unidad inexistente (formando parte de una ruta/nombre de fichero)
218 Nombre de fichero incorrecto.
217 Ruta incorrecta.
215 Fichero no encontrado.
214 Directorio no encontrado.
213 Directorio raíz lleno.
212 Disco lleno.
211 El fichero ya existe (al intentar renombrar o mover un fichero).
210 Movimiento de directorio incorrecto (se ha intentado mover un directorio a uno de sus descendientes).
209 Fichero de sólo lectura (al intentar escribir).
208 El directorio no está vacío (al intentar borrarlo).
207 Atributos inválidos (al intentar cambiarlos).
206 Operación incorrecta sobre las entradas «.» o «..»
205 Existe un fichero de sistema con ese nombre (al crear un fichero o directorio se borra el preexistente, excepto si es de sistema).
204 Existe un directorio con ese nombre (lo mismo que con los ficheros de sistema).
203 Existe un fichero con ese nombre (al intentar crear un directorio).
202 El fichero está abierto (al intentar borrarlo, renombrarlo, moverlo, o cambiar sus atributos especificando directamente el nombre del fichero).
199 Se ha llegado al final del fichero (al leer del mismo).
196 Demasiados ficheros abiertos (al intentar abrir uno).
195 Número de fichero incorrecto (mayor de 63).
194 Número de fichero incorrecto (no se ha asignado ese número a ningún fichero abierto).
188 El RAM disk ya existe (al intentar crearlo).
187 El RAM disk no existe (al intentar borrarlo).

5. COMPRESION Y DESCOMPRESION DE GRAFICOS

NestorBASIC incorpora funciones para la compresión de gráficos de VRAM a RAM, y su descompresión de RAM a VRAM. El formato de compresión es el que utiliza Sunrise (o al menos utilizaba) en la rutina de aparición de su logotipo, trabaja por bytes y es el siguiente:

– Bytes sin repetir (hasta 63):

&B00nnnnnn &Hdd .. &Hdd

&Bnnnnnn es el número de bytes, &Hdd son los bytes

– Byte repetido hasta 63 veces:

&B01nnnnnn &Hdd

&Bnnnnnn es el número de repeticiones, &Hdd es el byte

– Byte repetido hasta 16383 veces:

&B10nnnnnn &Bnnnnnnnn &Hdd

&Bnnnnnnnnnnnnnn es el número de repeticiones, &Hdd es el byte

– Marca de final de los datos:

&B11000000 = &HC0

La (des)compresión se realiza a través de segmentos consecutivos; es decir, tras (des)comprimir de/a la posición &H3FFF del segmento S, se continúa con la posición &H0000 del segmento S+1.

5.1 ERRORES

Los errores que pueden devolver las rutinas de compresión y descompresión de gráficos son:

-1 Error al comprimir o descomprimir. No existe el segmento o la dirección VRAM especificadas en los parámetros de entrada, o bien el segmento especificado corresponde a VRAM o es el 255 (segmentos no utilizables por estas funciones).
5 Error al comprimir. No hay segmentos suficientes para comprimir toda la imagen.
6 Error al descomprimir. Se ha encontrado un dato incorrecto, o se han acabado los segmentos.

6. ALMACENAMIENTO DE PROGRAMAS BASIC EN RAM

NestorBASIC incorpora funciones que permiten el almacenamiento de programas BASIC en cualquier segmento de RAM o VRAM, y la activación o la ejecución de los mismos manteniendo intactas las variables del programa original (el que realiza el salto al nuevo).

MUY IMPORTANTE: Para poder usar estas funciones hay que cambiar la dirección de comienzo de los programas BASIC, originalmente &H8000, a &H8003; esto ha de hacerse sólo una vez, ANTES de cargar NestorBASIC. Hay dos formas de realizar este cambio:

– En modo directo, teclear lo siguiente:

POKE &HF676,4
POKE &H8003,0
NEW

– Desde un programa BASIC. Esta es la mejor opción, ya que puede ser el mismo programa que cargue NestorBASIC. La primera línea del programa ha de ser como sigue:

1 'programa.bas
10 IF PEEK(&HF676)<>4 THEN POKE &HF676,4:POKE &H8003,0:RUN"programa.bas"
20 'A partir de aquí ya se puede cargar NestorBASIC

Cuando un programa almacenado en un segmento va a ser activado o ejecutado, NestorBASIC guarda las variables y las matrices en el segmento 4; posteriormente copia el programa del segmento deseado a la memoria normal del BASIC, y coloca las variables antes guardadas al final del mismo, tras lo cual actualiza los punteros apropiados de la zona de trabajo. El último paso es la ejecución del programa desde la primera línea o bien el salto al modo directo, según la función usada (ejecución o activación).

Para que un programa BASIC pueda ser almacenado en un segmento y posteriormente activado o ejecutado, debe ser almacenado con una cabecera especial con información sobre su longitud, imprescindible para poder concatenarle las variables ya existentes. Existe una función que permite grabar el programa BASIC activo en un fichero con esa cabecera; posteriormente, basta cargar dicho archivo en cualquier segmento con las funciones de acceso a disco, y el programa ya estará listo para ser activado o ejecutado en cualquier momento.

6.1 ERRORES

Evidentemente, si se ejecuta la instrucción o línea siguiente al USR que ordena la activación o ejecución de otro programa BASIC, nos encontramos ante una situación de error. Hay dos posibles errores:

Error -1 si no se existe el segmento especificado. Estas funciones soportan segmentos VRAm, pero no el segmento 255.
Error -2 si la memoria del BASIC es insuficiente para albergar el nuevo programa y las variables. Puede ocurrir si el programa activado o ejecutado es más largo que el original.

7. FUNCIONES VARIAS

En este grupo se engloban funciones para:

– Ejecución de rutinas en código máquina de la BIOS, la SUB-BIOS, la memoria del BASIC, la zona de trabajo del sistema, o bien rutinas almacenadas en segmentos (denominadas aquí «rutinas de usuario»).
– Almacenamiento y posterior recuperación de cadenas en segmentos.
– Impresión de una cadena en modo gráfico.
– Tratamiento de bloques parpadantes (modo «blink») en SCREEN 0.
– Definición de una interrupción de usuario (una rutina en código máquina contenida en un segmento, que será ejecutada en cada interrupción del reloj).
– Ejecución de efectos de sonido PSG creados con SEE versión 3.xx

Algunas de estas funciones usan una matriz de cadenas, F$, para el paso de parámetros, además de la matriz P. Ver sección 4 para más detalles acerca de F$.

Algunas de las rutinas internas de NestorBASIC pueden ser usadas por las rutinas de usuario y por la interrupción de usuario. En el apéndice 2 se detalla la ubicación y el funcionamiento de dichas rutinas.

El editor de efectos de sonido SEE ha sido creado por Fuzzy Logic y el uso de los efectos así creados en programas comerciales implica el pago de una pequeña cantidad de dinero a los autores. Más detalles en el apéndice 4.

8. REPRODUCCION DE MUSICAS

8.1. INICIALIZACION DEL REPRODUCTOR

NestorBASIC incorpora un reproductor de músicas Moonblaster 1.4 y uno de Moonblaster para MoonSound, versión Wave 1.05.

Dichos reproductores no son cargados automáticamente cuando NestorBASIC es cargado, dado que por su gran longitud no caben en el segmento de NestorBASIC y ha residir en un segmento aparte. Por tanto, para poder usar un reproductor hay que cargarlo explícitamente. sólo se puede tener cargado uno a la vez.

La función 71 se encarga de cargar e inicializar el reproductor deseado, dejándolo listo para su uso. Dicha función comprueba si el segmento 5 existe y pertenece al mapeador primario, en cuyo caso carga el reproductor en dicho segmento, que deja de estar disponible para el usuario. Si el segmento 5 no existe, o si existe pero no pertenece al mapeador primario, el reproductor no será cargado y la función devolverá un error.

El fichero NBASIC.BIN contiene dos versiones del reproductor de Moonblaster Wave: una es para ordenadores MSX2/2+ y para el Turbo-R en modo Z80, y la otra es para el Turbo-R en modo R800. En el caso del Turbo-R, NestorBASIC decide qué versión cargar en función del procesador que está activo en el momento de ejecutar la función 71. Hay que tener en cuenta que si se realiza un cambio de procesador es necesario volver a ejecutar esta función, ya que la versión Z80 no funciona en modo R800 y la versión R800 introduce en modo Z80 un ralentizamiento innecesario del sistema.

Cuando el reproductor es cargado también se realiza una búsqueda de chips musicales, y todos los encontrados quedan activos. Ver descripción de la función 73 para más detalles sobre la activación y desactivación de chips musicales.

8.2. FUNCIONALIDADES DEL REPRODUCTOR

Una vez que el reproductor está cargado, pueden usarse las funciones que NestorBASIC incorpora para:

– Comenzar la reproducción de una música previamente cargada en un segmento (que NO puede ser un segmento VRAM).
– Detener la reproducción de la música que está sonando.
– Pausar/continuar la música que está sonando.
– Desvanecer la música que está sonando, con elección de la velocidad de desvanecimiento.
– Obtener información sobre la música que está sonando (segmento y dirección inicial, título y samplekit o wavekit, posición y paso actuales).
– Obtener información sobre los chips musicales detectados.
– Desactivar los chips musicales, de forma que no sean usados aunque hayan sido detectados, y volver a activarlos.
– Cargar un samplekit de Music Module o un wavekit de MoonSound desde un fichero.

Mientras una música está sonando pueden usarse todas las funciones de NestorBASIC, incluyendo la reproducción de efectos de sonido y el uso de interrupciones de usuario. Si se desinstala NestorBASIC, la música que está sonando quedará automáticamente interrumpida.

El reproductor de Moonblaster 1.4 ocupa sólo 4.5K, por lo que el espacio entre las direcciones &H1200 y &H3FFF del segmento 5 queda libre y puede usarse, por ejemplo, para almacenar la música que va a ser reproducida. Esto no ocurre con el reproductor de Moonblaster Wave, que ocupa la totalidad del segmento 5.

En el caso de músicas Moonblaster 1.4, la música ha de estar almacenada en un único segmento, por lo que no puede ser mayor de 16K. Las músicas Moonblaster Wave pueden estar almacenadas a través de segmentos consecutivos, como máximo tres: si al leer datos de una música para su reproducción NestorBASIC llega a la dirección &H3FFF de un segmento, continuará en la dirección 0 del segmento siguiente.

Para cargar una música a través de segmentos consecutivos se puede usar por ejemplo un listado como este:

1000 'Carga de una musica a traves de segmentos consecutivos,
1010 'empezando en el segmento S, direccion D
1020 F$(0)="musica.mwm":P(2)=S:P(3)=D
1030 E=USR(31):IF E<>0 THEN 10000
1040 P(4)=&H4000:E=USR(33)
1050 IF (E<>0 AND E<>1 AND E<>199) THEN 10000
1060 IF E=0 THEN P(2)=P(2)+1:P(3)=0:GOTO 1040
1070 E=USR(32):IF E<>0 THEN 10000
...
10000 'Rutina de tratamiento del error de disco E
...

ATENCIÓN: Una música Moonblaster Wave puede comenzar en cualquier dirección de un segmento, siempre que continúe en el principio del segmento siguiente. Sin embargo al menos los primeros 800 bytes de la música, que contienen la tabla de patrones y diversos punteros, han de estar íntegros en el primer segmento.

8.3 ERRORES

Los errores devueltos por las funciones de reproducción musical son:

Error 7 devuelto por las funciones de establecimiento de chips, de pausa y de desvanecimiento de la música si uno de los parámetros de entrada es incorrecto.
Error 12 devuelto por las funciones de inicio de una música y activación/desactivación de chips si el reproductor no ha sido cargado. El resto de funciones no devueven error en este caso, simplemente no hacen nada.

Los siguientes errores son devueltos por la función de inicio de una música:

-1 El segmento lógico especificado no existe, corresponde a VRAM o es el 255.
12 El reproductor no ha sido cargado.
13 La música ha sido grabada en modo EDIT y no puede ser reproducida (reproductor Moonblaster 1.4). En la dirección especificada no hay una música Moonblaster Wave, o bien hay una música Moonblaster Wave grabada en modo EDIT (reproductor Moonblaster Wave).
14 Ya hay una música en reproducción.

La función de carga de un wavekit de Moonsound puede devolver el siguiente error, además de los errores de las funciones de acceso a disco:

15: En la posición actual del fichero especificado no hay un wavekit Moonblaster, o bien hay un wavekit que no ha sido grabado en modo USER.

NOTA: El reproductor de Moonblaster 1.4 no puede detectar si en la dirección especificada hay realmente una música Moonblaster, y se fía únicamente del byte inicial para decidir si en dicha dirección comienza una música en modo EDIT. El reproductor de Moonblaster Wave no tiene estas limitaciones.

La función de carga del reproductor devuelve los mismos errores que las funciones de acceso a disco, y el error -1 si el segmento 5 no existe o no pertenece al mapeador primario.

9. INTERACCION CON NESTORMAN E INTERNESTOR SUITE/LITE

NestorBASIC dispone de funciones especiales para la interacción con NestorMan (gestor residente de memoria dinámica para MSX-DOS 2), InterNestor Suite (pila TCP/IP para MSX-DOS 2) e InterNestor Lite (pila TCP/IP para MSX-DOS 1/2), si estos programas están instalados. De esta forma es posible desarrollar en BASIC aplicaciones que hagan uso de bloques de memoria dinámica y listas encadenadas, así como aplicaciones basadas en Internet. Para saber si NestorMan e InterNestor Suite están instalados se puede usar la función 81; el procedimiento para detectar si InterNestor Lite está instalado se detalla en la sección 9.4.

Nota: NestorMan e InterNestor Suite/Lite tienen sus propios manuales, donde se describen las funciones y rutinas que proporciona cada uno. Estos programas están disponibles en http://msx.konamiman.com.

9.1. SEGMENTOS DE NESTORBASIC Y SEGMENTOS DE NESTORMAN

NestorMan usa un sistema de segmentos lógicos muy similar al usado por NestorBASIC. Ambos espacios de segmentos, el de NestorBASIC y el de NestorMan, son independientes entre sí, con las siguientes excepciones:

– Los segmentos 0, 1, 2 y 3 son comunes a NestorBASIC y a NestorMan (en el manual de NestorMan, estos segmentos se denominan «segmentos de TPA»).

– Si NestorMan está presente cuando NestorBASIC es instalado, el segmento lógico 4 de NestorBASIC no se reserva usando las rutinas de soporte del mapeador del DOS 2, como el resto de los segmentos. En vez de eso, se reserva usando la función 7 de NestorMan; de esta forma, el segmento 4 de NestorBASIC tiene asignado a su vez un número de segmento en NestorMan (dicho número puede consultarse mediante la función 81 de NestorBASIC). El segmento es reservado con el atributo «exclusivo», por lo que no es usado por NestorMan para realizar reservas de bloques de memoria.

Si se va a usar NestorMan (y/o InterNestor Suite) junto con NestorBASIC, es recomendable limitar la cantidad de segmentos de RAM que usará NestorBASIC mediante la función 80. De lo contrario, NestorBASIC reservará para sí mismo todos los segmentos disponibles, y NestorMan no podrá realizar reservas de segmentos de RAM (necesarias para realizar reservas de bloques de memoria, crear listas encadenadas y enviar/recibir datos a/desde Internet).

Para ejecutar las funciones de NestorMan se puede usar la función 82; o bien se puede usar la función 58 especificando el gancho de la BIOS extendida (&HFFCA) como dirección a llamar, &H2202 en el par de registros DE, y el número de función en el registro C. Ver la sección 10 para la descripción de las funciones.

9.2. INTERCAMBIO DE DATOS ENTRE NESTORBASIC Y NESTORMAN

Al usar NestorMan a través de NestorBASIC, normalmente se necesitará hacer traspasos de datos entre un segmento de NestorBASIC y uno de NestorMan. Hay tres formas de hacer esto:

1) Si el segmento de origen o el de destino es de TPA (número de segmento 0 a 3), basta usar la función adecuada de NestorMan para el traspaso de un bloque de datos, dado que NestorMan ya ve estos segmentos.

2) Se puede usar el segmento 4 de NestorBASIC como buffer intermedio para el traspaso. Por ejemplo, supongamos un traspaso de NestorBASIC a NestorMan. S1 es el segmento de origen de NestorBASIC, S2 es el segmento de destino de NestorMan, y S3 es el número del segmento 4 desde el punto de vista de NestorMan. Entonces, primero se haráa una transferencia S1->4 usando la función de transferencia de bloques de NestorBASIC (función 10), y después se hará una transferencia S3->S2 usando la función de transferencia de bloques de NestorMan (función 14).

3) Las funciones de NestorBASIC 83 y 84 realizan una transferencia de un bloque de datos de un segmento de NestorMan a un segmento de NestorBASIC y viceversa.

Para leer o escribir únicamente un byte de datos de un segmento de NestorMan, lo más fácil es usar las funciones que el mismo proporciona para este propósito (funciones 12 y 13, respectivamente).

Recuerda que algunas funciones de NestorBASIC usan el segmento 4 como buffer para el almacenamiento temporal de datos. Para saber qué funciones usan el segmento 4, consulta la sección 10 o el apéndice 1.

9.3. USO DE INTERNESTOR SUITE

Las técnicas para usar InterNestor Suite desde NestorBASIC son similares a las técnicas descritas anteriormente para usar NestorMan. Únicamente hay que tener en cuenta lo siguiente:

– La función 85 permite ejecutar las rutinas de InterNestor Suite.

– Para leer y escribir datos de los segmentos de InterNestor Suite (constantes de configuración y variables), primero hay que averiguar mediante la función 81 los números de segmento de los módulos de InterNestor Suite (cada módulo reside en un segmento de NestorMan), y a partir de ahí usar las técnicas de intercambio de datos explicadas en la sección anterior.

– Las rutinas de InterNestor Suite para leer/escribir datos TCP o datagramas UDP sólo admiten segmentos TPA como orígen/destino para los datos o datagramas. Para este propósito se puede usar la porción final del segmento de NestorBASIC (segmento 0) como zona intermedia de almacenamiento. Esta zona siempre tendrá una longitud mínima de 600 bytes, sea cual sea la versión de NestorBASIC usada; esto es suficiente para almacenar datagramas estándar de hasta 576 bytes de longitud (o para almacenar un bloque de datos TCP de hasta 600 bytes).

El programa de ejemplo TCPCON-S.BAS, suministrado con NestorBASIC, ilustra el uso conjunto de NestorBASIC e InterNestor Suite.

9.4. USO DE INTERNESTOR LITE

InterNestor Lite es un programa mucho más sencillo que InterNestor Suite, por tanto su uso desde NestorBASIC también es más sencillo. Se proporciona una única función, la 86, que permite ejecutar cualquier rutina del segmento de código de InterNestor Lite. Para leer o escribir en su segmento de datos, es necesario usar las rutinas GET_VAR, SET_VAR y COPY_DATA del segmento de código.

Para saber si InterNestor Lite está instalado, se debe usar la función 58 para hacer una llamada al gancho de la BIOS extendida (dirección &HFFCA), pasando A=0 y DE=&H2203. Si la llamada devuelve A<>0, entonces InterNestor Lite está instalado. Ver la descripción de la función 86 para más detalles.

Muchas de las rutinas de InterNestor Lite usan direcciones de TPA como origen o destino para el intercambio de datos con las aplicaciones. Para estas rutinas se pueden especificar direcciones superiores a &H8000, que harán referencia a la memoria principal del BASIC y a la zona de trabajo del sistema; o bien direcciones inferiores a &H4000, que harán referencia al segmento de NestorBASIC.

Al final del segmento de NestorBASIC hay una zona libre, cuyo tamaño varía entre versiones de NestorBASIC pero que siempre será de al menos 600 bytes, que puede usarse como zona de almacenamiento temporal para intercambiar datos con InterNestor Lite. En otras palabras, puede usarse el espacio entre &H3DA8 y &H3FFF como origen o destino TPA para una transferencia de datos entre NestorBASIC e InterNestor Lite.

El programa de ejemplo TCPCON-L.BAS, suministrado con NestorBASIC, ilustra el uso conjunto de NestorBASIC e InterNestor Lite.

9.5. ERRORES

La función 86 (llamada a una función de InterNestor Lite) devolverá el error -1 si InterNestor Lite no está instalado.

La función 85 (llamada a una función de InterNestor Suite) devolverá el error -1 si InterNestor Suite no está instalado, o si se especifica un número de módulo inválido (los números de módulo válidos son del 1 al 4).

Las funciones 83 y 84 (transferencia de un bloque de datos entre un segmento de NestorMan y un segmento de NestorBASIC) devuelven el error -1 si se especifica un número de segmento (de NestorMan o de NestorBASIC) de origen o de destino inexistente. Pueden usarse los segmentos VRAM y el segmento 255 con estas funciones.

Las funciones 80, 81 y 82 nunca devuelven error.

10. LAS FUNCIONES DE NESTORBASIC

10.1. DESCRIPCION GENERAL

Las funciones que componen NestorBASIC se identifican con un número que se pasa como parámetro a través de la instrucción USR. Así, para usar la función F basta hacer USR(F), teniendo en cuenta que en caso de usar una variable para especificar la función, dicha variable ha de ser de tipo entero. Los parámetros para las funciones han de ser establecidos en la matriz P (y, dado el caso, en la matriz F) antes de la llamada a la función. Análogamente, los resultados devueltos por la función se encontrarán en P y/o en F.

Los elementos de P y F que no se mencionan explícitamente en la lista de resultados de cada función no resultan modificados, excepto las direcciones de segmento, que son convertidas al rango &H0000-&H3FFF si lo sobrepasaban (las direcciones del segmento 255 nunca son convertidas). Salvo que se especifique lo contrario, los parámetros de salida no son válidos en condiciones de error (P y F no resultan modificadas).

El «bloque VRAM» se refiere a las 64K inferiores (bloque 0) o a las 64K superiores (bloque 1). Las direcciones VRAM van de &H0000 a &HFFFF; si la dirección VRAM pasa de &HFFFF a &H0000 tras un autoincremento, el bloque VRAM también se actualiza (si era 0 pasa a 1, si era 1 pasa a 0).

La función USR devolverá un código de error, o 0 si no hay error. Los errores específicos para cada grupo de funciones están explicados en las secciones correspondientes.

El apéndice 1 contiene una lista de todas las funciones, que puede ser útil como referencia rápida.

Las funciones que usan el segmento 4 tienen una marca «(S4)» tras su nombre. Dichas funciones son las siguientes: 0, 26-28, 30, 33-41, 55-57, 71, 78, y 79.

10.2. FUNCIONES GENERALES

 Función 0
Desinstalación de NestorBASIC (S4)
Entrada P(0) = 0 -> No liberar la zona residente
P(0) <>0 -> Liberar la zona residente
Salida

Inutiliza el USR y, en el caso del DOS 2, libera todos los segmentos que habían sido reservados. también detiene las interrupciones en curso, incluidos efectos de sonido y músicas. Es importante llamar a esta función antes de volver al DOS, ya que en caso contrario los segmentos de RAM reservados no son liberados y no pueden volver a usarse hasta que se reinicia el ordenador.

Antes de desinstalar NestorBASIC hay que asegurarse de no dejar ningún fichero abierto, pues pueden quedar en los buffers internos del DOS datos perdidos de los ficheros que hayan sido escritos. Además, en el caso del DOS 2 quedarán descriptores de ficheros («file handles») abiertos inútilmente.

Si P(0)=0 a la entrada, la memoria ocupada por la rutina de salto en la zona del BASIC no es liberada, lo que preserva las reservas de memoria hechas por instrucciones CLEAR con posterioridad a la instalación de NestorBASIC. Si P(0)<>0, la zona reservada (y, por tanto, la cantidad de memoria libre) pasa a ser la misma que había antes de la instalación de NestorBASIC, y las variables son inicializadas.

Esta función nunca devuelve error.

 Función 1 Obtención de información general sobre NestorBASIC y sobre un segmento lógico
Entrada P(10)= Segmento lógico a investigar
Salida P(0) = Número de segmentos de RAM disponibles
P(1) = Versión principal de NestorBASIC
P(2) = Versión secundaria de NestorBASIC, en formato BCD (visualizar en formato hexadecimal)
P(3) = Versión principal de MSX-DOS
P(4) = Versión secundaria de MSX-DOS, en formato BCD (visualizar en formato hexadecimal)
P(5) = Cantidad de memoria ocupada por la rutina de salto
P(6) = Tamaño de la VRAM en K
P(7) = Dirección inicial de la zona libre en el segmento 0 (como máximo &H3DA8)
P(8) = Número de la última función llamada
P(9) = Número de ficheros abiertos
P(10)= Número máximo de ficheros abiertos simultaneamente (aplicable sólo bajo DOS 1)
P(11)= Slot en el que se encuentra el segmento P(0) (255 si ese segmento no existe o corresponde a VRAM)
P(12)= Segmento físico correspondiente al segmento lógico P(0)
F$(0)= Ruta completa del fichero NBASIC.BIN

El número máximo de ficheros abiertos bajo DOS 2 depende del estado de la memoria interna del DOS, pero nunca será mayor de 63.

Esta función devuelve el error -1 si el segmento especificado en P(0) no existe, corresponde a VRAM o es el 255. Los parámetros devueltos en P(0) a P(10) serán válidos aún en caso de error.

El número devuelto en P(0) por esta función es igual al número devuelto en P(0) por la función 80; es decir, es el número de segmentos reservados para NestorBASIC. Por defecto (si tras instalar NestorBASIC no se ha ejecutado nunca la función 81), NestorBASIC reserva todos los segmentos libres en el momento de su instalación, hasta un máximo de 247.

Bajo DOS 1, F$(0) contendrá simplemente una unidad y dos puntos, por ejemplo «A:». Bajo DOS 2 contendrá una unidad y un directorio, acabado en «\»; por ejemplo «C:\UTILS\GENIALES\».

La dirección devuelta en P(7) depende de la versión de NestorBASIC, pero siempre será inferior o igual a &H3DA8; es decir, siempre habrá al menos 600 bytes libres al final del segmento de NestorBASIC. Esta zona puede usarse, por ejemplo, para albergar temporalmente datos TCP o un datagrama UDP en caso de que se use InterNestor Suite con NestorBASIC.

P(8) devuelve el número de la última función llamada, pero la propia función 1 no cuenta. Así, si se llaman en secuencia, por ejemplo, las funciones 64, 3, 10, 1, 1, 1, lo que se obtendrá al final es P(8)=10. Un valor de cero indica que no se ha ejecutado ninguna función aparte de la 1 desde que se ha instalado NestorBASIC.

10.3. FUNCIONES DE ACCESO A SEGMENTOS LOGICOS

 Función 2 Lectura de un byte de un segmento
Entrada P(0) = Segmento
P(1) = Dirección
Salida P(2) = Byte leído

Inutiliza el USR y, en el caso del DOS 2, libera todos los segmentos que habían sido reservados. también detiene las interrupciones en curso, incluidos efectos de sonido y músicas. Es importante llamar a esta función antes de volver al DOS, ya que en caso contrario los segmentos de RAM reservados no son liberados y no pueden volver a usarse hasta que se reinicia el ordenador.

Antes de desinstalar NestorBASIC hay que asegurarse de no dejar ningún fichero abierto, pues pueden quedar en los buffers internos del DOS datos perdidos de los ficheros que hayan sido escritos. Además, en el caso del DOS 2 quedarán descriptores de ficheros («file handles») abiertos inútilmente.

Si P(0)=0 a la entrada, la memoria ocupada por la rutina de salto en la zona del BASIC no es liberada, lo que preserva las reservas de memoria hechas por instrucciones CLEAR con posterioridad a la instalación de NestorBASIC. Si P(0)<>0, la zona reservada (y, por tanto, la cantidad de memoria libre) pasa a ser la misma que había antes de la instalación de NestorBASIC, y las variables son inicializadas.

Esta función nunca devuelve error.

 

 Función 3 Lectura de un byte de un segmento con autoincremento de la dirección
Entrada P(0) = Segmento
P(1) = Dirección
Salida P(2) = Byte leído
P(1) = P(1) + 1
 

 

 Función 4 Lectura de un entero (2 bytes) de un segmento
Entrada P(0) = Segmento
P(1) = Dirección
Salida P(2) = Entero leído
El byte bajo del entero es leído de la dirección P(1), y el byte alto de la dirección P(1)+1.

 

 Función 5 Lectura de un entero (2 bytes) de un segmento con autoincremento de la dirección
Entrada P(0) = Segmento
P(1) = Dirección
Salida P(2) = Entero leído
P(1) = P(1) + 2
El byte bajo del entero es leído de la dirección P(1), y el byte alto de la dirección P(1)+1.

 

Función 6 Escritura de un byte en un segmento
Entrada P(0) = Segmento
P(1) = Dirección
P(2) = Byte a escribir
Salida
 

 

Función 7 Escritura de un byte en un segmento con autoincremento de la dirección
Entrada P(0) = Segmento
P(1) = Dirección
P(2) = Byte a escribir
Salida P(1) = P(1) + 1
 

 

Función 8 Escritura de un entero (2 bytes) en un segmento
Entrada P(0) = Segmento
P(1) = Dirección
P(2) = Entero a escribir
Salida
El byte bajo del entero es escrito en la dirección P(1), y el byte alto en la dirección P(1)+1.

 

Función 9 Escritura de un entero (2 bytes) en un segmento con autoincremento de la dirección
Entrada P(0) = Segmento
P(1) = Dirección
P(2) = Entero a escribir
Salida P(1) = P(1) + 2
El byte bajo del entero es escrito en la dirección P(1), y el byte alto en la dirección P(1)+1.

 

Función 10 Transferencia de un bloque de bytes de un segmento a otro
Entrada P(0) = Segmento de origen
P(1) = Dirección inicial de origen
P(2) = Segmento de destino
P(3) = Dirección inicial de destino
P(4) = Longitud del bloque
P(5)<> 0 -> Autoincremento de P(1)
P(6)<> 0 -> Autoincremento de P(3)
Salida P(1) = P(1) + P(4) si P(5)<>0
P(3) = P(3) + P(4) si P(6)<>0P(3)+P(4) debe ser menor de &H4000, de lo contrario el resultado es impredecible.
 

 

Función 11 Llenado de una zona de memoria con un byte
Entrada P(0) = Segmento lógico
P(1) = Dirección inicial
P(2) = Byte
P(3) = Longitud de la zona
Salida
P(1)+P(3) debe ser menor de &H4000, de lo contrario el resultado es impredecible.

 

Función 12 Llenado de una zona de memoria con un byte con autoincremento de la dirección
Entrada P(0) = Segmento lógico
P(1) = Dirección inicial
P(2) = Byte
P(3) = Longitud de la zona
Salida Salida: P(1) = P(1) + P(3)
P(1)+P(3) debe ser menor de &H4000, de lo contrario el resultado es impredecible.

10.4. FUNCIONES DE ACCESO A LA VRAM

Función 13 Lectura de un byte de la VRAM
Entrada P(0) = Bloque VRAM
P(1) = Dirección
Salida P(2) = Byte leído
 

 

Función 14 Lectura de un byte de la VRAM con autoincremento de la dirección
Entrada P(0) = Bloque VRAM
P(1) = Dirección
Salida P(2) = Byte leído
P(0):P(1) = P(0):P(1) + 1
 

 

Función 15 Lectura de un entero (2 bytes) de la VRAM
Entrada P(0) = Bloque VRAM
P(1) = Dirección
Salida P(2) = Entero leído
El byte bajo del entero es leído de la dirección P(1), y el byte alto de la dirección P(1)+1.

 

Función 16 Lectura de un entero (2 bytes) de la VRAM con autoincremento de la dirección
Entrada P(0) = Bloque VRAM
P(1) = Dirección
Salida P(2) = Entero leído
P(0):P(1) = P(0):P(1) + 2
El byte bajo del entero es leído de la dirección P(1), y el byte alto de la dirección P(1)+1.

 

Función 17 Escritura de un byte en la VRAM
Entrada P(0) = Bloque VRAM
P(1) = Dirección
P(2) = Byte a escribir
Salida
 

 

Función 18 Escritura de un byte en la VRAM con autoincremento de la dirección
Entrada P(0) = Bloque VRAM
P(1) = Dirección
P(2) = Byte a escribir
Salida P(0):P(1) = P(0):P(1) + 1
 

 

Función 19 Escritura de un entero (2 bytes) en la VRAM
Entrada P(0) = Bloque VRAM
P(1) = Dirección
P(2) = Entero a escribir
Salida
El byte bajo del entero es escrito en la dirección P(1), y el byte alto en la dirección P(1)+1.

 

Función 20 Escritura de un entero (2 bytes) en la VRAM con autoincremento de la dirección
Entrada P(0) = Bloque VRAM
P(1) = Dirección
P(2) = Entero a escribir
Salida P(0):P(1) = P(0):P(1) + 2
El byte bajo del entero es escrito en la dirección P(1), y el byte alto en la dirección P(1)+1.

 

Función 21 Transferencia de un bloque de bytes de VRAM a RAM
Entrada P(0) = Bloque VRAM de origen
P(1) = Dirección inicial de origen (VRAM)
P(2) = Segmento de destino
P(3) = Dirección inicial de destino (RAM)
P(4) = Longitud del bloque
P(5)<> 0 -> Autoincremento de P(1)
P(6)<> 0 -> Autoincremento de P(3)
Salida P(1) = P(1) + P(4) si P(5)<>0
P(2):P(3) = P(2):P(3) + P(4) si P(6)<>0P(1)+P(4) debe ser menor de &H4000, de lo contrario el resultado es impredecible.
 

 

Función 22 Transferencia de un bloque de bytes de RAM a VRAM
Entrada P(0) = Segmento de origen
P(1) = Dirección inicial de origen (RAM)
P(2) = Bloque VRAM de destino
P(3) = Dirección inicial de destino (VRAM)
P(4) = Longitud del bloque
P(5)<> 0 -> Autoincremento de P(1)
P(6)<> 0 -> Autoincremento de P(3)
Salida P(1) = P(1) + P(4) si P(5)<>0
P(2):P(3) = P(2):P(3) + P(4) si P(6)<>0
 

 

Función 23 Transferencia de un bloque de bytes de VRAM a VRAM
Entrada P(0) = Bloque VRAM de origen
P(1) = Dirección inicial de origen
P(2) = Bloque VRAM de destino
P(3) = Dirección inicial de destino (VRAM)
P(4) = Longitud del bloque (máximo &H4000)
P(5)<> 0 -> Autoincremento de P(1)
P(6)<> 0 -> Autoincremento de P(3)
Salida P(0):P(1) = P(0):P(1) + P(4) si P(5)<>0
P(2):P(3) = P(2):P(3) + P(4) si P(6)<>0

Si P(4) es mayor de &H4000 sólo se transferirán &H4000 bytes, y el incremento de las direcciones se limitará también a &H4000, pero P(4) no se modificará. Por tanto, para transferir bloques mayores (hasta 64K) de forma fácil se puede hacer algo como esto:

10 ‘P(0) a P(3) ya establecidos. Longitud de la transferencia en L.
20 P(5)=1:P(6)=1
30 P(4)=VAL(«&H»+HEX$(L)):J=USR(23):L=L-&H4000:IF L>0 THEN 30

El paso a hexadecimal y posterior retorno a decimal de L es necesario debido a que el BASIC considera las variables enteras en el rango -32768 a 32767, y una asignación directa de un número mayor a P(4) daría un error de desbordamiento.

Dado que el TurboBASIC trata las variables de coma flotante de forma especial, si se usa este método dentro de un turbo-bloque es necesario que L sea un múltiplo entero de 256.

 

Función 24 Llenado de una zona de la VRAM con un byte
Entrada P(0) = Bloque VRAM
P(1) = Dirección inicial
P(2) = Byte
P(3) = Longitud de la zona (máximo 16K)
Salida
Para establecer una longitud mayor de 16K se ha de emplear el truco explicado en la función 23.

 

Función 25 Llenado de una zona de la VRAM con un byte con autoincremento de la dirección
Entrada P(0) = Bloque VRAM
P(1) = Dirección inicial
P(2) = Byte
P(3) = Longitud de la zona (máximo 16K)
Salida P(0):P(1) = P(0):P(1) + P(3)
Para establecer una longitud mayor de 16K se ha de emplear el truco explicado en la función 23.

10.5. FUNCIONES DE ACCESO A FICHEROS

Función 26 Búsqueda de ficheros (S4)
Entrada F$(1) = Máscara de Búsqueda (cadena vacía=»*.*»)
P(0) = 0 -> Buscar primer fichero coincidente con la máscara
P(0) = 1 -> Buscar los siguientes ficheros
P(1) = Atributos de Búsqueda: 2*H + 4*S + 8*V + 16*D
H = 1 -> Incluir en la Búsqueda los ficheros ocultos
S = 1 -> Incluir en la Búsqueda los ficheros de sistema
V = 1 -> Buscar sólo la etiqueta de volumen del disco
D = 1 -> Incluir en la Búsqueda los subdirectorios
Salida F$(0) = Nombre del fichero encontrado
P(0) = 1
P(1) = Atributos del fichero encontrado (siempre 0 bajo DOS 1):
R + 2*H + 4*S + 8*V + 16*D + 32*A
R = 1 -> sólo lectura
H = 1 -> Oculto
S = 1 -> Sistema
V = 1 -> Etiqueta de volumen
D = 1 -> Directorio
A = 1 -> Archivo
P(2) = Hora de creación/modificación (0 a 23)
P(3) = Minuto de creación/modificación (0 a 59)
P(4) = Día de creación (1 a 31)
P(5) = Mes de creación (1 a 12)
P(6) = Año de creación (1980 a 2079)
P(7) = Cluster inicial (2 a 4095)
P(8) = Unidad lógica (0=A:,…,7=H:)
P(9) = Longitud (parte baja)
P(10) = Longitud (parte alta)
P(11) = 0, si buscando el primero no se ha encontrado ninguno 1, si buscando el primero se ha encontrado alguno
P(11), si buscando siguientes no se ha encontrado ninguno
P(11)+1, si buscando siguientes se ha encontrado alguno
F$(1) puede incluir una unidad y, en el caso del DOS 2, una ruta de acceso;
F$(0) contendrá únicamente el nombre del fichero hallado.P(0) se debe poner a 0 para buscar la primera entrada coincidente con la máscara especificada, y se debe dejar a 1 para ir buscando las siguientes. Esto lo hace automáticamente la función (pone siempre P(0) a 1). Además, P(11) se pone a 1 al buscar el primer fichero (a 0 si no se encuentra ninguno) y se incrementa automáticamente al ir buscando los siguientes; por tanto se puede confeccionar un bucle como este:10 'Búsqueda de todos los ficheros de la unidad B: (directorio por defecto)
20 F$(1)="B:":P(0)=0:P(1)=2+16 'Busca también directorios y f. ocultos
30 IF USR(26)<>0 THEN PRINT:PRINT"Total hallados:";P(11):END
40 PRINT F$(0),CHR$(-ASC("h")*((P(1)AND2)<>0));
CHR$(-ASC("d")*((P(1)AND16)<>0));
CHR$(-ASC("a")*((P(1)AND32)<>0)):GOTO 30Cuando ya no haya más ficheros/directorios coincidentes la función devolverá el error «Fichero no encontrado». Bajo DOS 1, un error al buscar el primer fichero puede significar también que la unidad no existe o el nombre del fichero es incorrecto (bajo DOS 2 estos errores tienen un código específico).Para obtener la longitud del fichero se puede usar la fórmula P(9)+65536*P(10). A la hora de mostrar longitudes en pantalla hay que tener en cuenta que el formato de representación de las variables numéricas varía de BASIC a TurboBASIC para números grandes; lo mejor es representar directamente la longitud en K: INT(P(9)/1024)+64*P(10).

 

Función 27 Renombrado de un fichero (S4)
Entrada F$(0) = Fichero
F$(1) = Nuevo nombre del fichero
Salida
F$(0) puede incluir una unidad y, en el caso del DOS 2, una ruta de acceso;
F$(1) únicamente el nuevo nombre del fichero. Bajo DOS 1 se puede renombrar más de un fichero a la vez usando comodines, bajo DOS 2 sólo uno cada vez.

 

Función 28 Borrado de un fichero (S4)
Entrada F$(0) = Fichero
Salida

F$(0) puede incluir una unidad y, en el caso del DOS 2, una ruta de acceso. Bajo DOS 2 la función devolverá error si se intenta borrar un fichero abierto. Bajo DOS 1 no habrá error, pero en cualquier caso no es recomendable borrar un fichero abierto, porque un posterior acceso al mismo puede dar lugar a resultados impredecibles.

Bajo DOS 1 es posible borrar más de un fichero a la vez usando comodines, bajo DOS 2 sólo uno cada vez.

 

Función 29 Desplazamiento de un fichero (DOS 2)
Entrada F$(0) = Fichero
F$(1) = Nueva localización del fichero
Salida

Esta función sólo está disponible bajo DOS 2. Bajo DOS 1 siempre devolverá el error 1.

F$(0) puede incluir una unidad y una ruta de acceso. F$(1) no debe incluir el nombre del fichero (que siempre es desplazado con el mismo nombre) ni especificación de unidad (no es posible desplazar un fichero a otra unidad, sólo a otro directorio de la misma unidad). Si se especifica un directorio en lugar de un fichero, también Serán desplazados todos sus ficheros y subdirectorios.

 

Función 30 Creación de un fichero o directorio
Entrada F$(0) = Nombre del fichero o subdirectorio
P(0) = Atributos de creación (ignorado bajo DOS 1):
R + 2*H + 4*S para crear un fichero;
2*H + 16 para crear un directorio.
R = 1 -> sólo lectura
H = 1 -> Oculto
S = 1 -> Sistema
Salida

F$(0) puede incluir una unidad y una ruta de acceso. El fichero será creado con una longitud de 0 bytes, y no quedará abierto: para acceder a él, primero hay que abrirlo explícitamente (función 31).

Bajo DOS 1 sólo es posible crear ficheros, y P(0) es ignorado. Bajo DOS 2 los ficheros siempre son creados con el atributo de «Archivo», además de los especificados en P(0).

 

Función 31 Apertura de un fichero
Entrada  F$(0) = Fichero
Salida P(0) = Número asociado al fichero

F$(0) puede incluir una unidad y, en el caso del DOS 2, una ruta de acceso. El número devuelto en P(0) identifica al fichero y hay que especificarlo posteriormente en las funciones empleadas para acceder al mismo. El valor concreto de este número depende de la versión del DOS y del número de ficheros que ya han sido abiertos y cerrados: nunca debe tomarse como referencia del número de ficheros abiertos (para ello hay que usar la función 1).

Bajo DOS 1 se generará un error 3 si ya hay demasiados ficheros abiertos. El número máximo de ficheros que pueden ser abiertos bajo DOS 1 puede consultarse mediante la función 1.

 

Función 32 Cierre de un fichero
Entrada P(0) = Número de fichero
Salida
Es importante cerrar un fichero que ya no va a ser usado, puesto que de lo contrario, si el fichero ha sido escrito pueden quedar datos perdidos en los buffers internos del DOS, además de la entrada de directorio del fichero sin actualizar.

 

Función 33 Lectura de un fichero (S4)
Entrada P(0) = Número de fichero
P(2) = Segmento de destino
P(3) = Dirección de destino
P(4) = Número de bytes a leer
P(6) = Incrementar P(3) si <>0
Salida P(7) = Número de bytes leídos
P(3) = P(3)+P(4) si P(6)<>0
P(3)+P(4) debe ser menor de &H4000, de lo contrario el resultado es impredecible.

El fichero es leído a partir de la posición que indique su puntero en ese momento; dicho puntero es incrementado automáticamente tras la lectura. Para consultar o modificar el puntero de un fichero hay que usar la función 42.

Para leer hasta el final del fichero, o para leer el fichero entero si es menor de 16K, lo mejor es intentar leer 16K (establecer P(4)=&H4000) e ignorar el error devuelto si éste es el 1 o el 199: para esta función, estos errores simplemente indican que se ha leido hasta llegar al final del fichero.

Si se llega al final del fichero antes de haber leído P(4) bytes se producirá un error; para averiguar cuántos bytes han podido ser leídos basta consultar P(7). Si no hay error, P(7) será igual a P(4); si hay un error físico (FAT incorrecta, error físico general o ausencia de disco) P(7) siempre será 0.

 

Función 34 Lectura de un fichero a VRAM (S4)
Entrada P(0) = Número de fichero
P(2) = Bloque VRAM de destino
P(3) = Dirección de destino
P(4) = Número de bytes a leer (máximo &H4000)
P(6) = Incrementar P(3) si <>0
Salida P(7) = Número de bytes leídos
P(2):P(3) = P(2):P(3)+P(4) si P(6)<>0

Si P(4) es mayor de &H4000 sólo se leerán &H4000 bytes, y el incremento de la dirección se limitará también a &H4000, pero P(4) no se modificará. Por tanto, para leer bloques mayores (hasta 64K) se puede emplear el truco explicado en la función 23.

Para esta función también son válidas las consideraciones sobre el puntero del fichero y el valor de P(7) hechas en la descripción de la función 33.

 

Función 35 Lectura de sectores de disco (S4)
Entrada P(0) = Unidad (0=A:,…,7=H:)
P(1) = Sector inicial
P(2) = Segmento de destino
P(3) = Dirección de destino
P(4) = Número de sectores a leer (máximo 32)
P(6) = Incrementar P(3) si <>0
Salida P(7) = P(4)*512 (0 en condiciones de error)
P(3) = P(3)+P(4)*512 si P(6)<>0
P(3)+P(4)*512 debe ser menor de &H4000, de lo contrario el resultado es impredecible.
Esta función no soporta lecturas parciales: si no hay error entonces P(7) contiene el número de bytes leídos, es decir, P(4)*512; en caso de error es 0. Si P(6)<>0, a P(3) se le sumará el número de bytes leídos (P(7) o 0).

 

Función 36 Lectura de sectores de disco a VRAM (S4)
Entrada P(0) = Unidad (0=A:,…,7=H:)
P(1) = Sector inicial
P(2) = Bloque VRAM de destino
P(3) = Dirección de destino
P(4) = Número de sectores a leer (máximo 32)
P(6) = Incrementar P(3) si <>0
Salida P(7) = P(4)*512 (0 en condiciones de error)
P(3) = P(3)+P(4)*512 si P(6)<>0

Si P(4) es mayor de 32 sólo se leerán 32 sectores (&4000 bytes), y el incremento de la dirección se limitará también a &4000, pero P(4) no se modificará. Por tanto, para leer bloques mayores (hasta 64K) se puede emplear el truco explicado en la función 23.

Para esta función también son válidas las consideraciones sobre P(7) hechas en la descripción de la función 35.

 

Función 37 Escritura en un fichero (S4)
Entrada P(0) = Número de fichero
P(2) = Segmento de origen
P(3) = Dirección de origen
P(4) = Número de bytes a leer
P(6) = Incrementar P(3) si <>0
Salida P(7) = Número de bytes escritos
P(3) = P(3)+P(4) si P(6)<>0
P(3)+P(4) debe ser menor de &H4000, de lo contrario el los datos escritos en el fichero son impredecibles.
El fichero es escrito a partir de la posición que indique su puntero en ese momento; dicho puntero es incrementado automáticamente tras la escritura. Para consultar o modificar el puntero de un fichero hay que usar la función 42. En caso de error físico (FAT incorrecta, error físico general, ausencia de disco o disco protegido contra escritura), P(7) será 0.

 

Función 38 Escritura en un fichero desde VRAM (S4)
Entrada P(0) = Número de fichero
P(2) = Bloque VRAM de origen
P(3) = Dirección de origeno
P(4) = Número de bytes a escribir (máximo &H4000)
P(6) = Incrementar P(3) si <>0
Salida P(7) = Número de bytes escritos
P(2):P(3) = P(2):P(3)+P(4) si P(6)<>0

Si P(4) es mayor de &4000 sólo se escribirán &4000 bytes, y el incremento de la dirección se limitará también a &4000, pero P(4) no se modificará. Por tanto, para escribir bloques mayores (hasta 64K) se puede emplear el truco explicado en la función 23.

Para esta función también son válidas las consideraciones sobre el puntero del fichero hechas en la descripción de la función 37.

 

Función 39 Escritura de sectores de disco (S4)
Entrada P(0) = Unidad (0=A:,…,7=H:)
P(1) = Sector inicial
P(2) = Segmento de origen
P(3) = Dirección de origen
P(4) = Número de sectores a escribir (máximo 32)
P(6) = Incrementar P(3) si <>0
Salida P(7) = P(4)*512 (0 en condiciones de error)
P(3) = P(3)+P(4)*512 si P(6)<>0
P(3)+P(4)*512 debe ser menor de &H4000, de lo contrario los datos escritos son impredecibles.
Esta función no soporta escrituras parciales: si no hay error entonces P(7) contiene el número de bytes escritos, es decir, P(4)*512; en caso de error es 0. Si P(6)<>0, a P(3) se le sumará el número de bytes escritos (P(7) o 0).

 

Función 40 Escritura de sectores de disco desde VRAM (S4)
Entrada P(0) = Unidad (0=A:,…,7=H:)
P(1) = Sector inicial
P(2) = Bloque VRAM de origen
P(3) = Dirección de origen
P(4) = Número de sectores a escribir (máximo 32)
P(6) = Incrementar P(3) si <>0
Salida P(7) = P(4)*512 (0 en condiciones de error)
P(3) = P(3)+P(4)*512 si P(6)<>0

Si P(4) es mayor de 32 sólo se escribirán 32 sectores (&H4000 bytes), y el incremento de la dirección se limitará también a &H4000, pero P(4) no se modificará. Por tanto, para escribir bloques mayores (hasta 64K) se puede emplear el truco explicado en la función 23.

Para esta función también son válidas las consideraciones sobre P(7) hechas en la descripción de la función 39.

 

Función 41 Relleno de un fichero con un dato (S4)
Entrada P(0) = Número de fichero
P(1) = Dato (un byte)
P(4) = Longitud (máximo &H4000)
Salida P(7) = Número de bytes escritos
Esta función simplemente escribe P(4) bytes iguales a P(1) a partir de la dirección 0 en el segmento 4, y hace una llamada a la función 37 con P(2)=4 y P(3)=0. Por tanto, son válidas todas las consideraciones hechas en la explicación de la función 37.

 

Función 42 Movimiento del puntero de un fichero
Entrada P(0) = Número de fichero
P(1) = Base del desplazamiento del puntero:
0 -> Desplazamiento relativo al principio del fichero
1 -> Desplazamiento relativo a la posición actual
2 -> Desplazamiento relativo al final del fichero
P(2) = Desplazamiento (parte baja)
P(3) = Desplazamiento (parte alta)
Salida  P(4) = Nueva posición del puntero (parte baja)
P(5) = Nueva posición del puntero (parte alta)

Para establecer P(2) y P(3) con un desplazamiento D mayor que 32768 o menor que 0 hay que emplear la fórmula siguiente:

P(3)=INT(D/65536):P(2)=VAL(«&H»+HEX$(D-(P2*65536)))

y para recomponer el nuevo puntero en P hay que hacer

P=P(2)-(65536*(P(2)<0))+65536!*P(3)

Dado que el TurboBASIC trata las variables de coma flotante de forma especial, si se usan estas fórmulas dentro de un turbo-bloque es necesario que D sea un múltiplo entero de 256.

Para consultar la posición actual del puntero basta usar esta función con P(1)=1, P(2)=0 y P(3)=0; y para consultar la longitud del fichero, usarla con P(1)=2, P(2)=0 y P(3)=0. En el primer caso el puntero queda inalterado.

Al usar esta función hay que tener en cuenta que el desplazamiento se interpreta con signo, por tanto:

– Si se usa con P(1)=0, el desplazamiento deberá ser positivo. En caso contrario el resultado de posteriores accesos al fichero es impredecible.

– Si se usa con P(1)=1, un desplazamiento positivo hará que el puntero avance, y uno negativo hará que el puntero retroceda.

– Si se usa con P(1)=2, el desplazamiento deberá ser negativo. En caso contrario el puntero se situará más alla de la longitud del fichero; en estas condiciones una lectura dará un error de fin de fichero (con 0 bytes leídos), y una escritua hará que el espacio entre el final del fichero y el puntero sea rellenado con ceros.

 

Función 43 Obtención de la unidad establecida por defecto y el vector de unidades disponibles
Entrada
Salida P(0) = Unidad establecida por defecto (0=A:,…,7=H:)
P(1) = Vector de unidades disponibles
El vector de unidades disponibles es un byte que contiene, en cada bit, información sobre si una unidad existe (bit=1) o no (bit=0); el bit más bajo corresponde a la unidad A:, y el más alto a la H:. Por ejemplo, si la función devuelve P(1)=&B01000011 significa que están disponibles las unidades A:, B: y G:.

 

Función 44 Establecimiento de la unidad por defecto
Entrada P(0) = Unidad a establecer (0=A:,…,7=H:)
Salida
Esta función devuelve el error 62 si se intenta establecer una unidad inexistente (no disponible o superior a 7).

 

 Función 45 Obtención de información sobre el espacio de un disco
Entrada P(0) = Unidad (0=Unidad por defecto, 1=A:,…,8=H:)
Salida P(1) = Sectores por cluster
P(2) = Número total de clusters (hasta 4096)
P(3) = Número de clusters libres
El espacio libre en bytes se puede averiguar mediante la fórmula P(1)*P(3)*512, o en K con P(1)*P(3)/2; y lo mismo con el espacio total, usando P(2) en lugar de P(3). Esta función devuelve el error 62 si se especifica una unidad inexistente (no disponible o superior a 8).

 

Función 46 Obtención del directorio actual (DOS 2)
Entrada P(0) = Unidad (0=Unidad por defecto, 1=A:,…,8=H:)
Salida F$(0)= Directorio actual
Esta función sólo está disponible bajo DOS 2. Bajo DOS 1 siempre devolverá el error 1. La cadena devuelta no incluirá unidad ni «\» inicial ni final; por tanto, el directorio raíz se representa mediante una cadena vacía.

 

Función 47 Establecimiento del directorio actual (DOS 2)
Entrada F$(0) = Unidad (opcional) + directorio
Salida
Esta función sólo está disponible bajo DOS 2. Bajo DOS 1 siempre devolverá el error 1. Esta función no cambia la unidad establecida por defecto, para ello hay que usar la función 44.

 

Función 48 Obtención del tamaño del RAM disk (DOS 2)
Entrada
Salida P(0) = Tamaño del RAM disk en segmentos de 16K
Esta función sólo está disponible bajo DOS 2. Bajo DOS 1 siempre devolverá el error 1. Para obtener el tamaño del RAM disk en K basta hacer P(0)*16. Un tamaño igual a 0 indica que no existe el RAM disk.

 

Función 49 Creación del RAM disk (DOS 2)
Entrada P(0) = Tamaño deseado en segmentos de 16K
Salida P(0) = Tamaño del RAM disk creado en segmentos de 16K
Esta función sólo está disponible bajo DOS 2. Bajo DOS 1 siempre devolverá el error 1. Dado que por defecto NestorBASIC reserva todos los segmentos de RAM disponibles al instalarse, antes de llamar a esta función es necesario usar la función 80 para reducir la cantidad de segmentos usados por NestorBASIC; de lo contrario no habrá segmentos libres con los que crear el RAM disk (a no ser que el ordenador disponga de más de 4M de RAM). Si no hay P(0) segmentos libres pero es posible crear un RAM disk menor, la función lo creará y no devolverá error; en P(0) se devolverá el tamaño del RAM disk que ha podido crearse. En cambio, si no hay ningún segmento libre y no puede crearse el RAM disk, sí devolverá error.

 

Función 50 Obtención del byte de atributos de un fichero (DOS 2)
Entrada P(0) = Número de fichero, o bien P(0) = 255 y F$(0) = Nombre del fichero
Salida P(1) = Byte de atributos: R + 2*H + 4*S + 8*V + 16*D + 32*A R = 1 -> sólo lectura
H = 1 -> Oculto
S = 1 -> Sistema
V = 1 -> Etiqueta de volumen
D = 1 -> Directorio
A = 1 -> Archivo

Esta función sólo está disponible bajo DOS 2. Bajo DOS 1 siempre devolverá el error 1.

Si P(0)=255 se obtendrá el byte de atributos del fichero establecido en F$(0) (puede especificarse una unidad y una ruta de acceso), en caso contrario se obtendrá dicho byte para el fichero previamente abierto con el número P(0).

 

Función 51 Establecimiento del byte de atributos de un fichero
Entrada P(0) = Número de fichero, o bien
P(0) = 255 y F$(0) = Nombre del fichero
P(1) = Nuevo byte de atributos:
R + 2*H + 4*S + 8*V + 16*D + 32*A
R = 1 -> sólo lectura
H = 1 -> Oculto
S = 1 -> Sistema
V = 1 -> Etiqueta de volumen
D = 1 -> Directorio
A = 1 -> Archivo
Salida P(1) = Byte de atributos establecido

Esta función sólo está disponible bajo DOS 2. Bajo DOS 1 siempre devolverá el error 1.

Si P(0)=255 se establecerá el byte de atributos del fichero establecido en F$(0) (puede especificarse una unidad y una ruta de acceso), en caso contrario se establecerá dicho byte para el fichero abierto con el número P(0).

No es posible establecer los atributos de un fichero abierto especificando su nombre en F$(0); si se intenta, la función generará un error. Para ello hay que establecer su número de fichero en P(0).

Un fichero sólo puede ver modificados sus atributos de sistema, oculto, sólo lectura y archivo; un subdirectorio, sólo el de oculto. Si se intenta cambiar cualquier otro, la función devolverá un error. No es posible alterar los atributos de las entradas «.» y «..»

 

Función 52 Tratamiento de una cadena de ruta de acceso (DOS 2)
Entrada F$(0) = Cadena a tratar
P(10)<>0 si la ruta hace referencia a una etiqueta de volumen
Salida F$(1) = Ultimo elemento de la ruta
P(8) = Unidad lógica (1=A:,…,8=H:)
P(9) = Posición en la cadena del último elemento
(0 si no hay último elemento)
Los siguientes parámetros a -1 si se cumple la condición, si no a 0:
P(0) La ruta contiene carácteres que no se refieren a la unidad
P(1) En la ruta se especifica un directorio
P(2) En la ruta se especifica una unidad
P(3) En la ruta se especifica el nombre de un fichero
P(4) En la ruta se especifica la extensión de un fichero
P(5) El último elemento es ambiguo
P(6) El último elemento es «.» o «..»
P(7) El último elemento es «..»

Esta función sólo está disponible bajo DOS 2. Bajo DOS 1 siempre devolverá el error 1.

Esta función simplemente trata la cadena de entrada devolviendo los parámetros especificados. No accede a disco ni modifica la unidad o el directorio por defecto.

Si sólo se especifica una unidad, o el último carácter de la ruta es el separador de directorios «\», no existe el «último elemento» de la cadena. En ese caso P(9) valdrá 0 y F$(1) será una cadena vacía. Ejemplo: para F$(0) = «A:\DIR\FILES\FICHE.RO», el último elemento, devuelto en F$(1), es «FICHER.RO», y P(9) valdrá 14.

Si la ruta no contiene especificación de unidad, la unidad establecida por defecto en el sistema será devuelta en P(2). Por tanto P(2) nunca será cero.

Si P(10)<>0 a la entrada, los parámetros P(1) y P(4) a P(7) siempre valdrán 0.

10.6. FUNCIONES DE COMPRESION Y DESCOMPRESION DE GRAFICOS

Función 53 Compresión de datos gráficos
Entrada P(0) = Bloque VRAM de origen inicial
P(1) = Dirección VRAM de origen inicial
P(2) = Segmento de destino inicial
P(3) = Dirección RAM de destino inicial
P(4) = Tamaño de la imagen a comprimir
P(5) = Incrementar P(1) si <>0
P(6) = Incrementar P(3) si <>0
Salida P(7) = Tamaño en RAM de la imagen comprimida
P(8) = Número de segmentos utilizados
P(0):P(1) = P(0):P(1) + P(4) si P(5)<>0
P(2):P(3) = Dirección RAM siguiente a la última utilizada, si P(6)<>0

La compresión se realiza a través de segmentos consecutivos: tras comprimir a la posición &H3FFF del segmento S, se continúa con la posición &H0000 del segmento S+1. Si se sobrepasa la dirección &H3FFF del último segmento, la función devolverá el error 5. Esta función no soporta segmentos VRAM, ni el segmento 255.

Si la última dirección RAM utilizada es la &H3FFF del segmento S y P(6)<>0 a la entrada, a la salida P(2) valdrá S+1 y P(3) valdrá 0. Si S era el último segmento, P(2) valdrá 0.

 

Función 54 Descompresión de datos gráficos
Entrada P(0) = Bloque VRAM de destino inicial
P(1) = Dirección VRAM de destino inicial
P(2) = Segmento de origen inicial
P(3) = Dirección RAM de origen inicial
P(5) = Incrementar P(1) si <>0
P(6) = Incrementar P(3) si <>0
Salida P(7) = Tamaño en VRAM de la imagen descomprimida
P(8) = Número de segmentos utilizados
P(0):P(1) = P(0):P(1) + P(7) si P(5)<>0
P(2):P(3) = Dirección RAM siguiente a la última utilizada, si P(6)<>0

La descompresión se realiza a través de segmentos consecutivos: tras descomprimir de la posición &H3FFF del segmento S, se continúa con la posición &H0000 del segmento S+1. Si se sobrepasa la dirección &H3FFF del último segmento, o si se encuentra un dato incorrecto, la función devolverá el error 6. Esta función no soporta segmentos VRAM, ni el segmento 255.

Si la última dirección RAM utilizada es la &H3FFF del segmento S y P(6)<>0 a la entrada, a la salida P(2) valdrá S+1 y P(3) valdrá 0. Si S era el último segmento, P(2) valdrá 0.

10.7. FUNCIONES PARA LA EJECUCION DE PROGRAMAS BASIC

Función 55 Ejecución de un programa BASIC almacenado en un segmento (S4)
Entrada P(0) = Segmento
P(1) = Dirección inicial
Salida

MUY IMPORTANTE: Para poder usar esta función hay que cambiar la dirección de comienzo de los programas BASIC. Ver sección 6 para más detalles.

Esta función ejecuta el programa BASIC almacenado en el segmento indicado. El programa ha de estar almacenado a partir de la dirección indicada en P(1) del segmento especificado en P(0), con el siguiente formato:

+&H0000: No usado por NestorBASIC. Puede ser útil, por ejemplo, para insertar un byte identificador.
+&H0001: Dirección final del programa +1, en el rango &H8000-&HBFFF; byte bajo.
+&H0002: Idem, byte alto.
+&H0003: Inicio del programa

Todas las variables numéricas del programa original Serán traspasadas al programa ejecutado. Es posible ejecutar esta función desde dentro de un turbo-bloque; en este caso sólo se transferirán las variables enteras creadas fuera del mismo que hayan sido especificadas al principio con CALL TURBO ON (variable, …, matriz(), …).

Las variables de cadena que hayan sido guardadas en la zona de cadenas también serán transferidas; no así aquellas que hayan sido asignadas directamente desde el programa BASIC: éstas residen dentro del mismo, y se perderán. Para asegurarse de que una cadena es almacenada en la zona de cadenas hay que realizar la siguiente operación: C$=C$+»». Evidentemente, la opción más práctica es centralizar todas las cadenas en una matriz (por ejemplo F$), y realizar esta operación con un simple bucle.

Esta función devolverá el error -1 si se especifica un segmento inexistente (el segmento 255 no es soportado), y el -2 si la memoria del BASIC es insuficiente para albergar el nuevo programa y las variables. Esto puede ocurrir si el programa ejecutado es más largo que el original, pero no es probable si la diferencia de longitudes entre ambos programas no es exagerada y el número de variables es razonablemente bajo.

 

Función 56 Activación de un programa BASIC almacenado en un segmento (S4)
Entrada P(0) = Segmento
P(1) = Dirección inicial
Salida

MUY IMPORTANTE: Para poder usar esta función hay que cambiar la dirección de comienzo de los programas BASIC. Ver sección 6 para más detalles.

Esta función actúa como la función 55, con la siguiente diferencia: una vez que el nuevo programa y las variables están en la memoria del BASIC, el programa no es ejecutado y el BASIC vuelve al modo directo. Por lo demás, el funcionamiento es idéntico, así como los posibles errores.

 

Función 57 Grabación de un programa BASIC con cabecera en un fichero (S4)
Entrada P(0) = Byte a grabar en la primera posición (no usado por NestorBASIC)
F$(0) = Ruta + nombre del fichero
Salida P(1) = -1 -> No hay error
<> -1 -> Ha habido un error de disco, y el fichero ha quedado abierto con ese número; el código de error es devuelto entonces por el USR, como siempre.

MUY IMPORTANTE: Para poder usar esta función hay que cambiar la dirección de comienzo de los programas BASIC. Ver sección 6 para más detalles.

Esta función graba el programa BASIC activo en el fichero especificado, con la cabecera adecuada para ser ejecutado o activado con las funciones 55 o 56 (ver descripción de la función 55 para detalles sobre el formato).

El uso de esta función simplifica la conversión de programas BASIC normales a programas ejecutables con la función 55, proceso que se reduce a:

load"prog.bas" 'Carga del programa BASIC
f$(0)="prog.nba":?USR(57) 'Grabación con cabecera (P(0) opcional)

Una vez grabado de esta forma, la carga y ejecución del programa es sencilla:

1000 'Apertura de prog.nba, lectura al segmento S y cierre del fichero
1001 F$(0)="prog.nba":?USR(31):P(2)=S:P(3)=0:P(4)=&H4000:?USR(33):?USR(32)
...
10000 'Ejecución del programa (tratamiento del error opcional)
10001 P(0)=S:P(1)=0:IF USR(55)=-1 THEN PRINT "ERROR: Segmento inexistente!" ELSE PRINT "ERROR: Memoria insuficiente!"
10002 END

Usando la función 56 en lugar de la 55 es posible cargar programas grabados con cabecera de los cuales no se tenga copia en formato normal (LOADable).

Por supuesto, también pueden usarse las funciones normales de acceso a disco para grabar el programa, pero entonces habrá que crear la cabecera a mano:

POKE &H8000,P(0) 'Dato no usado por NestorBASIC
POKE &H8001,PEEK(&HF676)
POKE &H8002,PEEK(&HF677)
'Grabar de &H8000 a PEEK(&H8001)+256*PEEK(&H8002)

Los posibles errores devueltos por esta función son los mismos que los de las funciones de acceso a disco (ver sección 4.2). En el caso de que una finalización con error provoque que el fichero quede abierto, P(1) contendrá el número asociado al fichero; en caso contrario valdrá -1.

10.8. FUNCIONES VARIAS

Función 58 Ejecución de una rutina de la BIOS, de la SUB-BIOS, de la memoria BASIC o de la zona de trabajo del sistema
Entrada P(0) = 0 para ejecutar una rutina de la BIOS, de la memoria BASIC o de la zona de trabajo del sistema
<> 0 para ejecutar una rutina de la SUB-BIOS
P(1) = Dirección de inicio de la rutina
P(2) a P(11) = Registros de entrada a la rutina:
P(2) = AF P(8) = AF’
P(3) = BC P(9) = BC’
P(4) = DE P(10)= DE’
P(5) = HL P(11)= HL’
P(6) = IX
P(7) = IY
Salida P(2) a P(12) = Registros de salida de la rutina, con la misma asignación que a la entrada, más los siguientes:
P(12) = A
P(13) = Bandera Cy (-1 si establecida, 0 si no)
P(14) = Bandera Z (-1 si establecida, 0 si no)

Esta función permite ejecutar rutinas en código máquina de la BIOS, de la SUB-BIOS, de la memoria del BASIC o de la zona de trabajo del sistema, con posibilidad de establecer los registros del Z80 antes de la llamada usando la matriz de parámetros; el estado de los registros tras la llamada también puede ser consultado de la misma forma.

Si P(0)=0 a la entrada, la función ejecutará directamente la rutina en código máquina situada en la dirección especificada en P(1), sin realizar ningún cambio de slot o segmento. En la práctica esto significa que de esta forma se pueden ejecutar rutinas de la BIOS (si la dirección está entre 0 y &H3FFF), rutinas cargadas por el usuario en la memoria del BASIC (por ejemplo con BLOAD), o bien rutinas del sistema situadas en la zona de trabajo en página 3 (por ejemplo el gancho de la BIOS extendida, situado en &HFFCA).

Nótese sin embargo que cuando esta función es ejecuada, el segmento de NestorBASIC está conectado en la página 1. Esto implica que no se pueden ejecutar directamente rutinas que están en la ROM del intérprete del BASIC. Para ejecutar tales rutinas se debe usar la rutina de la BIOS CALBAS (&H0159), que admite en IX la dirección de la rutina del intérprete del BASIC a llamar.

Si P(0)<>0 a la entrada, se ejecutará la rutina situada en la dirección P(1) de la SUB-BIOS; en este caso, se devolverá un error -1 si se especifica una dirección superior a &H3FFF. Para efectuar la llamada a la SUB-BIOS se usa la rutina de la BIOS EXTROM, por lo que el contenido del registro IX [variable P(6)] a la entrada se perderá.

El valor devuelto en P(12) será igual al valor devuelto en el byte alto de P(2). Del mismo modo, los valores devueltos en P(13) y P(14) indicarán el mismo estado que los bits 0 y 6, respectivamente, del byte bajo de P(2). Dado que normalmente interesa recuperar el valor devuelto en A por sí mismo o bien los valores de las banderas Cy y Z por sí mismas, en vez del valor del par AF completo, el uso de P(12) a P(14) resultará más conveniente que el uso de P(2) al examinar los registros de salida. Sin embargo, para establecer el valor de A y de las banderas a la entrada es necesario usar P(2), no se pueden usar P(12) a P(14). El valor a establecer en P(2) se puede calcular mediante la siguiente fórmula:

P(2) = Cy + 2*N + 4*P/V + 16*H + 64*Z + 128*M + 256*A

 

Función 59 Ejecución de una rutina de usuario (rutina en código máquina contenida en un segmento)
Entrada P(0) = Segmento en el que reside la rutina
P(1) = Dirección de inicio de la rutina
P(2) a P(11) = Registros de entrada a la rutina:
P(2) = AF P(8) = AF’
P(3) = BC P(9) = BC’
P(4) = DE P(10)= DE’
P(5) = HL P(11)= HL’
P(6) = IX
P(7) = IY
Salida P(2) a P(12) = Registros de salida de la rutina,
con la misma asignación que a la entrada,
más los siguientes:
P(12) = A
P(13) = Bandera Cy (-1 si establecida, 0 si no)
P(14) = Bandera Z (-1 si establecida, 0 si no)

Esta función permite ejecutar rutinas en código máquina residente en un segmento, con posibilidad de establecer los registros del Z80 antes de la llamada usando la matriz de parámetros; el estado de los registros tras la llamada también puede ser consultado de la misma forma.

El segmento indicado será conectado en la página 2 para la ejecución de la rutina, por lo que ésta debe estar ensamblada entre las direcciones &H8000 y &HBFFF. La BIOS estará conectada y disponible en la página 0, y el segmento de NestorBASIC en la página 1 antes de la llamda a la rutina. Al final de la misma este estado ha de ser reestablecido si se realizan cambios de slot o segmento.

Algunas de las rutinas y variables internas de NestorBASIC (rutinas para la manipulación de RAM y VRAM, y para obtener información sobre las interrupciones, entre otras) pueden ser usadas por las rutinas de usuario. En el apéndice 2 se detalla la ubicación y el funcionamiento de dichas rutinas y variables.

Para esta rutina también sín válidas las consideraciones sobre los valores de salida P(12) a P(14) hechas en la explicación de la función 58.

Esta función no soporta segmentos VRAM ni el segmento 255, y devolverá el error -1 si se indica un segmento inexistente en P(0).

 

Función 60 Impresión de una cadena en modo gráfico
Entrada F$(0) = Cadena
Salida

Esta función sólo funciona en los modos gráficos SCREEN 5 a 11, y es equivalente a la instrucción PRINT#1,F$(0) previa ejecución de OPEN»GRP:»AS#1. La diferencia es que esta función es compatible con TurboBASIC. Ejecutada en otros modos gráficos no hará nada; nunca devuelve error.

La longitud máxima de la cadena es de 80 carácteres; si es más larga, sólo se imprimirán los primeros 80. La cadena no puede contener el carácter 0, que es tomado como carácter de terminación de la misma.

 

Función 61 Almacenamiento de una cadena en un segmento
Entrada F$(0) = Cadena
P(0) = Segmento
P(1) = Dirección
P(2) = Incrementar P(1) si <>0
Salida P(1) = P(1) + LEN(F$(0)) + 1 si P(2)<>0

Esta función almacena la cadena F$(0) a partir de la dirección especificada del segmento especificado. La cadena se almacena con un carácter 0 al final, por lo que ocupará LEN(F$(0))+1 bytes.

La longitud máxima de la cadena es de 80 carácteres; si es más larga, sólo se almacenarán los primeros 80. La cadena no puede contener el carácter 0, ya que de ser encontrado uno será interpretado como el final de la misma.Esta función devuelve el error -1 si se especifica un segmento inexistente en P(0).

 

Función 62 Recuperación de una cadena almacenada en un segmento
Entrada P(0) = Segmento
P(1) = Dirección
P(2) = Incrementar P(1) si <>0
Salida F$(1) = Cadena
P(1) = P(1) + LEN(F$(1)) + 1 si P(2)<>0

Esta función copia en F$(1) la cadena almacenada a partir de la dirección especificada del segmento especificado. La cadena se da por terminada cuando se encuentra un carácter 0, o cuando ya se han copiado 80 carácteres.

Si la función se ejecuta desde el BASIC normal, la cadena no puede contener carácteres 255, ya que de ser encontrados Serán sustituidos por el carácter 34 (comillas); esto es debido al método de asignación de cadenas en BASIC, que requiere un tratamiento especial para las comillas. Esta limitación no se presenta si se ejecuta la función desde un turbo-bloque.

Esta función devuelve el error -1 si se especifica un segmento inexistente en P(0).

 

Función 63 Inicialización del modo de parpadeo en SCREEN 0
Entrada

P(0) = Color del texto parpadeante

P(1) = Color del fondo parpadeante
P(2) = Tiempo de parpadeo activo (0 a 15)
P(3) = Tiempo de parpadeo inactivo (0 a 15)
Si P(2) y P(3) son 0, sólo se borra la zona de parpadeo en VRAM

Salida

Esta función inicializa los colores y los tiempos del modo de parpadeo («blink mode») en SCREEN 0, y borra la zona de la VRAM dedicada a guardar las coordenadas de los carácteres que parpadean. Si P(2) y P(3) son cero, sólo se borra la VRAM y no se modifican los colores ni los tiempos.

Esta función sólo puede ejecutarse en modo SCREEN 0 con al menos 41 columnas; en caso contrario no hará nada salvo devolver el error -1.

Las acciones que realiza esta función se pueden conseguir por separado desde el BASIC de la siguiente manera:

– Establecimiento de los colores:

VDP(13) = Color texto + 16*Color fondo

– Establecimiento de los tiempos:

VDP(14) = Tiempo activo + 16*Tiempo inactivo

– Borrado de la VRAM:

Llenar con ceros la zona de 256 bytes de VRAM que comienza en &H0A00

Las variables del sistema FORCLR (&HF3E9) y BAKCLR (&HF3EA) contienen respectivamente el color de texto y el color de fondo establecidos con el comando COLOR. Por tanto, para conseguir un efecto de vídeo inverso basta hacer:

P(0)=PEEK(&HF3EA):P(1)=PEEK(&HF3E9):P(2)=15:P(3)=0:?USR(63)

o bien

VDP(13)=PEEK(&HF3EA)+16*PEEK(&HF3E9):VDP(14)=&HF0

 

Función 64 Construcción o borrado de un bloque de carácteres parpadeantes en SCREEN 0
Entrada P(0) = 0 para borrar bloque
<> 0 para crear bloque
P(1) = Coordenada X (columna) inicial (0 a 79)
P(2) = Coordenada Y (fila) inicial (0 a 27)
P(3) = Longitud en X (columnas)
P(4) = Longitud en Y (filas)
P(5) = Actualizar P(1) si <>0
P(6) = Actualizar P(2) si <>0
Salida P(1) = P(1) + P(3) si P(5)<>0
P(2) = P(2) + P(4) si P(6)<>0

Esta función crea o borra el bloque de carácteres parpadeantes de las dimensiones especificadas, en las coordenadas especificadas. Es conveniente haber ejecutado la función 63 antes de usar esta.

Esta función sólo puede ejecutarse en modo SCREEN 0 con al menos 41 columnas; en caso contrario no hará nada, y no devolverá error. Si P(1)>79 y/o P(2)>27 a la entrada, devolverá el error -1.

La función no comprueba si el bloque sobrepasa los límites de la pantalla. Si un bloque sobrepasa la columna 79, continuará en la columna 0 de la línea siguiente. Por el contrario, aquella parte del bloque que sobrepase la línea 27 no se visualizará.

 

Función 65 Obtención de información sobre las interrupciones
Entrada
Salida P(0) = -1 si hay alguna interrupción en marcha
(interrupción de usario, efecto de sonido
o reproducción de música)
P(1) = -1 si hay una interrupción de usuario en marcha
P(2) = Segmento de la interrupción de usuario
P(3) = Dirección de la interrupción de usuario
P(4) = -1 si hay un efecto de sonido en marcha
P(5) = -1 si hay una música en reproducción

P(2) y P(3) devuelven la definición de la interrupción de usuario, aunque está suspendida. Si no se ha definido ninguna, ambos parámetros valdrán cero.

Para obtener más información sobre el efecto de sonido en marcha hay que usar la función 67. En cuanto a la música, la función a utilizar para obtener más información es la 72.

 

Función 66 Definición o suspensión de una interrupción de usuario
Entrada P(0) = 0 para suspender la interrupción en curso
1 para definir y establecer una interrupción
-1 para invertir el estado de la interrupción
(establecida <–> suspendida)
P(1) = Segmento de la interrupción (ignorado si P(0)<>1)
P(2) = Dirección de la interrupción (ignorado si P(0)<>1)
Salida

Esta función define o suspende una interrupción de usuario, es decir, una rutina en código máquina que será ejecutada en cada interrupción del reloj, 50 o 60 veces por segundo.

Si P(0)=1, la interrupción queda definida mediante P(1) y P(2), y establecida (se ejecuta a 50 o 60 Hz). Si P(0)=0, la interrupción queda suspendida (no se ejecuta), pero su definición no cambia. Si P(0)=-1 se invierte el estado de la interrupción (de establecimiento a suspensión y viceversa), pero tampoco cambia la definición de la misma.

El segmento de la interrupción será conectado en la página 2 para la ejecución de la misma, por lo que ésta debe estar ensamblada entre las direcciones &H8000 y &HBFFF. La BIOS estará conectada en la página 0 y el segmento de NestorBASIC en la página 1; este estado ha de ser reestablecido al final de la interrupción en caso de que ésta realice cambios de slot o segmento. Las interrupciones estarán inhibidas y así han de permanecer durante la ejecución de la interrupción. No es necesario preservar ningún registro, NestorBASIC ya se encarga de ello.

Algunas de las rutinas y variables internas de NestorBASIC (rutinas para la manipulación de RAM y VRAM, y para obtener información sobre las interrupciones, entre otras) pueden ser usadas por la interrupción de usuario. En el apéndice 2 se detalla la ubicación y el funcionamiento de dichas rutinas y variables.

No es posible definir una interrupción en un segmento VRAM, ni en el 255. Esta función devolverá el error -1 si se indica un segmento inexistente en P(1). Si se especifica un valor distinto de 0, 1 o -1 en P(0), la función devolverá el error 7.

10.9. EFECTOS DE SONIDO PSG

Función 67 Obtención de información sobre los efectos de sonido PSG
Entrada P(0) = Nuevo volumen máximo (0 a 15, -1 para no cambiarlo)
Salida P(1) = -1 si hay un efecto sonando
P(2) = Número de efecto que suena, o del último que ha sonado
P(3) = Prioridad del efecto que suena, o del último que ha sonado
P(4) = Segmento del juego de efectos
P(5) = Dirección del juego de efectos
P(6) = Número más alto de efecto definido
P(7) = Volumen máximo

La información devuelta por esta función sólo será válida si el juego de efectos ha sido inicializado con la función 68. El juego de efectos ha de haber sido creado con el editor SEE versión 3.xx, desarrollado por Fuzzy Logic.

Esta función nunca devuelve error. Si se especifica un valor mayor que 15 en P(0), será interpretado como 15.

 

Función 68 Inicialización de un juego de efectos de sonido PSG
Entrada P(0) = Segmento
P(1) = Dirección
Salida

Esta función inicializa el juego de efectos de sonido almacenado en el segmento y dirección especificados, dejándolo listo para su uso mediante la función 69.

El juego de efectos ha de haber sido creado con el editor SEE versión 3.xx, de Fuzzy Logic; si el formato del juego es incorrecto la función devolverá el error 8.

No es posible usar un juego de efectos almacenado en segmentos VRAM ni en el segmento 255. Esta función devolverá el error -1 si se indica un segmento inexistente en P(0).

 

Función 69 Reproducción de un efecto de sonido PSG
Entrada P(0) = Número de efecto
P(1) = Prioridad (0: baja, <>0: alta)
Salida

Esta función reproduce el efecto de sonido especificado del juego de efectos inicializado con la función 68. El juego de efectos ha de haber sido creado con el editor SEE versión 3.xx, de Fuzzy Logic. No se ha de ejecutar esta función si no se ha inicializado antes el juego de efectos: el resultado en este caso es impredecible.

P(1) regula la prioridad en caso de intentar reproducir un efecto cuando ya está sonando otro. Funciona de la siguiente manera:

– Si el efecto que está sonando y el nuevo tienen la misma prioridad, el efecto en curso se interrumpe y comienza la reproducción del nuevo.
– Si el efecto que está sonando tiene prioridad baja y el nuevo tiene prioridad alta, lo mismo.
– Si el efecto que está sonando tiene prioridad alta y el nuevo tiene prioridad baja, el efecto en curso sigue sonando y la función devuelve el error 11.

Si el efecto especificado en P(0) no está definido (la pista inicial se ha dejado en «OFF» en el editor), la función devolverá el error 9. Si el efecto no existe (el número de efecto es mayor que el número de efecto más alto), se devolverá el error 10.

 

Función 70 Interrupción del efecto de sonido PSG en curso
Entrada
Salida
Esta función interrumpe la reproducción del efecto de sonido en curso si lo hay, y silencia el PSG. Nunca devuelve error.

10.10. FUNCIONES PARA LA REPRODUCCION DE MUSICA MOONBLASTER

Función 71 Carga e inicialización, o desinstalación, del reproductor Moonblaster (S4)
Entrada P(0) = Reproductor a cargar:
0: Moonblaster 1.4
1: Moonblaster para Moonsound, versión Wave 1.05
3: Detección automática: Cargar reproductor Moonblaster Wave si hay MoonSound; si no, cargar reproductor Moonblaster 1.4.
-1: Desinstalar el reproductor cargado actualmente
Salida P(0) = Reproductor cargado (0, 1 o -1, igual que a la entrada)
P(1) = -1 -> No hay error
<> -1 -> Ha habido un error de disco, y NBASIC.BIN ha quedado abierto con ese número; el código de error es devuelto entonces por el USR, como siempre.

Esta función carga el reproductor de músicas seleccionado por P(0) en el segmento 5, dejándolo listo para su uso. también realiza una Búsqueda de todos los chips musicales existentes, y los deja todos activos (ver función 73 para más detalles sobre la activación y desactivación de chips).

Para que el reproductor pueda ser cargado, el segmento 5 ha de existir y pertenecer al mapeador primario; en caso contrario la función devolverá el error -1. En caso de error de disco al leer el fichero, la función devolverá el código de error correspondiente (ver sección 4.2). Si a causa de un error de disco NBASIC.BIN queda abierto, su número de fichero asociado será devuelto en P(1); en caso contrario P(1) valdrá -1.

El fichero NBASIC.BIN contiene dos versiones del reproductor de Moonblaster Wave: una es para ordenadores MSX2/2+ y para el Turbo-R en modo Z80, y la otra es para el Turbo-R en modo R800. En el caso del Turbo-R, NestorBASIC decide qué versión cargar en función del procesador conectado en el momento de ejecutar la función 71. Hay que tener en cuenta que si se realiza un cambio de procesador es necesario volver a ejecutar esta función, ya que la versión Z80 no funciona en modo R800 y la versión R800 introduce en modo Z80 un ralentizamiento innecesario del sistema.

Para desinstalar el reproductor se puede usar esta misma función con P(0)=-1 a la entrada; no es necesario detener antes la música que está sonando, la función ya se encarga de eso. Tras la desinstalación (consistente simplemente en el borrado de la cadena «NestorPlayer» situada al principio del segmento 5), el segmento 5 vuelve a estar disponible como un segmento más. Si se intenta desinstalar el reproductor cuando no hay ningún reproductor instalado, la función no hará nada, y no devolverá error.

Se pueden cargar, desinstalar y volver a cargar los reproductores Moonblaster tantas veces como sea necesario a lo largo de un programa. Si hay un reproductor cargado y se desea cargar otro, es conveniente desinstalar primero el que hay cargado.

 

Función 72 Obtención de información sobre la música en reproducción
Entrada
Salida P(0) = -1 si hay una música sonando o pausada
P(1) = -1 si hay una música Moonblaster 1.4 sonando o pausada
P(2) = -1 si hay una música Moonblaster Wave sonando o pausada
P(3) = 0
P(4) = -1 si hay una música pausada
P(5) = Segmento de la música que suena, o de la última que ha sonado
P(6) = Dirección inicial de la música que suena, o de la última que ha sonado
P(7) = Posición actual
P(8) = Paso actual en la posición (0 a 15)
P(9) = -1 si hay un MSX-MUSIC detectado
P(10)= -1 si hay un MSX-AUDIO detectado
P(11)= -1 si hay un OPL4 detectado
P(12)= -1 si el reproductor está cargado
P(13)= Reproductor cargado (válido sólo si P(12)=-1):
0: Moonblaster 1.4
1: Moonblaster Wave 1.05
F$(0)= Título de la musica (cadena vacía si no suena ninguna)
F$(1)= Samplekit o wavekit (cadena vacía si no suena ninguna música)

Si no hay ningún reproductor cargado, P(12) valdrá 0 y el resto de parámetros de salida no Serán establecidos (excepto P(9) a P(11)); la función no devolverá ningún error. Para cargar el reproductor hay que usar la función 71.

Si no hay ninguna música sonando, P(5) y P(6) devolverán la posición y el paso en que se detuvo la última música reproducida, y F$(0) y F$(1) estarán vacías. En caso contrario, F$(0) devolverá el título de la música (siempre 40 carácteres en el caso de una música Moonblaster 1.4, 50 para una música Moonblaster Wave) y F$(1) el samplekit o wavekit que había sido cargado en el Moonblaster cuando la música se grabó, en mayúsculas y sin extensión («NONE» si no había ninguno).

P(9) a P(11) devuelven información sobre los chips detectados, aún en el caso de que no haya ningún reproductor cargado. Para obtener información sobre los chips activos hay que usar la función 73.

 

Función 73 Activación y desactivación de los chips musicales
Entrada P(0) = 0 -> sólo consultar chips activos
1 -> Activar o desactivar chips según P(1) a P(3)
2 -> Activar todos los chips presentes
P(1) = 0 -> No modificar estado del MSX-MUSIC
1 -> Desactivar MSX-MUSIC
2 -> Activar MSX-MUSIC
-1 -> Invertir estado del MSX-MUSIC
P(2) = 0 -> No modificar estado del MSX-AUDIO
1 -> Desactivar MSX-AUDIO
2 -> Activar MSX-AUDIO
-1 -> Invertir estado del MSX-AUDIO
P(3) = 0 -> No modificar estado del OPL4
1 -> Desactivar OPL4
2 -> Activar OPL4
-1 -> Invertir estado del OPL4
Salida P(4) = 0 -> MSX-MUSIC no presente
1 -> MSX-MUSIC presente pero inactivo
2 -> MSX-MUSIC presente y activo
P(5) = 0 -> MSX-AUDIO no presente
1 -> MSX-AUDIO presente pero inactivo
2 -> MSX-AUDIO activo
P(6) = 0 -> OPL4 no presente
1 -> OPL4 presente pero inactivo
2 -> OPL4 presente y activo

Esta función permite desactivar el MSX-MUSIC, el MSX-AUDIO y el OPL4, de forma que no sonarán aunque están presentes, y volverlos a activar. Puede ser útil, por ejeplo, para oir sólo la parte MSX-AUDIO de una música en un ordenador con el MSX-MUSIC interno.

Si P(0)=0 a la entrada, la función sólo devolverá información sobre los chips activos en P(4) a P(5), y no cambiará el estado de ningún chip. Si P(0)=2, todos los chips presentes Serán activados (este es el estado establecido por defecto al cargar el reproductor musical). Para obtener información sobre los chips presentes hay que usar la función 72.

Si P(0)=1, los chips Serán activados o desactivados según P(1) a P(3); cualquier intento de activar un chip no presente será ignorado. Si tanto el MSX-MUSIC como el MSX-AUDIO (reproductor Moonblaster 1.4) o el OPL4 (reproductor Moonblaster Wave) son desactivados, la función 74 (inicio de la reproducción de una música) no hará nada pero no devolverá error.

Para que los cambios en el estado de los chips surtan efecto, la música que está sonando debe ser detenida (función 75 o 77) y recomenzada (función 74). Si no había ninguna música sonando basta iniciarla normalmente (función 74).

Esta función devolverá el error 7 si alguno de los parámetros de entrada es incorrecto (aunque si P(0)<>1 no es necesario establecer P(1) a P(3)), y el error 12 si el reproductor no ha sido cargado.

 

Función 74 Inicio de la reproducción de una música Moonblaster
Entrada P(0) = Segmento de la música
P(1) = Dirección inicial de la música
Salida

Esta función comienza la reproducción de la música Moonblaster especificada. Si el segmento especificado no existe, corresponde a VRAM o es el 255, la función devolverá el error -1. Si el reproductor adecuado a la música no está cargado, devolverá el error 12 (para cargar el reproductor hay que usar la función 71). Si la música es Moonblaster Wave puede estar almacenada a través de segmentos consecutivos; ver sección 8.2 para más detalles.

En el caso del reproductor Moonblaster 1.4, la función examina el primer byte de la música en la dirección indicada; si es &HFF significa que el fichero de la música ha sido grabado en formato EDIT y no puede ser reproducida, en cuyo caso devuelve el error 13. En caso contrario asume que en la dirección indicada comienza una música en formato USER y comienza la reproducción sin más comprobaciones. Si se especifica una dirección en la que no hay una música Moonblaster 1.4 almacenada los resultados son impredecibles.

El reproductor de Moonblaster Wave no tiene esta limitación: es capaz de detectar si en la dirección especificada realmente hay una música Moonblaster Wave, y si está grabada en modo USER; en caso contrario devuelve el error 13.

Si tanto el MSX-MUSIC como el MSX-AUDIO (reproductor Moonblaster 1.4) o el OPL4 (reproductor Moonblaster Wave) han sido desactivados con la función 73, esta función no hará nada, y no devolverá error. Si ya hay una música sonando o pausada, devolverá el error 14.

 

Función 75 Detención de la reproducción de una música
Entrada
Salida
Esta función detiene la reproducción de la música que está sonando y silencia los chips musicales. Si no hay ninguna música sonando o no hay un reproductor Moonblaster cargado, no hace nada. Nunca devuelve error.

 

Función 76 Pausa y continuación de una música
Entrada P(0) = 0 -> Pausar la música
1 -> Continuar la música pausada
-1 -> Invertir estado de la música (Reproducción <–> pausa)
Salida
Esta función pausa o continúa la reproducción de una música Moonblaster. Si no hay ninguna música sonando o pausada o si el reproductor no ha sido cargado, no hará nada, pero no devolverá error. Si el parámetro indicado en P(0) es incorrecto, devolverá el error 7.

 

Función 77 Desvanecimiento de una música
Entrada P(0) = 0 -> sólo consultar si hay un desvanecimiento en marcha
-1 -> Congelar desvanecimiento
1..254 -> Iniciar/descongelar desvanecimiento con el retardo indicado
Salida P(1) = -1 si hay un desvanecimiento en marcha
P(2) = Retardo del desvanecimiento en curso (-1 si está congelado)

Esta función inicia el desvanecimiento de la música Moonblaster en curso. El retardo indica los ciclos de reloj (de 1/50 o 1/60 segundos) que pasarán entre cada paso del desvanecimiento, por lo que un retardo más bajo implicará un desvanecimiento más rápido. Una vez que el desvanecimiento se haya completado (el volumen de la música alcance cero), la música será detenida automáticamente: no es necesario detenerla manualmente con la función 75.

Si P(0)=-1 el desvanecimiento queda congelado, es decir, la música queda sonando normalmente con el nivel de volúmen alcanzado. Para continuar con el desvanecimiento hay que volver a ejecutar esta función especificando un nuevo retardo en P(0).

Si P(0)=0 lo único que hará la función será establecer P(1) y P(2) a la salida. Si no hay ninguna música sonando o pausada, o si el reproductor no ha sido cargado, la función no hará nada. Nunca devuelve error.

 

Función 78 Carga de un samplekit de Music Module (S4)
Entrada P(0) = Número de fichero
Salida P(7) = Número de bytes leídos

Esta función carga del fichero indicado un samplekit de Music Module en formato Moonblaster: 56 bytes de cabecera, que son copiados en una zona adecuada del segmento del reproductor, y 32K de samples, que son cargados en la sample-RAM del Music Module.

El hecho de que la carga se realice desde un fichero ya abierto posibilita la concatenación del samplekit con otros datos en un único fichero: en ese caso, basta mover el puntero del fichero al punto adecuado y entonces ejecutar la función. Sin embargo, el caso más frecuente es la carga de un fichero MBK generado directamente por el Moonblaster. En tal caso bastan las siguientes intrucciones para cargar el samplekit:

F$(0)=»sampkit.mbk»:?USR(31):?USR(78):?USR(32)

En caso de producirse un error de disco, la función devolverá el código de error correspondiente, y P(7) contendrá el número de bytes que han podido ser leidos del fichero. Si este número es mayor de 16K, sólo las primeras 16K de la sample-RAM habrán sido cargadas. Si es menor, la sample-RAM no se habrá visto modificada.

Si el reproductor Moonblaster 1.4 no han sido cargado o no hay un Music Module presente, la función no hará nada, pero no devolverá error. Si la totalidad del samplekit es cargado, P(7) no valdrá 32824 sino -32712, debido a que las variables enteras en BASIC tienen un rango de -32768 a 32767.

 

Función 79 Carga de un wavekit de MoonSound (S4)
Entrada P(0) = Número de fichero
Salida P(6):P(7) = Número de bytes leidos

Esta función carga del fichero indicado un wavekit de MoonSound, que ha de haber sido grabado en formato USER. En caso contrario devuelve el error 15.

El hecho de que la carga se realice desde un fichero ya abierto posibilita la concatenación del wavekit con otros datos en un único fichero: en ese caso, basta mover el puntero del fichero al punto adecuado y entonces ejecutar la función. Sin embargo, el caso más frecuente es la carga de un fichero MWK generado directamente por el Moonblaster. En tal caso bastan las siguientes intrucciones para cargar el wavekit:

F$(0)=»wavkit.mwk»:?USR(31):?USR(79):?USR(32)

En caso de producirse un error de disco, la función devolverá el código de error correspondiente, y P(6):P(7) contendrá el número de bytes que han podido ser leidos del fichero. En este caso la sample-RAM del MoonSound puede haberse visto alterada, pero la zona de trabajo del reproductor no habrá sido actualizada, por lo que no se puede considerar que el wavekit ha sido parcialmente cargado.

Si el reproductor Moonblaster Wave no ha sido cargado o no hay un MoonSound presente, la función no hará nada, pero no devolverá error. Si la totalidad del samplekit es cargado, P(6):P(7) contendrá el tamaño total del wavekit (igual al tamaño del fichero si simplemente se carga un fichero .MWK).

10.11. FUNCIONES PARA EL CONTROL DEL USO DE SEGMENTOS

Función 80 Consulta y establecimiento del número de segmentos reservados para NestorBASIC
Entrada P(0) = Nuevo número de segmentos reservados para NestorBASIC
(0: no modificar, sólo obtener el número de segmentos reservados actualmente)
Este número incluye los segmentos de NestorBASIC, el TurboBASIC y la memoria normal del BASIC
Salida P(0) = Número de segmentos reservados para NestorBASIC tras la llamada
P(1) = Máximo número de segmentos reservables para NestorBASIC

Esta función puede ejecutarse tanto en DOS 1 como en DOS 2, pero está pensada para ser usada en DOS 2.

Bajo DOS 2, cuando NestorBASIC es instalado reserva para sí mismo todos los segmentos de RAM libres que encuentra, hasta 247. Esto implica que no quedan segmentos libres para otros programas residentes que también hagan reservas de segmentos de RAM, como el RAM disk del DOS 2, NestorMan o InterNestor Suite. La solución a este problema es usar esta función para indicarle a NestorBASIC cuántos segmentos necesitamos realmente, de forma que el resto de los segmentos sean liberados y queden disponibles para otros programas. Por ejemplo, si vamos a usar un reproductor musical (que se cargará en el segmento 5) y sólo necesitamos un segmento extra para datos, es conveniente llamar a esta función con P(0)=7; el segmento extra será el número 6.

Si se indica un número de segmentos inferior a 6 en P(0), NestorBASIC reservará 5 segmentos (ver sección 2), o 6 si hay algún reproductor musical instalado. Si se indica un número de segmentos superior al total disponible, se reservarán tantos segmentos como sea posible (hasta 247) y se devolverá en P(0) el número de segmentos que realmente han podido ser reservados. En cualquier caso, la función nunca devuelve error.

Bajo DOS 1, lo único que hace esta función es modificar variables internas de NestorBASIC; el valor devuelto en P(1) es fijo y se calcula cuando NestorBASIC es instalado. Bajo DOS 2, en cambio, esta función realmente realiza reservas o liberaciones de segmentos usando las rutinas de soporte l mapeador del DOS 2; en este caso el valor devuelto en P(1) es recalculado en cada ejecución de la función, y depende de la cantidad de segmentos que hayan sido reservados por otros programas residentes.

10.12. FUNCIONES PARA LA INTERACCION CON NESTORMAN E INTERNESTOR SUITE/LITE

Función 81 Consulta de la disponibilidad de NestorMan e InterNestor Suite
Entrada
Salida P(0) = 0 si NestorMan no está instalado
1 si NestorMan está instalado
3 si NestorMan e InterNestor Suite están instalados
P(1) = Segmento NestorMan del módulo de nivel 1 de InterNestor Suite
P(2) = Segmento NestorMan del módulo de nivel 2 de InterNestor Suite
P(3) = Segmento NestorMan del módulo de nivel 3 de InterNestor Suite
P(4) = Segmento NestorMan del módulo de nivel 4 de InterNestor Suite
P(5) = Número de segmento NestorMan del segmento 4 de NestorBASIC

El valor devuelto en P(5) sólo será válido si P(0) vale 1 o 3 a la salida. Este valor es necesario si se quiere hacer un traspaso de datos entre un segmento de NestorMan y un segmento de NestorBASIC usando como buffer intermedio el segmento 4 (que es común a ambos programas) como se explica en la sección 9.2.

Los valores devueltos en P(1) a P(4) sólo Serán válidos si P(0) vale 3 a la salida. No es necesario conocer la ubicación de los módulos de InterNestor Suite para ejecutar sus rutinas (mediante la función 85), pero sí para leer y escribir las constantes de configuración y las variables de los módulos, como se detalla en la sección 9.3.

 

Función 82 Ejecución de una función de NestorMan
Entrada P(0) = Función a ejecutar
P(2) a P(11) = Registros de entrada a la función:
P(2) = AF P(8) = AF’
P(3) = BC P(9) = BC’
P(4) = DE P(10)= DE’
P(5) = HL P(11)= HL’
P(6) = IX
P(7) = IY
Salida P(2) a P(12) = Registros de salida de la función, con la misma asignación que a la entrada, más los siguientes:
P(12) = A
P(13) = Bandera Cy (-1 si establecida, 0 si no)
P(14) = Bandera Z (-1 si establecida, 0 si no)

Esta función ejecuta la función de NestorMan especificada en P(0) mediante el método indirecto, es decir, por medio de una llamada al gancho de la BIOS extendida. Es equivalente por tanto a la ejecución de la función 58 previo establecimiento de P(1)=&HFFCA, P(3)=Función+256*B, y P(4)=&H2202.

Para esta rutina también sín válidas las consideraciones sobre los valores de salida P(12) a P(14) hechas en la explicación de la función 58.

Se devolverá un error -1 si NestorMan no está instalado. Sin embargo, no se comprueba si la función especificada existe realmente en NestorMan.

La sección 9 describe técnicas para el intercambio de datos entre NestorMan y NestorBASIC.

 

Función 83 Transferencia de un bloque de bytes de un segmento de NestorMan a un segmento de NestorBASIC
Entrada P(0) = Segmento NestorMan de origen
P(1) = Dirección inicial de origen
P(2) = Segmento NestorBASIC de destino
P(3) = Dirección inicial de destino
P(4) = Longitud del bloque
P(5)<> 0 -> Autoincremento de P(1)
P(6)<> 0 -> Autoincremento de P(3)
Salida P(1) = P(1) + P(4) si P(5)<>0
P(3) = P(3) + P(4) si P(6)<>0

Esta función es idéntica a la función 10, excepto que el valor pasado en P(0) hace referencia a un segmento de NestorMan. Como en la función 10, P(3)+P(4) debe ser menor de &H4000, se puede especificar un segmento VRAM o el segmento 255 en P(2), y se devuelve el error -1 si alguno de los segmentos especificados no existe.

Esta función tiene una única limitación: no es posible usarla especificando el segmento 1 como segmento NestorBASIC de destino. Normalmente esto no supondrá un problema, ya que el segmento 1 contiene el TurboBASIC y no se querrá modificar su contenido. Si a pesar de todo se necesita hacer una
transferencia hacia el segmento 1, primero se deberá hacer una copia a otro segmento de NestorBASIC como paso intermedio, por ejemplo el segmento 4.

 

Función 84 Transferencia de un bloque de bytes de un segmento de NestorBASIC a un segmento de NestorMan
Entrada P(0) = Segmento NestorBASIC de origen
P(1) = Dirección inicial de origen
P(2) = Segmento NestorMan de destino
P(3) = Dirección inicial de destino
P(4) = Longitud del bloque
P(5)<> 0 -> Autoincremento de P(1)
P(6)<> 0 -> Autoincremento de P(3)
Salida P(1) = P(1) + P(4) si P(5)<>0
P(3) = P(3) + P(4) si P(6)<>0

Esta función es idéntica a la función 10, excepto que el parámetro pasado en P(2) hace referencia a un segmento de NestorMan. Como en la función 10, P(3)+P(4) debe ser menor de &H4000, se puede especificar un segmento VRAM o el segmento 255 en P(0), y se devuelve el error -1 si alguno de los segmentos especificados no existe.

Esta función tiene una única limitación: no es posible usarla especificando el segmento 1 como segmento NestorBASIC de origen. Normalmente esto no supondrá un problema, ya que el segmento 1 contiene el TurboBASIC y no se querrá leer su contenido. Si a pesar de todo se necesita hacer una transferencia desde el segmento 1, primero se deberá hacer una copia a otro segmento de NestorBASIC como paso intermedio, por ejemplo el segmento 4.

 

Función 85 Ejecución de una rutina de InterNestor Suite
Entrada P(0) = Módulo de la rutina a ejecutar, 1 a 4
P(1) = Dirección de la rutina a ejecutar
P(2) a P(11) = Registros de entrada a la rutina:
P(2) = AF P(8) = AF’
P(3) = BC P(9) = BC’
P(4) = DE P(10)= DE’
P(5) = HL P(11)= HL’
P(6) = IX
P(7) = IY
Salida P(2) a P(12) = Registros de salida de la rutina, con la misma asignación que a la entrada, más los siguientes:
P(12) = A
P(13) = Bandera Cy (-1 si establecida, 0 si no)
P(14) = Bandera Z (-1 si establecida, 0 si no)

Mediante esta función es posible ejecutar una rutina de cualquiera de los módulos de InterNestor Suite. Para leer o escribir las constantes de configuración y las variables de los módulos es necesario obtener los números de segmento de NestorMan de los mismos mediante la función 81, y usar entonces alguna de las técnicas descritas en la sección 9.2 para el intercambio de datos entre NestorBASIC y NestorMan.

Para esta rutina también sín válidas las consideraciones sobre los valores de salida P(12) a P(14) hechas en la explicación de la función 58.

Esta función devolverá el error -1 si InterNestor Suite no está instalado, o si el número de módulo pasado en P(0) es inválido.

La sección 9.3 menciona algunas consideraciones sobre el uso conjunto de NestorBASIC e InterNestor Suite.

 

Función 86 Ejecución de una rutina de InterNestor Lite
Entrada P(1) = Dirección de la rutina a ejecutar
P(2) a P(11) = Registros de entrada a la rutina:
P(2) = AF P(8) = AF’
P(3) = BC P(9) = BC’
P(4) = DE P(10)= DE’
P(5) = HL P(11)= HL’
P(6) = IX
P(7) = IY
Salida P(2) a P(12) = Registros de salida de la rutina, con la misma asignación que a la entrada, más los siguientes:
P(12) = A
P(13) = Bandera Cy (-1 si establecida, 0 si no)
P(14) = Bandera Z (-1 si establecida, 0 si no)

Mediante esta función es posible ejecutar cualquier rutina de InterNestor Lite. P(1) debe contener la dirección de alguna de las rutinas de InterNestor Lite listadas en su manual del programador, de lo contrario el resultado de ejecutar esta función es impredecible.

Esta función devuelve el error -1 si InterNestor Lite no está instalado. Para saber por adelantado si InterNestor Lite está instalado, usa el siguiente código, que implementa el método de detección descrito en la sección 9.4:

P(0)=0: P(1)=&HFFCA: P(2)=0: P(4)=&H2203: E=USR(58):IF P(12)=0 THEN … (not installed)

Para esta rutina también sín válidas las consideraciones sobre los valores de salida P(12) a P(14) hechas en la explicación de la función 58.

En la sección 9.4 se comenta el uso de las rutinas de InterNestor Lite que realizan intercambios de datos con TPA desde NestorBASIC. Para esta rutina también sín válidas las consideraciones sobre los valores de salida P(12) a P(14) hechas en la explicación de la función 58.

El siguiente programa de ejemplo muestra la versión de InterNestor Lite que está instalada.

10 BLOAD"nbasic.bin",R
20 IF P(0)<5 AND P(0)<>3 THEN PRINT "Error "+P(0):END
30 '* Comprueba si INL está instalado
40 P(0)=0: P(1)=&HFFCA: P(2)=0: P(4)=&H2203: E=USR(58): IF P(12)=0 THEN PRINT "InterNestor Lite no está instalado.":GOTO 100
50 '* La rutina VERS_PAUSE (&H402A) devuelve la versión de INL en C.D.E y el número de implementación en B, se debe llamar con A=0
60 P(1)=&H402A:P(2)=0:E=USR(86)
70 X=P(3):GOSUB 1000:RB=X '* Registro B
80 X=P(4):GOSUB 1000:RD=X '* Registro D
90 PRINT "InterNestor Lite Versión " ; P(3) AND &HFF ; "." ; RD ; "." ; P(4) AND &HFF ; ", implementación " ; RB ; " está instalado."
100 '* Desinstala NestorBASIC y termina
110 P(0)=1:E=USR(0):END
1000 '* Esta subrutina extrae el byte alto de X
1010 X=((X AND &HFF00)/256) AND &HFF
1020 RETURN

El programa TCPCON-L.BAS, suministrado con NestorBASIC, es un ejemplo más complejo que ilustra el uso conjunto de NestorBASIC e InterNestor Lite.

 

APENDICE 1 – LISTADO DE FUNCIONES DE NESTORBASIC

En este apéndice se listan todas las funciones de NestorBASIC ordenadas por número. Las funciones que usan el segmento 4 tienen una marca «(S4)» tras su nombre. Dichas funciones son las siguientes: 0, 26-28, 30, 33-41, 55-57, 71, 78, y 79.

Funciones generales
Función 0 Desinstalación de NestorBASIC (S4)
Función 1 Obtención de información general sobre NestorBASIC y sobre un segmento lógico

 

Acceso a RAM
Función 2 Lectura de un byte de un segmento
Función 3 Lectura de un byte de un segmento con autoincremento de la dirección
Función 4 Lectura de un entero (2 bytes) de un segmento
Función 5 Lectura de un entero (2 bytes) de un segmento con autoincremento de la dirección
Función 6 Escritura de un byte en un segmento
Función 7 Escritura de un byte en un segmento con autoincremento de la dirección
Función 8 Escritura de un entero (2 bytes) en un segmento
Función 9 Escritura de un entero (2 bytes) en un segmento con autoincremento de la dirección
Función 10 Transferencia de un bloque de bytes de un segmento a otro
Función 11 Llenado de una zona de memoria con un byte
Función 12 Llenado de una zona de memoria con un byte con autoincremento de la dirección

 

 

Acceso a VRAM
Función 13 Lectura de un byte de la VRAM
Función 14 Lectura de un byte de la VRAM con autoincremento de la dirección
Función 15 Lectura de un entero (2 bytes) de la VRAM
Función 16 Lectura de un entero (2 bytes) de la VRAM con autoincremento de la dirección
Función 17 Escritura de un byte en la VRAM
Función 18 Escritura de un byte en la VRAM con autoincremento de la dirección
Función 19 Escritura de un entero (2 bytes) en la VRAM
Función 20 Escritura de un entero (2 bytes) en la VRAM con autoincremento de la dirección
Función 21 Transferencia de un bloque de bytes de VRAM a RAM
Función 22 Transferencia de un bloque de bytes de RAM a VRAM
Función 23 Transferencia de un bloque de bytes de VRAM a VRAM
Función 24 Llenado de una zona de la VRAM con un byte
Función 25 Llenado de una zona de la VRAM con un byte con autoincremento de la dirección

 

 

Acceso a disco
Función 26 Búsqueda de ficheros (S4)
Función 27 Renombrado de un fichero (S4)
Función 28 Borrado de un fichero (S4)
Función 29 Desplazamiento de un fichero (DOS 2)
Función 30 Creación de un fichero o directorio (S4)
Función 31 Apertura de un fichero
Función 32 Cierre de un fichero
Función 33 Lectura de un fichero (S4)
Función 34 Lectura de un fichero a VRAM (S4)
Función 35 Lectura de sectores de disco (S4)
Función 36 Lectura de sectores de disco a VRAM (S4)
Función 37 Escritura en un fichero (S4)
Función 38 Escritura en un fichero desde VRAM (S4)
Función 39 Escritura de sectores de disco (S4)
Función 40 Escritura de sectores de disco desde VRAM (S4)
Función 41 Relleno de un fichero con un dato (S4)
Función 42 Movimiento del puntero de un fichero
Función 43 Obtención de la unidad establecida por defecto y el vector de unidades disponibles
Función 44 Establecimiento de la unidad por defecto
Función 45 Obtención de información sobre el espacio de un disco
Función 46 Obtención del directorio actual (DOS 2)
Función 47 Establecimiento del directorio actual (DOS 2)
Función 48 Obtención del tamaño del RAM disk (DOS 2)
Función 49 Establecimiento del RAM disk (DOS 2)
Función 50 Obtención del byte de atributos de un fichero (DOS 2)
Función 51 Establecimiento del byte de atributos de un fichero
Función 52 Tratamiento de una cadena de ruta de acceso (DOS 2)

 

Compresión de gráficos
Función 53 Compresión de datos gráficos
Función 54 descompresión de datos gráficos

 

Ejecución de programas BASIC
Función 55 Ejecución de un programa BASIC almacenado en un segmento (S4)
Función 56 Activación de un programa BASIC almacenado en un segmento (S4)
Función 57 Grabación de un programa BASIC con cabecera en un fichero (S4)

 

Funciones varias
Función 58 Ejecución de una rutina de la BIOS, de la SUB-BIOS, de la memoria BASIC o de la zona de trabajo del sistema
Función 59 Ejecución de una rutina de usuario (rutina en código máquina contenida en un segmento)
Función 60 Impresión de una cadena en modo gráfico
Función 61 Almacenamiento de una cadena en un segmento
Función 62 Recuperación de una cadena almacenada en un segmento
Función 63 Inicialización del modo de parpadeo en SCREEN 0
Función 64 Construcción o borrado de un bloque de carácteres parpadeantes en SCREEN 0
Función 65 Obtención de información sobre las interrupciones
Función 66 Definición o suspensión de una interrupción de usuario

 

Efectos de sonido PSG
Función 67 Obtención de información sobre los efectos de sonido PSG
Función 68 Inicialización de un juego de efectos de sonido PSG
Función 69 Reproducción de un efecto de sonido PSG
Función 70 Interrupción del efecto de sonido PSG en curso

 

Reproducción de música Moonblaster
Función 71 Carga e inicialización, o desinstalación, del reproductor Moonblaster (S4)
Función 72 Obtención de información sobre la música en reproducción
Función 73 Activación y desactivación de los chips musicales
Función 74 Inicio de la reproducción de una música Moonblaster 1.4
Función 75 Detención de la reproducción de una música
Función 76 Pausa y continuación de una música
Función 77 Desvanecimiento de una música
Función 78 Carga de un samplekit de Music Module (S4)
Función 79 Carga de un wavekit de MoonSound (S4)

 

Control del uso de segmentos
Función 80 Consulta y establecimiento del número de segmentos reservados para NestorBASIC

 

Interacción con NestorMan e InterNestor Suite/Lite
Función 81 Consulta de la disponibilidad de NestorMan e InterNestor Suite
Función 82 Ejecución de una función de NestorMan
Función 83 Transferencia de un bloque de bytes de un segmento de NestorMan a un segmento de NestorBASIC
Función 84 Transferencia de un bloque de bytes de un segmento de NestorBASIC a un segmento de NestorMan
Función 85 Ejecución de una rutina de InterNestor Suite
Función 86 Ejecución de una rutina de InterNestor Lite

APENDICE 2 – RUTINAS Y VARIABLES DE NESTORBASIC ACCESIBLES AL USUARIO

Cuando se ejecuta una rutina de usuario o una interrupción de usuario, el segmento de NestorBASIC queda conectado en le página 1. Al principio del mismo hay una tabla que contiene saltos a algunas de las rutinas internas de NestorBASIC, así como algunas variables internas del mismo, que pueden resultar útiles para las rutinas de usuario. En esta sección se detalla la ubicación y el funcionamiento de dichas rutinas y variables.

Todas estas rutinas mantienen el estado de las interrupciones, excepto PUTSLOT 0 que vuelve con las interrupciones inhibidas.

ATENCIÓN: El segmento lógico 255 se refiere siempre a la memoria conectada en las páginas 2 y 3 en el momento en que se hace referncia a dicho segmento. Mientras se está ejecutando una rutina o una interrupción de usuario la página 2 NO contiene el segmento del BASIC, sino el de la rutina o la interrupción. Para convertir realmente el segmento 255 a una dirección+segmento del BASIC hay que hacer lo siguiente:

ld hl,dirección
call CHKSLFF
cp 3
jr z,OKFF
ld a,2
OKFF: ;

Nota: Las variables y zonas de datos mencionadas en esta sección son de sólo lectura. Modificarlas puede dar lugar a resultados impredecibles.

El contenido de la tabla es el siguiente:

&H4100: Cadena identificadora «NestorBASIC x.xx»

&H4110: TABSEGS

Puntero a la tabla de segmentos lógicos de NestorBASIC. El formato de dicha tabla es el siguiente:

-2: Máximo número de segmentos reservables para NestorBASIC (siempre válido bajo DOS 1; bajo DOS 2 este valor es válido inmediatamente después de la instalación de NestorBASIC, pero puede variar después)
-1: Número de segmentos disponibles (como P(0) devuelto por las funciones 1 y 80)
+0: Slot del segmento lógico 0
+1: Segmento fisico del segmento lógico 0
+2: Slot del segmento lógico 1
+3: Segmento fisico del segmento lógico 1

+492: Slot del segmento lógico 246
+493: Segmento fisico del segmento lógico 246

&H4112: INT_DATA

Contiene información sobre las interrupciones de NestorBASIC:

bit 0 = 1: Interrupción de usuario en marcha
bit 1 = 1: Efecto de sonido en marcha
bit 2 = 1: música Moonblaster 1.4 en reproducción
bit 3 = 1: música Moonblaster Wave en reproducción

&H4113: PUTSLOT0

Conecta un slot en la pagina 0 sin usar ENASLT. Vuelve con las interrupciones inhibidas.

Entrada: A = Slot a conectar
Salida: –
Registros: AF

&H4116: CHKSLE

Comprueba si un segmento lógico existe. NO reconoce como validos los segmentos correspondientes a VRAM ni el 255.

Entrada: A = Segmento lógico
Salida: Cy= 1 -> El segmento lógico existe
Cy= 0 -> El segmento lógico no existe
Registros: F

&H4119: CHKSLFF

Comprueba si un segmento lógico es el 255, en ese caso lo convierte al segmento adecuado (segmento de la pagina 2 si HL<&HC000, segmento 3 si HL>=&HC000)

Entrada: A = Segmento lógico
HL = Dirección
Salida: A = Segmento convertido si era el 255, si no, inalterado
Registros: F

&H411C: CHKSLV

Comprueba si un segmento lógico corresponde a VRAM, en ese caso lo convierte a la dirección VRAM adecuada.

Entrada: A = Segmento lógico
HL = Dirección
Salida: Si es VRAM:
A = Bloque VRAM
HL = dirección VRAM
Cy = 1
Si no es VRAM:
A, HL inalterados
Cy = 0
Registros: –

&H411F: VTOSL

Convierte una dirección VRAM en su segmento lógico equivalente.

Entrada: A = Bloque VRAM
HL = Dirección VRAM
Salida: A = Segmento lógico equivalente
HL = Dirección RAM equivalente
Cy = 1 -> A=1 pero solo hay 64K VRAM
Registros: F

&H4122: GET_SF

Obtiene el segmento físico y el slot correspondientes a un segmento lógico.

Entrada: A = Segmento lógico
Salida: A = Segmento físico
B = Slot (255 -> Segmento lógico inexistente)
Registros: –

&H4125: GET_SLT

Obtiene el slot conectado a la pagina 1 o 2.

Entrada: A = Pagina (1 o 2)
Salida: B = Slot
Registros: F, C

&H4128: READ_SL

Lee un byte de un segmento lógico.

Entrada: A = Segmento lógico
HL = Dirección (0-&H3FFF)
Salida: A = Dato
Registros: F, AF’

&H412B: WRITE_SL

Escribe un dato en un segmento lógico.
Entrada: A = Segmento lógico
E = Dato
HL = Dirección (0-&H3FFF)
Salida: –
Registros: F, AF’

&H412E: LDIRSS

Realiza una transferencia de un segmento lógico a otro. Reconoce el segmento lógico 255 y los segmentos VRAM. Vuelve con la BIOS conectada en la pagina 0. NO comprueba si BC > &H4000.

Entrada: IXh = Segmento lógico fuente
IXl = Segmento lógico destino
HL = Dirección origen (0..&HFFF)
DE = Dirección destino (0..&HFFF)
BC = Longitud (0..&H3FFF)
Salida: A = 0 -> Transferencia realizada
A <> 0 -> Uno de los segmentos lógicos no existe
Registros: Todos

&H4131: CHKBV

Comprueba si una dirección VRAM existe.

Entrada: A = Bloque VRAM (0 o 1, 64K inferiores o superiores)
Salida: Cy = 1 -> No existe esa dirección
(A = 1 pero el ordenador sólo tiene 64K VRAM)
Registros: –

&H4134: SET_RD

Prepara el VDP para lectura de VRAM.

Entrada: HL = Dirección VRAM, 16 bits bajos
CY = Dirección VRAM, bit 17
Salida: –
Registros: AF, HL

&H4137: SET_WR

Prepara el VDP para escritura en VRAM.

Entrada: HL = Dirección VRAM, 16 bits bajos
CY = Dirección VRAM, bit 17
Salida: –
Registros: AF, HL

&H413A: LDIRVR

Copia de un bloque de bytes de VRAM a RAM.

Entrada: Dirección VRAM establecida con SET_RD
DE = Destino RAM
BC = Longitud
Salida: DE = dirección siguiente al final del bloque
Registros: AF

&H413D: LDIRRV

Copia de un bloque de datos de RAM a VRAM.

Entrada: Dirección VRAM establecida con SET_WR
HL = Origen RAM
BC = Longitud
Salida: HL = dirección siguiente al final del bloque
Registros: AF

&H4140: LDIRVV

Copia de un bloque de datos de VRAM a VRAM a traves de un buffer en RAM.

Entrada: HL = Origen, 16 bits bajos
DE = Destino, 16 bits bajos
BC = Longitud
A = %000000 D O, bit 17 de Origen y Destino
IX = Buffer RAM de BC bytes
Salida: –
Registros: AF, HL, DE

&H4143: FILLVR

Llena una zona de VRAM con un byte.

Entrada: Dirección inicial establecida con SET_WR
BC = Longitud
A = Dato
Salida: –
Registros: –

&H4146: BLK_CLS

Borra la zona de VRAM destinada al modo de parpadeo (modo «blink» de SCREEN 0).

Entrada: –
Salida: –
Registros: AF

&H4149: BLK_COL

Establecimiento del color del modo de parpadeo.

Entrada: A = Color texto + 16* color fondo
Salida: –
Registros: A

&H414C: BLK_TIM

Establecimiento de los tiempos del modo de parpadeo.

Entrada: A = Tiempo ON + 16* tiempo OFF
Salida: –
Registros: A

&H414F: BLK_ON

Construcción de un bloque parpadeante.

Entrada: HL = XXYY
B = Longitud X
C = Longitud Y
Salida: L = YY siguiente a la última línea
H = XX original

Registros: AF

&H4152: BLK_OF

Borrado de un bloque parpadeante.

Entrada: HL = XXYY
B = Longitud X
C = Longitud Y
Salida: L = YY siguiente a la última línea
H = XX original
Registros: AF

&H4155: C_BLKAD

Cálculo de la dirección VRAM correspondiente a una coordenada concreta para el modo de parpadeo.

Entrada: HL = XXYY
Salida: HL = Dirección VRAM
Registros: AF

&H4158: C_STBT

Cálculo del bit correspondiente a una coordenada concreta del modo de parpadeo.

Entrada: A = Coordenada X
Salida: A = Bit puesto a 1
Registros: F

&H415B: GINFOUS

Devuelve información sobre la interrupción de usuario.

Entrada: –
Salida: A = Segmento
HL = Dirección

&H415E: GINFOSFX

Devuelve información sobre los efectos de sonido PSG

Entrada: A = Nuevo volumen máximo (-1 para no cambiarlo)
Salida: A = Segmento del juego de efectos
HL = Dirección del juego de efectos
B = Número del efecto que suena, o del último que ha sonado
C = Prioridad del efecto que suena, o del último que ha sonado
D = Número de efecto más alto existente
E = Volumen máximo

&H4161: GINFOMUS

Devuelve información sobre la música que está sonando y la presencia del reproductor Moonblaster.

Entrada: –
Salida: Cy = 1 -> No hay ningún reproductor cargado,
el resto de resultados no son válidos.
Cy = 0 -> Hay un reproductor cargado.
El resto de resultados son válidos
si hay una música sonando (consultar INT_DATA).
A = Segmento lógico de la música que suena
HL = Dirección inicial de la música que suena
B = Chips presentes:
bit 0 = 1 -> MSX-MUSIC presente
bit 1 = 1 -> MSX-AUDIO presente
bit 2 = 2 -> OPL4 presente
C = Chips activos:
bit 0 = 1 -> MSX-MUSIC activo
bit 1 = 1 -> MSX-AUDIO activo
bit 2 = 2 -> OPL4 activo
D = Posición
E = Paso actual en la posición (0 a 15)
IXl= 255 si la música está pausada

&H4164: REPTYPE

Byte de información que contiene el tipo de reproductor musical cargado:

0: Reproductor MoonBlaster 1.4
1: Reproductor MoonBlaster Wave

Atención: antes de consultar esta información hay que comprobar que efectivamente hay algún reproductor cargado. Esto se puede hacer con la función GINFOMUS (&H4161).

&H4165: GETF01

Entrada: –
Salida: –

Esta rutina copia los contenidos de las cadenas F$(0) y F$(1) a dos buffers de NestorBASIC situados en la página 3; las direcciones de dichos buffers están indicadas en las variables F0BUFADD y F1BUFADD, mencionadas más adelante.

sólo se copian los 80 primeros carácteres de las cadenas. Al final de las mismas se inserta un carácter 0.

&H4168: SETF0
&H416B: SETF1

Entrada: –
Salida: –

Estas rutinas establecen las cadenas F$(0) y F$(1), respectivamente, con el contenido de dos buffers internos de NestorBASIC situados en la página 3; las direcciones de dichos buffers están indicadas en las variables F0BUFADD y F1BUFADD, mencionadas más adelante.

Las cadenas deben estar finalizadas con un carácter 0 en los buffers, y su longitud máxima es de 80 carácteres; si son más largas, sólo se establecerán los primeros 80 carácteres.

&H416E: F0BUFADD
&H4170: F1BUFADD

Estas variables almacenan las direcciones de los buffers en página 3 que son usados como destino por la rutina GETF01 y como origen por las rutinas SETF0 y SETF1, respectivamente. Estos buferes tienen un tamaño de 80 bytes cada
uno.

&H4172: SL_2

Número de segmento lógico conectado en la página 2 (es decir, número de segmento lógico en el que reside la rutina que lee esta variable).

&H4173: NMAN_SL4

Número de segmento NestorMan del segmento 4 de NestorBASIC.

&H4174: INS_SL1
&H4175: INS_SL2
&H4176: INS_SL3
&H4177: INS_SL4

Números de segmento NestorMan de los módulos 1 a 4, respectivamente, de InterNestor Suite.

APENDICE 3 – INTERRUPCIONES BAJO MSX TURBO-R

NestorBASIC funciona perfectamente en cualquier MSX 2/2+/Turbo-R, pero puede dar problemas con las interrupciones si se ejecuta en un Turbo-R en modo DOS 1, sobre todo si se usa una amplicación de memoria externa. Esto es debido a que antes de ejecutar una interrupción, NestorBASIC ha de averiguar qué segmento hay conectado en la página 1, y en modo DOS 1 esto sólo se puede hacer con la instrucción IN A,(&HFD), que en los Turbo-R no funciona exactamente igual que en los MSX2/2+.

Por tanto, si se van a usar interrupciones de usuario o efectos de sonido en un programa que use NestorBASIC, lo mejor es detectar si el ordenador es un Turbo-R (si PEEK(&H2D)=3) y se trabaja en modo DOS 1 (se puede averiguar con la función 1), y en ese caso avisar de que se ha de arrancar en modo DOS 2.

APENDICE 4 – CONDICIONES DE USO

NestorBASIC es software gratuito, o como dicen los expertos, freeware. Sin embargo hay un par de condiciones para usarlo en tus progamas:

– En algún lugar del programa (al cargar, en una opción «acerca de», en el «staff», etc) ha de aparecer una mención al uso de NestorBASIC, así como la versión del mismo (para averiguar la versión de NestorBASIC que usas, utiliza la función 1).

– Si el programa no es para uso personal del autor (es decir, si va a ser distribuido, de forma gratuita o no) has de cederme una copia del mismo.

Para cualquier sugerencia, consulta o comentario acerca de NestorBASIC, me encontrarás en <konamiman@konamiman.com>.

El uso de los efectos de sonido creados con el editor SEE tiene sus propias condiciones de uso. Si vas a vender tu programa por más de 15 NLG has de pagar una pequeña cantidad a los autores, como máximo 25 NLG. Para más detalles o para comentarios acerca de SEE contacta con Fuzzy Logic:

R. v/d Meulen A. v/d Wal
Lijsterstraat 25 Tormentil 15
8917 CX Leeuwarden 8445 RR Heerenveen
Holland. Holland.

[/vc_column_text][/vc_column][/vc_row]