BBC Basic en el Spectrum (parte I) Quería reunir todas mis notas acerca de cómo convertir un listado Basic del BBC al Spectrum, pero he decidido dividirlo en dos partes y empezar primero con mi traducción al español del texto original en ingles del Z80 BBC Basic, publicado en la internet por J.G. Harston en sus páginas web: "http://mdfs.net/Software/Spectrum/BBCBasic/" Basic BBC (Z80) Basic BBC (Z80) para el Sinclair Spectrum (C) R.T.Russell 1982-1999 Conversión al Spectrum (C) J.G.Harston 1992-2005 1. Introducción El Basic BBC (Z80) ha sido diseñado para ser lo más compatible possible con la Versión 4 del Basic BBC 6502 residente en los Acorn BBC de su serie Master. La sintaxis no siempre es identica a la versión 6502, pero en muchos casos la versión Z80 es más tolerante. El Basic BBC para el Spectrum está basado en la implementación para el coprocesador Z80 de Acorn mediante los E/S del BBC. El Basic BBC puede instalarse en una ROM seleccionada por el puerto &7FFD o un DOCK o EX. También se puede cargar en la RAM misma, lo cual nos deja con unos 17K menos de espacio libre para los datos y programas. Cuando el BASIC inicia, aparecerá en pantalla: Acorn BBC BASIC Version 2.20 (C) Copyright R.T.Russell 1983 > Si el sistema permite procesos seperados, entoces tipear "*Quit" nos regreará al punto del que fue llamado. "*Help" reporta la versión actual de la interface. 2. Uso de la Memoria El Basic BBC corre en la memoria baja ROM/RAM de &0000-&3FFF o en la memoria alta en &BB00-&EFFF. Cerca de 1K de memoria es reservada tras el "screen" del Spectrum para los datos y variables del sistema del Spectrum, resultando en un valor de PAGE de &6000. La memoria de usuaio restante queda disponible para programas Basic, variables (heap) y stack. Dependiendo de la configuration del sistema, HIMEM puede tener un valor de hasta &F000. Si un Timex MMU está presente y la RAM disponible está en &4000-&7FFF, entonces el "screen" es removido, y como resultado PAGE empieza en &4000. PAGE puede subir o HIMEM bajar mediante otras partes del sistema de reserva de memoria del host. 3. Comandos, sentencias y funciones La sintaxis de los comandos, sentencias y funciones Basic son las mismas que las del Basic 6502 para el BBC (BASIC 4). Algunos comandos y funciones son implementadas llamando a puntos de entrada del sistema operativo en &FF00-&FFFF y así que su functionalidad depende del nivel de soporte implementado por la interfaz del host. Las diferencias con la interfaz actual del host (version 0.4x) se han listado aquí. 4. El teclado El Spectrum usa la sigte. configuración de teclado cuando corre el Basic BBC. +-----++-----++-----++-----++-----++-----++-----++-----++-----++-----+ |COPY ||CAPS || || ||LEFT ||DOWN || UP ||RIGHT|| TAB || DEL | | ! || @ || # || $ || % || & || ' || ( || ) || _ | | 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9 || 0 | +-----++-----++-----++-----++-----++-----++-----++-----++-----++-----+ +-----++-----++-----++-----++-----++-----++-----++-----++-----++-----+ | Q || W || E || R || T || Y || U || I || O || P | | || || || < || > || [ || ] || || ; || " | | q || w || e || r || t || y || u || i || o || p | +-----++-----++-----++-----++-----++-----++-----++-----++-----++-----+ +-----++-----++-----++-----++-----++-----++-----++-----++-----++-----+ | A || S || D || F || G || H || J || K || L || | | ~ || | || \ || { || } || ^ || - || + || = || | | a || s || d || f || g || h || j || k || l ||ENTER| +-----++-----++-----++-----++-----++-----++-----++-----++-----++-----+ +--------++-----++-----++-----++-----++-----++-----++-----++-----++-------+ | SHIFT || Z || X || C || V || B || N || M || ||ESCAPE | | || : || ` || ? || / || * || , || . || SYM || | | SHIFT || z || x || c || v || b || n || m || SYM || SPACE | +--------++-----++-----++-----++-----++-----++-----++-----++-----++-------+ 5. Caracteres especiales ! in-dirección de 32-bits $ variable de cadena o in-dirección de cadena % variable entera & Precede a una constante hexadecimal ' Nueva línea en PRINT o INPUT * Precede a una sentencia del "sistema operativo" : Separate sentenciass tipeadas en una misma línea ; Introduce comentarios en ensamblador, suprime la acción en PRINT ? in-dirección de 8-bits (PEEK & POKE) [ Entra en el ensamblador ] Sale del ensamblador ~ Convierte a hex (PRINT y STR$) 6. Variables Los nombres de Variable pueden ser de largo ilimitado y todos los caracteres son significativos. Y deben empezar con una letra. Solamente pueden contener los caracteres A..Z, a..z, 0..9 y la subraya. Las palabras reservadas incrustadas son permitidas. Las mayúsculas y las minúsculas en los nombres de variable también son diferenciadas. Los sigtes tipos de variable son permitidos: A real A% entero A$ cadena Las variables A%..Z% son consideradas especiale ya que no son borradas por RUN, CHAIN y CLEAR. Además A%, B%, C%, D%, E%, F%, H%, L%, X% e Y% son especialmente usadas en rutinas CALL y USR, mientras O% y P% tienen un significado especial en ensamblador (código origen y contador de programa respectivamente). La variable especial @% controla el formateado de impresión de números. Las variables @%..Z% son llamadas "variables estáticas", todas las demás son "variables dinámicas". Las variables reales tienen un rango de aproximadamente +-1E-38 a +-1E38 y las funciones numéricas evaluan hasta una figura segura de 9. Internamente cada numero real es almacenado en 40 bits. Las variables enteras son almacenadas en 32 bits y tienen un rango desde -2,147,483,648 a 2,147,483,647. Las variables de cadena pueden contener de 0 a 255 caracteres. Todas las matrices deben ser dimensionadas antes de usarse. 7. Comandos directos Los comandos directos no pueden ser usados dentro de listados Basic, de intentarlo, el sistema dará el mensaje de error 'Mistake'. Comando Sintaxis Acción AUTO AUTO [inicio][,incr] Genera números de línea automáticamente. DELETE DELETE inic,fin Borra líneas de programa. LIST LIST [lin1][,lin2] Lista todo o parte del programa. LISTO LISTO num Controla la indentación en LIST. LOAD LOAD "nombre" Carga un programa en memoria. NEW Elimina totalmente el programa y variables. OLD Recupera un programa eliminado por NEW. RENUMBER RENUMBER [inic][,incr] Renumera las líneas de un programa. SAVE SAVE ["nombre"] Salva el programa a un disco. Si la primera línea del programa es 'REM > nombre', entonces SAVE sólo usará el nombre dado en la sentencia REM. 8. Sentencias Las sigtes. sentencias pueden ser usadas en programas o como órdenes directas desde el teclado. Sentencia Sintaxis Acción CALL CALL dir[,parámetros] llama a una rutina en ensamblador. CHAIN CHAIN nombre carga y ejecuta un programa. CLEAR borra las variables dinámicas. CLS borra la pantalla. DEF DEF FNnom[(paráms)] Define una funcción de usuario. DEF PROCnom[(paráms)] Define un procedimiento. DIM DIM var(sub1[,sub2...])[,..] Dimensiona una o más matrices. DIM exp1 [,exp2...] Reserva espacio para el ensamblador, etc. END Termina el programa y cierra los ficheros. ENDPROC Retorna de un procedimiento. FOR FOR var=x TO y [STEP z] empieza un bucle FOR...NEXT. GOSUB GOSUB exp llama a una subrutina BASIC. GOTO GOTO exp salta a una línea especifica. IF IF exp THEN sent [ELSE sent] ejecuta sent(s) si exp = no-cero. IF exp THEN line [ELSE line] salta si exp= no-cero. LET [LET] var = exp Asigna valor de exp a variable var. LOCAL LOCAL var1[,var2...] Declara variables locales para una funcción o procedimiento. NEXT NEXT [var1[,var2...]] cierra el bucle FOR...NEXT. ON ON exp GOTO lin1,lin2...[ELSE linz] GOTO computado. ON exp GOSUB lin1,lin2..[ELSE linz] GOSUB computado. ON ERROR ON ERROR sents Ejecuta sent(s) si se da un error. ON ERROR OFF desactiva la captura de errores. PROC PROCnom[(parametros)] llama a un procedimiento. REM REM cualquier texto comentarios REPEAT inicia bucle REPEAT...UNTIL. REPORT imprime mensaje del último error dado. RESTORE RESTORE [lin] pone el puntero de datos al comienzo o a una línea DATA. RETURN Retorna de una subrutina. RUN ejecuta el programa en curso. STOP detiene el programa y genera un mensaje. TRACE TRACE ON inicia el modo de rastreo del programa. TRACE OFF desactiva el rastreo. TRACE exp rastrea las lineas menores que la exp dada. UNTIL UNTIL exp Termina el bucle si exp es no-cero. WIDTH WIDTH exp fija el ancho de PRINT en pantalla. 9. Instrucciones E/S Sentencia Sintaxis Acción BPUT BPUT #can,exp Escribe byte men.sign. de exp en el diskete. CLOSE CLOSE #can Cierra fichero abiert. Si chan=0 cierra todoa lis ficheros. DATA DATA list Lista de datos a leer por READ. EXT# EXT#can=exp Fija la extentensión de un fichero abierto. INPUT INPUT ["prompt"[,]]var[,var] espera datos del usuario. Una coma tras el "prompt" y aparece un signo "?". INPUT LINE ["prompt.... igual a INPUT pero acepta todo lo tipeado incluidas las comas, puntos, etc. INPUT# INPUT #can,var[,var...] lee los datos de un fichero abierto. OSCLI OSCLI string Pasa el string al "sistema operativo". PRINT PRINT [TAB(x[,y])][SPC(n)]['][;][~][exp[,exp...][;] imprime los datos a un canal de salida. PRINT# PRINT #can,exp[,exp...] escrive los datos a un fichero abierto. PTR# PTR#can=exp fija el puntero en curso de un fichero abierto. PUT PUT port,exp manda el byte men.sign. de exp a port. READ READ var[,var...] lee la información de sentencia(s) DATA. VDU VDU exp[,exp...] envía byte men.sign. de exp a un canal de salida. VDU exp;[exp;...] envía 16 bits men.sign. de exp a un canal de salida como dos caracteres (byte m.s. primero). 10. Imprimiendo Por defecto, las cadenas son impresas justificadas a la izquierda y los números son justificados a la derecha en el área de impresión. Las cantidades numéricas se imprimen justificadas a la izq. si son precedidas por pto. y coma (;). La coma (,) tabula al inicio de la sigte. área de impresión, a menos que el cursor esté ya al comienzo. Un apóstrofe (') en PRINT o INPUT fuerzan una línea nueva. Un pto. y coma al final del PRINT evita el salto de línea. TAB(x), TAB(x,y) y SPC(n) pueden ser usados con PRINT e INPUT para posicionar el cursor. Una tilde (~) hace que los números aparezcan en hexadecimal. La variable @% controla el formato numérico del modo sigte.: Byte men.sign.: ancho del área de impresión, 0-255. Normalmente 10. Byte 2 : Número de posiciones decimales. Máximo 10. Byte 3 : tipo de formato: 0 - formato general (por defecto) 1 - formato exponencial 2 - formato fijado. Byte MS: STR$ flag. si es cero, entonces STR$ formatea en modo G9. Si no es cero entonces STR$ formatea de acuerdo a los bytes 2 y 3 de @%. Ejemplo Resultado @%=&2010A 01234567890123456789 PRINT "HELLO",8 HELLO 8.0 PRINT "HELLO" 8 HELLO 8.0 PRINT "HELLO";8 HELLO8.0 PRINT "HELLO",;8 HELLO 8.0 Valor G9 G2 E2 F2 @%=&90A @%=&20A @%=&1020A @%=&2020A .001 1E-3 1E-3 1.0E-3 0.00 .006 6E-3 6E-3 6.0E-3 0.01 .01 1E-2 1E-2 1.0E-2 0.01 .1 0.1 0.1 1.0E-1 0.10 1 1 1 1.0E0 1.00 10 10 10 1.0E1 10.00 100 100 1E2 1.0E2 100.00 1000 1000 1E3 1.0E3 1000.00 11. Operadores Simbolo Función + Adición o concatenación. - Negación o sustracción. * Multiplicación. / División. ^ Involución (eleva a potencia). NOT Complemento de uno (entero). EOR OR exclusivo de bit (entero). OR Bit OR (entero). AND Bit AND (entero). MOD Modulo (resultado entero). DIV División de enteros (resultado entero). = Igual. <> No igual. < Menor que. > Mayor que. <= Menor igual que. >= Mayor igual que. Los precedentes de operadores son: 1. Expresiones en paréntesis, funciones, negación, NOT. 2. ^ 3. *, /, MOD, DIV 4. +, - 5. =, <, >, <>, <=, >= 6. AND 7. OR, EOR 12. Funciones Aritméticas Función Acción ABS(exp) Valor absoluto de exp. ACS(exp) Arco-coseno de exp, en radianes. ASN(exp) Arco-seno de exp, en radianes. ATN(exp) Arco-tangente de exp, en radianes. COS(exp) Coseno de exp en radianes. DEG(exp) Valor en grados de exp en radianes. EXP(exp) e elevado a la potencia de exp. INT(exp) El entero de exp. LN(exp) Logaritmo Natural de exp. LOG(exp) Logaritmo de exp en base 10. RAD(exp) Valor en radianes de exp en grados. RND[(exp)] RND genera un entero aleatorio de 32-bits. RND(-n) semilla de la sequencia. RND(0) repite el último valor en la forma RND(1). RND(1) genera un número entre 0 y 0.999999999 RND(n) gener un entero aleatorio entre 1 y n. SGN(exp) da: 1 si exp > 0, 0 si exp = 0, -1 si exp < 0. SIN(exp) Seno de exp en radianes. SQR(exp) Raíz cuadrada de exp. TAN(exp) Tangente de exp en radianes. 13. Funciones de cadena Función Acción ASC(str) da el código ASCII del primer caracter de la cadena str. da -1 si la cadena es nula. CHR$(exp) da el caracter correspondiente al valor ASCII de exp. EVAL(str) Evalua str como una expresión y da la cadena o número resultante. GET espera que se pulse una tecla y devuelve su valor ASCII. GET$ igual pero devolviendo el caracter de la tecla pulsada. INKEY(n) espera n centisegundos para pulsar una tecla y devuelve su valor ASCII, si no se pulsa nada, entonces da -1. INKEY$(n) idem, pero devuelve el caracter de la tecla pulsada, de lo contrario da una cadena nula. INSTR(r,s[,n]) devuelve la posición de s en la cadena r, opcionalmente puede empezar por la posición n. LEFT$(str,n) devuelve n caracteres a la izq. de str. LEN(str) da el largo de la cadena str (0-255). MID$(str,m[,n]) devuelve una sub-cadena desde m, con largo n, o hasta el final de str. RIGHT$(str,n) devuelve n caracteres a la der. de str. STR$[~](exp) convierte exp en decimal (o hex.) a una cadena. STRING$(n,str) genera una cadena consistente de n copias de str. VAL(str) extrae el valor numérico de str. Si str no empieza con un número con o sin signo, VAL retorna cero. 14. Funciones especiales de E/S Funcción Acción BGET#can devuelve un byte de un fichero abierto. COUNT Número de caracteres impresos desde la última nueva línea. END Retorna fin de la pila de variables del BASIC. EOF#can da TRUE si el fichero abierto llegó a su final. ERL número de línea del último error. ERR Código del último error. EXT#can da la longitud del fichero abierto. FALSE da cero. FNname[(parametros)] función numérica o de cadena definida por el usuario. GET(port) devuelve el contenido del puerto Z80. MODE da el modo de pantalla en curso. OPENIN(str) abre un fichero para lectura y devuelve el número del canal. OPENOUT(str) como el anterior, pero abriendo el fichero para escritura. OPENUP(str) similar, pero abriendolo para su actualización. PI da el valor 3.14159265. POS da la columna en curso del cursor (LHS=0). PTR#can lee el puntero en curso de un fichero abierto. TOP da la primera dirección tras terminar el programa. TRUE da -1. USR(direc) llama a una rutina en código máquina y devuelve un entero. VPOS da la línea en curso del cursor (linea de arriba=0). 15. Pseudo-variables Las pseudo-variables le permiten al usuar leer y modificar las variables del sistema. Pueden ser usadas también con sentencias de asignasión, por ejemplo: TIME=TIME+50 (nota: la palabra LET no está permitida). Nombre Función PAGE dirección de memoria del programa en curso. HIMEM "top" de la memoria usada por el BASIC. LOMEM inicio de la dirección del almacenaje de variables dinámicas. TIME tiempo elapsado del reloj, cuenta en centisegundos. TIME$ hora y fecha del reloj en tiempo real con el formato: "Día dd Mes aaaa. hh:mm:ss". 16. Códigos de Error Modo inmediato solamente (código de error 0): Silly RENUMBER espacio LINE espacio Desastrosos y no atrapables: Bad program No room Sorry Capturables: 1 Out of range (fuera de rango) 4 Mistake (error) 5 Missing , (falta , ) 6 Type mismatch (tipo equivocado) 7 No FN (falta FN) 9 Missing " (faltan las ") 10 Bad DIM (dimensionado erroneo) 11 DIM space (espacio para el dimensionado) 12 Not LOCAL (falta LOCAL) 13 No PROC (falta el procedimiento) 14 Array (matriz) 15 Subscript (subindice) 16 Syntax error (error sintáctic) 17 Escape 18 Division by zero (división por 0) 19 String too long (cadena demasiado larga) 20 Too big (demasiado grande) 21 -ve root (-ve raiz) 22 Log range (rango del logaritmo) 23 Accuracy lost (falló la exactitud) 24 Exp range (rango de expresión) 26 No such variable (no existe la variable) 27 Missing ) (falta ")") 28 Bad HEX (hexadecimal erroneo) 29 No such FN/PROC (no existe ...) 30 Bad call (llamada erronea) 31 Arguments 32 No FOR (falta el FOR) 33 Can't match FOR (no empareja) 34 FOR variable (la variable del bucle FOR) 36 No TO (falta TO) 38 No GOSUB (falta la subrutina) 39 ON syntax (la sintaxis de ON) 40 ON range (el rango de ON) 41 No such line (no existe línea) 42 Out of DATA (fuera de datos) 43 No REPEAT (falta el REPEAT) 45 Missing # (falta el #) 190 Directory full (dir. lleno) 192 Too many open files (hay muchos abiertos) 196 File exists (ya existe) 198 Disk full (el disco está lleno) 200 Close error (error al cerrar) 204 Bad name (nombre erroneo) 214 File not found (no se encuentra) 222 Channel (canal) 253 Bad string (cadena erroena) 254 Bad command (comando directo erroneo) 17. Operadores de "Indirección" La indirección es el proceso que nos ofrecen PEEK y POKE en otros dialectos de BASIC. Tenemos 3 poeradores de indirección: Nombre Propósito Nro. de bytes afectados ? indirección de bytes 1 ! indirección de "words" 4 $ indirección de cadenas 1 to 256 Y=PEEK(X) es equivalente a Y=?X POKE X,Y es equivalente a ?X=Y ! actua sobre 4 bytes sucessivo. Por ejemplo, !M=&12345678 debería cargar &78 en la dirección M, &56 en M+1, &34 en M+2 e &12 en M+3. $ escribe una cadena, seguida por retorno de carro, en un área especifica de la memoria, por ejemplo: $M="ABCDEF" colocará los caracteres ASCII A - F en las posiciones M a M+5 y cargará &0D en M+6. Interrogación (?) y admiración (!) pueden ser usados tambien como operadores binarios, por ejemplo: M?3, significa "el contenido de la memori M +3". El operando a la izq. debe ser una variable, nunca una constante. El poder de los operadores de indirección reside en la forma como ellos pueden ser usados para crear tu propia estructura de datos. Por ejemplo, puede necesitarser una estructura consistente de una cadena de 10 caracteres, un número de 8-bits y una referencia a una estructura similar. Si M es la dirección inicial de la estructura, entonces: $M es una cadena M?11 es un número de 8-bits M!12 es la dirección de la estructura relacionada. De este modo se pueden crear y manipular listas enlazadas y estructuras de árbol en la memoria, muy facilmente. 18. Acceso al código máquina La función USR y la sentencia CALL, proveen de una interfaza flexible entre el BASIC y el código máquina. Tanto USR como CALL inicializan los registros del Z80 previos a la llamada a la subrutina en código máquina como sigue: Registro A = byte men.signif. de A% " F = byte men.signif. de F% " B = byte men.signif. de B% " C = byte men.signif. de C% " D = byte men.signif. de D% " E = byte men.signif. de E% " H = byte men.signif. de H% " L = byte men.signif. de L% " IY = dirección de la rutina en código máquina (=PC) " IX = dirección del bloque de parámetros (solamente con CALL) USR(dir) llama a una rutina en c. m. y devuelve un entero de 32-bits, producto del contenido de los registros H, L, H' y L' (del más significativo al menos significativo) cuando sale de dicha rutina. CALL dir[,parametros] envía un bloque de parámetros que contienen la sigte. información: Número de parámetros - 1 byte Tipo de Parámetros - 1 byte ) repitiendose a menudo Parametros de la dirección - 2 bytes ) cuantos sean necesarios. Los Tipos de Parametros son los sigtes.: 0: un valor de 8-bits (ejm.: ?X) 4: variable entera de 32-bits (ejm.: !X o X%) 5: variable de coma flotante de 40-bita (ejm.: V) 128: una cadena fija (ejm.: $X, terminando por &0D) 129: una variable de cadena (ejm.: A$) En el caso de una variable de cadena, el parametro de dirección es la dirección de un descriptor de cadena ("String Descriptor") conteniendo la dirección de inicio, el largo real de la cadena y su número de bytes. Los Parametros son pasados por referencia y pueden ser cambiados por la rutina en c. m. 19. Ensamblador Residente Z80 El Basic BBC incluye un ensamblador completo para el procesador anfitrión ("host"), en este caso el Z80. Se trata de un ensamblador en-linea que carga su código objeto directamente en el área de la memoria objetivo; la variable estatica P% es el contador del programa. El ensamblador en-linea es accesado exactamente del mismo modo que el ensamblador 6502 para la versión BBC Micro. O sea, '[' entra al modo ensamblador y ']' sale de él. Los reportes de error y el listado son controlados por el pseudo-op OPT como sigue: OPT 0 Inhibe el reporte de error y no lista. OPT 1 Inhibe el reporte de error pero da listado. OPT 2 Reporta error pero no lista. OPT 3 Reporta error y genera listado. OPT 4 como OPT 0 pero pone codigo en O% antes que en P%. OPT 5 como OPT 1 pero pone codigo en O% antes que en P%. OPT 6 como OPT 2 pero pone codigo en O% antes que en P%. OPT 7 como OPT 3 pero pone codigo en O% antes que en P%. Normalmente el primer paso del ensamblador será con OPT 0 y el segundo paso con OPT 2 (si ningún listado es requerido) o OPT 3 (de requerirse listado). No confundir el pseudo-op OPT con el Comando *OPT del Sistema Operativo. Todos los mnemónicos estandar de Zilog son aceptados: ADD, ADC y SBC deben ser seguidos por A o HL. Por ejemplo, ADD A,C es aceptado pero ADD C no lo es. En cambio los paréntesis en en y OUT son opcionales. De este modo, OUT (5),A y OUT 5,A son igualmente válidos. La instrucción en F,(C) no es aceptada, pero el código equivalente es producido con en (HL),C. Los Pseudo-ops aceptados por el ensamblador son DEFB, DEFW y DEFM; estos escriben un byte de 8-bits, un "word" de 16-bits y una cadena de n caracteres respectivamente. Ejemplo del uso del ensamblador: 100 DIM code 15 :REM Reserva espacio para 16 bytes de código 110 bdos=5 120 FOR pass=0 TO 1 :REM Implementa ensamblado en 2 pasos 130 P%=code :REM el contador del programa al inicio de cada paso 140 [OPT pass*3 ;Entra al ensamblador y selecciona listar en el paso 2 150 LD D,95:LD E,ASC"!" 160 .loop ;una etiqueta 170 LD C,2 ;Sentencias fuente 180 PUSH DE:CALL bdos:POP DE 190 INC E:DEC D:JR NZ,loop 200 RET:] :REM salida del ensamblador 210 NEXT pass 220 CALL code :REM Ejecuta la rutina en ensamblador En este ejemplo en particular, un solo paso hubiera sido suficiente, ya que no hay "referencias hacia adelante". 20. La interfaz del Sistema Operativo Todos los comandos * del Sistema Operativo son pasados al host para su implementación. CALL y USR con direcciones en el rango &FF00 - &FFFF, proveen acceso al sistema operativo de la máquina, igual que con el BBC Micro. Los registros A, H, L y E del procesador son inicializados con los bytes menos significativos de las variables enteras A%, X%, Y% y E%, respectivamente. En el caso de USR, el valor devuelto de 32-bits está compuesto de los registros F, H, L y A del procesador, correspondiendo a los registros P, Y, X y A del 6502 desde el más significativo al menos significativo. La interfaz "host" provee las sigtes. entradas al sistema operativo: OSFIND, OSGBPB, OSBPUT, OSBGET, OSARGS, OSFILE, OSRDCH, OSASCI, OSNEWL, OSWORD, OSBYTE, OSCLI desde &FFCE hasta &FFF7. 21. La interfaz del Sistema "Host" Algunas sentencias y funciones del Basic BBC han sido implementadas llamando a puntos de entrada del sistema operativo en &FF00 - &FFFF así que su functionalidad depende del nivel de soporte aportados por la interfaz host. Las diferencias en la interfaz actual (version 0.3x) han sido listadas aquí. ADVAL coge la información de periféricos de entrada tales como joysticks o mouse, si están conectados, o el número de espacio libre en un buffer. ADVAL(0) botones del joystick ADVAL(-1) bytes en el buffer de teclado ADVAL(1) joystick 1 posición-X ADVAL(-2) bytes en el buffer de entrada serial ADVAL(2) joystick 1 pos.-Y ADVAL(-3) espacio libre en la salida serial ADVAL(3) joystick 2 posición-X ADVAL(-4) espacio libre en la salida de impresora ADVAL(4) joystick 2 pos.-Y ADVAL(-5) espacio libre en la cola del canal 0 de SOUND ADVAL(-6) espacio libre en la cola del can. 1 de SOUND ADVAL(7) mouse posición X ADVAL(-7) espacio libre en la cola del can. 2 de SOUND ADVAL(8) mouse pos. Y ADVAL(-8) espacio libre en la cola del can. 3 de SOUND El host actual del Spectrum no devuelve nada en respusta a ADVAL. CALL CALL pasa el control a una subrutina en c. m. Un CALL a una dirección en el rango de &FF00 - &FFFF, accede a varias funciones del SO tal como se detailó en la sección sobre el interfaz del SO. CLG Borra la pantalla y fija el color de fondo del modo gráfico seleccionado usando la acción actual de trazado (mediante GCOL). Envía CHR$16 al VDU. El host actual borra toda la pantalla con los colores por defecto. BGET# Lee un byte de un canal previamente abierto con OPENIN o OPENUP. El host actual no implementa OPEN. CLOSE# Cierra el canal especificado. El host actual no implementa OPEN, por lo que CLOSE es ignorado. CLS Borra pantalla en modo texto y fija el color de fondo del modo texto. El cursor es movido a la posición 'home' (0,0) en la parte superior izq. de la pantalla. Envía CHR$12 al VDU. COLOUR Selecciona el color de tinta. borde y papel del modo texto. Envía CHR$17;CHR$n al VDU. En el Spectrum no hay colores lógicos, solamente físicos. Los colores son codificados como RGB, en vez del BRG nativo del Spectrum, con los bits individuales teniendo el sigte. significado: Bit 0 - Rojo Bit 1 - Verde Bit 2 - Azul Bit 3 - Brillo Bit 4 - Parpadeo Bit 5 - Cambia solamente el color, no el brillo ni el parpadeo Bit 6 - Cambiaq solo brillo y parpadeo, no los colores Bit 7 - 0 (fija la tinta o brillo/parpadeo), 1 (fija el papel o el borde) De esto resulta que los colores pasan a ser puestos como sigue: &00+n (0-63) - texto, color de tinta &40+n (64-127) - parpadeo y brillo sin cambiar los colores &80+n (128-191) - texto, color de fondo &C0+n (192-255) - borde Tinta Papel Borde Color 0 &00 128 &80 192 &C0 Negro 1 &01 129 &81 193 &C1 Rojo 2 &02 130 &82 194 &C2 Verde 3 &03 131 &83 195 &C3 Amarillo 4 &04 132 &84 196 &C4 Azul 5 &05 133 &85 197 &C5 Magenta 6 &06 134 &86 198 &C6 Cyan 7 &07 135 &87 199 &C7 Blanco El borde no puede parpadear o tener brillo, así que los bits en este caso, son ignorado. DRAW Dibuja una linea con el color de tinta en modo graphico, desde el último punto trazado hasta el X,Y especificado. La resolución siempre es de 1024 pixeles de ancho y 1280 pixeles de alto en todos los modos gráficos. DRAW x,y equivale a PLOT 5,x,y. El actual host del Spectrum ignora a DRAW. ENVELOPE Usado en conjunto con SOUND para controlar el tono y/o amplitud de un sonido mientras se toca. ENVELOPE actualmente es ignorado. EOF# Da TRUE si se alcanza el final del fichero abierto. Ya que OPEN aun no está implementado, EOF siempre dará FALSE. EXT# Da la longitud total del fichero abierto. Al no estar implementado OPEN, siempre da cero. GCOL Selecciona la tinta y papel para el modo gráfico. Envía CHR$18;CHR$m;CHR$n al VDU. Los modos son: 0 se traza con el color elegido. 1 hace un OR al color con el color que ya está ahí. 2 hace un AND al color con el que ya está ahí. 3 hace un OR exclusivo al color con el que ya está ahí. 4 Invierte el color en curso. El color es elegido mediante COLOUR: &00+n (0-63) - tinta para el modo gráfico &40+n (64-127) - brillo y parpadeo en modo gráfico &80+n (128-191) - papel para el modo gráfico &C0+n (192-255) - indefinido El host actual del Spectrum ignora a GCOL. GET/GET$ Espera el sigte. caracter del flujo de entrada de datos, usualmente el teclado. INKEY/INKEY$ Con argumento positivo espera el máximo tiempo especificado en centisegundos por un caracter del flujo de entrada de datos, o devuelve "", o -1 si ninguna tecla es pulsada. Con argumento negativo da el tipo de host o chequea una pulsación individual de teclas, usando los sigtes. códigos de teclas compatible BBC: -001 Shift -017 Q -033 -049 1 -002 Symbol-Shift -018 3 -034 W -050 2 -003 -019 4 -035 E -051 D -004 -020 5 -036 T -052 R -005 -021 -037 7 -053 6 -006 -022 8 -038 I -054 U -007 -023 -039 9 -055 O -008 -024 -040 0 -056 P -009 -025 -041 -057 -066 A -082 S -098 Z -114 -067 X -083 C -099 Space -115 -068 F -084 G -100 V -116 -069 Y -085 H -101 B -117 -070 J -086 N -102 M -118 -071 K -087 L -103 -119 -072 -088 -104 -120 -073 -089 -105 -121 -074 Enter -090 -106 -122 El host actual del Spectrum no implementa escaneo de teclado, devolviendo FALSE. INKEY-256 da &E0 especificando al "Spectrum". INPUT# Lee los datos de un fichero abierto con multiples llamadas a BGET. El host actual no implementa OPEN, así que INPUT# no lee nada. MODE Fija el modo gráfico. La pantalla es borrada y todos los parámetros de gráficos y texto (colores, origen, etc.) son reseteados a sus valores por defecto. Sends CHR$22;CHR$n al VDU. El host actual usa un único modo de pantalla de 32 caracteres por 24 lineas. Esto es casi equivalente al modo 6 del BBC. MOVE Mueve el cursor de gráficos a una posición absoluta sin dibujar ninguna linea. La pantalla es siempre de 1024 pixeles de ancho y 1280 pixeles de alto en todos los modos gráficos. MOVE x,y es equivalente a PLOT 4,x,y. El host actual ignora MOVE. OPENIN Abre un fichero para su lectura y devuelve el número de canal de dicho fichero. Un valor de cero significa que el fichero especificado no fue encontrado, o no se pudo abrir por otra razón. El host actual no implementa OPEN, por lo que da cero. OPENOUT Como OPENIN pero abriendolo para su escritura. Si el fichero no existe, entonces es creado. Si el fichero ya existe, entonces su longitud es puesta a cero y todos los datos que contenía dicho fichero se pierden. Si devuelve cero, significa que el fichero no pudo ser creado. El host actual no implementa OPEN, por lo que da cero. OPENUP Abre un fichero para su actualización (tanto lectura como escritura) y devuelve el número de canal de dicho fichero. file. Si da cero significa que el fichero especificado no fue encontrado, o no se pudo abrir por alguna razón. El host actual no implementa OPEN, por lo que da cero. OSCLI Pasa una cadena para ser interpretada como un comando del 'sistema operativo'. PLOT Una sentencia de trazado multi-propósito. PLOT requiere de tres valores numéricos: la primera especifica el tipo de punto, linea, triangulo, circulo, etc. a dibujar; los otros dos son las coordenadas X e Y a usarse en ese orden. Los valores más usados son comunmente PLOT 4 y PLOT 5, que son los equivalentes de MOVE y DRAW. PLOT envía CHR$25; CHR$k;CHR$(x MOD 256);CHR$(x DIV 256);CHR$(y MOD 256);CHR$(y DIV 256); al VDU. Los códigos de PLOT son: PLOT 0 Mueve a una posición relativa al último punto. PLOT 1 Dibuja una linea relativa con el color de tinta. PLOT 2 Traza una linea relativa en color lógico inverso. PLOT 3 Dibuja una linea relativa con el color de papel. PLOT 4 Mueve el punto a una posición absoluta. PLOT 5 Dibuja una linea absolutea con el color de tinta. PLOT 6 Traza una linea absoluta en color lógico inverso. PLOT 7 Dibuja una linea absoluta en con el color de papel. PLOT 8-15 el último punto de una linea es omitido si se usa el trazo inverso. PLOT 16-23 Las lineas son dibujadas punteadas. PLOT 24-31 Las lineas son trazadas punteadas, omitiendo el último punto. PLOT 32-39 Línea sólida con el punto inicial omitido. PLOT 40-47 Línea sólida pero con los puntos de ambos extremos omitidos. PLOT 48-55 Línea punteada con el punto inicial omitido. PLOT 56-63 Línea punteada pero con los puntos de ambos extremos omitidos. PLOT 64-71 Traza un sólo punto. PLOT 72-79 Rellena líneas Horizontales. PLOT 80-87 Sibuja y rellena un triángulo formado por la pos. y los 2 últimos puntos. PLOT 88-95 Línea horizontal en blanco. El host actual no implementa PLOT. POINT Devuelve el color de la pantalla en las coordenadas especificadas. Si el punto está fuera de la ventana gráfica, entonces da -1. El host actual no implementa POINT. POS Devuelve la posición horizontal actual del cursor de texto en la pantalla. La columna a la izq. es 0 y el de la der. es 1 menos el número de columnas de texto en el modo seleccionado por MODE. PRINT# Escribe datos a un ficehero abierto con múltiples llamadas a BPUT. El host actual no implementa OPEN, por lo que PRINT# es ignorado. En contraste con otras versiones del Basic BBC (Z80), el Basic BBC para el Spectrum, es una conversión del Basic BBC para el coprocesador Z90 de Acorn usando el fichero de E/S del BBC, así que lee y escribe ficheros de datos en el mismo formato que el Basic del 6502 y ARM. PTR# Una pseudo-variable que permite al puntero de un fichero de accesso directo accesarlo para leer y cambiar sus datos. El host actual no implementa OPEN, por lo que escribir al PTR# es ignorado y su lectura no devuele dato alguno. SOUND Generas sonido de acuerdo con los parámetros sigtes.: SOUND canal,volumen,tono,duración canal Los bits 0 - 1 son el número del canal (1 - 3). Si el bit 4 es activado, la cola de sonido es soltada y el nuevo sonido empieza de inmediato. volumen Los valores de -15 a -1 seleccionan un sonido de amplitud 15 a 1 respectivamente con un tono constante, cero genera silencio y los valores del 1 al 15 seleccionan la envolvente (ver ENVELOPE). tono Elige el tono inicial. C medio es 53, y un cambio de semitono es uno de 4. duration Valores de 0 a 254 fijan la duración del sonido, en unidades de aproximadamente 1/20 sw segundo. -1 causa un sonido indefinido, el cual solo puede ser detenido con otra sentencia SOUND con el bit "flush" (soltar) activado o pulsando ESC. El host actual no implementa SOUND. TAB Palabra reservada exclusiva de PRINT o INPUT. TAB(X) pone espacios suficientes para moverse hasta la columna X de acuerdo al valor de COUNT. TAB(X,Y) moverá el cursor a las posiciones X,Y (columna, fila) si es posible enviando CHR$31;CHR$x;CHR$y al VDU. TIME Una pseudo-variable que lee y fija el reloj de 100Hz. TIME es derivado de la variable del sistema del Spectrum FRAMES, el cual es un reloj de 50Hz, por lo que TIME tiene el bit 0 en blanco. TIME$ Una pseudo-variable de cadena de 24 caracteres que lee y fija el reloj del sistema en tiempo real. El formato de la cadena es: Dia,dd Mes aaaa.hh:mm:ss Donde: Dia es Mon, Tue, etc. dd es el día en números: 01, 02, etc. Mes es el nombre abreviado Jan, Feb, etc. aaaa es el año (2003, 2004, etc). hh es la hora (00 a 23). mm los minutos (00 a 59). ss los segundos (00 a 59). El host actual no implementa TIME$, por lo que da una cadena nula y no modifica nada. USR llama a una subrutina en c. m. y devuelve un valor. VPOS Da la posición vertical del cursor de texto. La primera fila es la 0 y la última es un número menor que el número de filas de texto en el modo fijado por MODE. 22. El Sistema VDU VDU Esta instrucción envía una lista de argumentos numéricos al VDU. Un valor de 16-bits puede ser enviado si el valor es seguido de ';'. Se envía como un par de caracteres, con el byte menos significativo primero. Caraceteres de control: Los sigtes. códigos de VDU están definidos. No todas ellas estan actualmente implementadas, pero el host interpreta o "parsea" correctamente el flujo del VDU para las secuencias no reconocidas. VDU 0 Nulo. VDU 1,n envía byte n a la impresora. Ignorado actualmente. VDU 2 habilita la impresora. Ignorado. VDU 3 Desabilita la impresora. Ignorado. VDU 4 hace que el texto sea escrito donde está el cursor modo texto. Ignorado. VDU 5 hace que el texto sea escrito con el cursor modo gráfico. Ignorado. VDU 6 habilita la salida del VDU. Cancela los efectos de VDU 21. VDU 7 provoca un "beep". Ignorado. VDU 8 Mueve el cursor de texto un caracter a la izq. Si se está en (0,1), entonces el bug de la ROM del Spectrum impide que el cursor se mueva a (31,0). Si está en (0,0), el cursor no se moverá. VDU 9 Mueve el cursor de texto un caracter a la der. Bypasea el bug de la ROM del Spectrum para asegurarse que funcione correctamente. VDU 10 Mueve el cursor de texto una linea abajo. VDU 11 Mueve el cursor de texto una linea arriba. Se se está en la linea 1, el bug de la ROM del Spectrum impide que el cursor se mueva más arriba y el cursor termina hasta (0,1). VDU 12 CLS: borra la ventana de texto con color de fondo y mueve el cursor a (0,0). VDU 13 Mueve el cursor de texto hacia el margen izq. de la ventana, pero no la mueve verticalmente. VDU 14 Entra al modo paginado. Aun no soportado. VDU 15 Detiene la paginación. Aun no soportado. VDU 16 CLG: borra la ventana de gráficos usando la acción y color de fondo de GCOL. El host actual borra toda la pantalla. VDU 17,n COLOUR n: fija el color de tinta, papel o borde del modo texto. VDU 18,a,c GCOL a,c: fija el color en modo gráfico. Ignorado actualmente. VDU 19,l,p,r,g,b pasa del mapa de color lógico al físico. Actulamente ignorado. VDU 20 fija los colores de texto y gráficos a sus valores por defecto (fondo negro con tinta blanca), resetea la paleta. VDU 21 Desabilita la salida del VDU. Todos los comandos VDU excepto 6 son ignorados. VDU 22,n MODE n: Selecciona un nuevo modo de pantalla y resetea todas las variables (colores, paleta, ventanas, posición de cursor, origen de gráficos, etc). El host actual se queda en los 32 x 24 del Spectrum para todos los modos. VDU 23,n,r1,r2,r3,r4,r5,r6,r7,r8 Programa los caracteres gráficos definidos por el usuario, y varias funciones VDU. Actualmente solo los caracteres &90 - &9F son redefinibles, también los caracteres &20 - &7E, si CHARS es fijado a la RAM. VDU 24,leftx;bottomy;rightx;topy; Define la ventana de gráficos. Actualmente no implementado. VDU 25,n,x;y; PLOT k,x,y: ejecuta una acción PLOT. Actualmente no implementada. VDU 26 Resetea las ventanas de texto y gráficos a sus posiciones por defecto (llenando toda la pantalla), el cursor de texto a 'home', el cursor gráfico y origen a 0,0. VDU 27 No hace nada. VDU 28,leftx,bottomy,rightx,topy fija una ventana de texto. El cursor es movido a la nueva posición 'home'. Aun no implementado. VDU 29,x;y; Mueve el origen gráfico las coordenadas especificadas. No implementada. VDU 30 Pone el texto en 'Home', la esquina superior izq. VDU 31,x,y TAB(x,y): Mueve el cursor a (x,y) si se está dentro de la ventana de texto. Se ignora si las coordenadas son invalidas. VDU 127 retrocede el cursor una posición y borra el chracter en ese punto. Caracteres imprimibles: Los caracteres 32 - 126 (&20 - &7E) son los caracteres del Spectrum que son fijados por CHARS. Los caracteres 128 - 143 (&80 - &8F) son al inicio fijados al bloque de gráficos Spectrum. Los caracteres 144 - 159 (&90 - &9F) son los UDCs y son al inicio fijados para las formas en inverso de "A" a "P". Los caracteres 160 - 255 initialmente son copias de &20 - &7F, dando CHR$255 correspondiente al signo '(c)' del Spectrum. 23. Comandos del Sistema Operativo Los sigtes. comandos han sido implementados por el código del host que interfacea el Basic BBC al sistema del Spectrum. *| *| comentario Todo lo que sigue a '|' es ignorado. */ */filename [parametros] Abreviación para *Run. *d: *drive: Selecciona d como la unidad disp. por defecto. *BASIC *BASIC [nombre] Entra al Basic BBC. *CAT *CAT [drive] Cataloga la unidad especificada o por defecto *DELETE *DELETE file Borrra un archivo. *FX *FX a[,b[,c]] Controla varios efectos con el MOS. *GO *GO [dir [params]] Llama una rutina en dir, o entra al prompt de comandos MOS si no hay dir. *HELP *HELP [words] Muestra información sobre el sistema. *LOAD *LOAD file [aaaa] Carga file en la dirección hex. aaaa, la cual puede ser FFFFxxxx especificando la memoria de pantalla. *QUIT *QUIT Vuelve al proceso de llamada, de poderse. *RUN *RUN file [params] Carga y ejecuta el file especificado, pasándole cualquier parámetro. *SAVE *SAVE file ssss eeee Salva la RAM desde la dirección hex. ssss hasta la dir. eeee-1. *SAVE file ssss +llll Salva la RAM desde la dirección ssss con una longitud llll. La dirección puede ser FFFFxxxx a la memoria de pantalla especificada. Si un *comando no es reconocido, el host trata de cargar y ejecutar desde la unidad por defecto. Los nombres de fichero son [d:]filename. Si d: está presente, solamente puede ser T: por Tape o 1: al 8: para microdrives 1 al 8. Al resetear, T: es seleccionado si no existe un Interface 1 conectado, de haberlo, 1: es seleccionado. Los comandos del SO pueden ser abreviados y/o tipeados en minúsculas. Un *comando no puede contener nombres de variable y debe ser el último elemento de una línea de programa. Para poder incluir una variable se debe usar la sentencia OSCLI, por ejemplo, para borrar un archivo cuyo nombre sólo se conoce al momento de ejecución: OSCLI "DELETE "+nombre$ 24. Ficheros de acceso directo o aleatorio El Basic BBC soporta el acceso directo así como la posibilidad de modificar (actualizar) un fichero previamente escrito. El accesso directo es efectuado mediante un puntero (PTR#chn), el cual puede ser posicionado en cualquier parte del fichero. El puntero es automaticamente incrementado tras operación de lectura o escritura (mediante BGET#, BPUT#, INPUT# o PRINT#). Ejemplos: 100 REM lee un fichero hacia atras 110 fin=OPENIN(nombre$):size=EXT#fin 120 FOR point=size-1 TO 0 STEP -1 130 PTR#fin=point : PRINT CHR$(BGET#fin); 140 NEXT : CLOSE #fin 100 REM actualiza un "registro" en un fichero de acceso directo 110 fin=OPENUP(nombre$) 120 PTR#fin=record_number*record_length 130 PRINT #fin,nuevo_dato,nuevo_dato$ 140 CLOSE #fin 25. Entorno del Spectrum "Host" (Aun por escribir hasta el momento de esta traducción). Traducción: Francisco León (c)2018 zx_if1@hotmail.com