VIC-veinte...ando con un ZX Spectrum o del Basic 2.0 al Basic Sinclair A manera de introducción. Este artículo se divide en tres partes. La primera trata sobre el emulador "Twenty Commodes" de James Smith, y es una traducción al español del texto original en inglés del autor. La segunda es dedicada al Basic del Vic=20, y la tercera es una observación de lo que el emulador permite y no permite comparado con un VIC=20 real. Parte I *** TWENTY COMMODES *** V1.90 Este programa emula un Commodore Vic=20 en un ZX Spectrum. Originalmente introducido en la CSSCGC2008, con muchas mejoras a partir de la versión 1.90. El programa funciona sin sonido en un 48k estandar. Un 128k o 48k con interface AY compatible, ofrecerá una emulación aceptable del sonido del VIC. Un joystick Kempston puede ser usado para replicar al mando de juegos del VIC. Si el emulador o clon permite acelerar la velocidad, entonces este es el momento de aprobvecharla. Un Z80 a 50MHz emulará al 6502 y hardware de un modo aceptablemente bien. 1) ¿Qué es un VIC=20? Si el PET fue la primera computadora de Commodore, el VIC fue la que introdujo estas máquinas al campo familiar y de aficionados en Norte América. Cuando salió a la venta en 1980, ofrecía muchas cosas más que sus competidores y por menos precio. Era barata y con un buen teclado, además de hardware para gráficos, reloj y E/S. Encima, color y sonido. El ZX-80 de Sinclair también salió ese año por £99 ($200), pero era mucho más simple que el VIC. Aunque no es justo compararlas, es interesante notar las diferencias que hubo a la hora de diseñar las computadoras entre británicos y estadounidenses. 2) Respecto al emulador 2.a) ¿Por qué emular un VIC=20? Es bien sabido que los usuarios del C=64 y Timex/Sinclair tienen una rivalidad amistosa (entre comillas). Así que pensé que sería bueno que un Spectrum emule una máquina de Commodore. Elegí al VIC=20 porque no tiene los más complejos chips SID y VIC-II, pero corre el Basic 2.0 de CBM en toda su gloria. El VIC también tiene pocos colores y su resolución es menor a la del Spectrum, con lo que la emulación se hace más facil. El modo de texto de 40 caracteres del C=64 podría ser dificil de emular apropiadamente en un Spectrum. ¿Se puede emular totalmente al VIC=20? Obviamente no, pero sí se puede replicar buena parte de su hardware. ¡Lo suficiente como para lograr correr algunos juegos comerciales! A continuación, veremos cómo cada parte de la arquitectura del VIC es emulada. Notaran que tal vez suene algo técnico. 2.b) CPU 6502 El programa tiene un 6502 virtual igual que el emulador de UK-101, Emula todas las instrucciones NMOS 6502 y también muchas del CMOS 6502. Las instrucciones no implementadas son: BBS,BBR,STO,WAI,SMB y RMB. Las otras instrucciones y modos de direccionamiento del CMOS han sido implementadas. El 6502 adopta un comportamiento CMOS cuando trata con interrupciones (BCD en OFF), la aritmética BCD (los flags se ponen correctamente) y la orden JMP (trabaja correctamente). Si un "código ilegal" es usado, el borde se pone rojo, pero continúa corriendo. Ese código será convertido a NOP, como el CMOS 6502, y PC será incrementado por 1, 2 o 3 bytes tal como se comporta el CMOS. El emulador carece de código JAM. 2.c) 6522 VIAs Es imposible emular un reloj de 1MHz con el reloj de 50Hz del Spectrum. Por lo tanto, no he intentado emular T1 y T2 de cada VIA. La dirección $9114 emula 1sb de T1 devolviendo valores aleatorios (supongo que RND lo usa). Las posiciones $911F y $912F son atrapadas y trabajan igual que $9111 y $9121. Las direcciones $9111 y $9120 emulan el joystick leyendo el puerto Kempston del Spectrum. La $9121 es emulada para el teclado VIC. 2.d) El chip VIC $9000/1 - posiciona la pantalla (HPOS y VPOS) - no emulado. $9002 - cambia el ancho (1-27). Desde la versión 1.72 en adelante emula el Bit 7 (inicio RAM color) y permite hasta 31 columnas. $9003 - cambia la altura (1-23). Bit 7 es soportado - ver $9004. Bit 0 soportado con limitaciones (Doble alto). Los caracteres son dibujados las 2 filas de alto requeridas, pero los atributos solo aplican a la mitad superior de la fila. El código doble-alto inacabado. Muchos juegos fijan la altura mayor de 12, y eso significa que la imagen ya no se ve totalmente en una pantalla ZX de 24 filas ("Duck Hunt" es un ejemplo). $9004 - emulada. Cuando se lee esta posición, el valor del raster retornado incrementa en un bucle entre 0-311. Bit 0 del contador del raster contenido en bit 7 de $9003. Programas que confían en el valor seguro del raster fallarán (o muy probablemente solo parpadeen). $9005 - permite redefinir el juego de caracteres moviéndolo a un punto diferente en la memoria. Bits 4-7, fijan la RAM de video, no soportado. El uso de la memoria de caracteres empezando en $1E00 hasta $8000 es soportado. Los cambios de la Versión 1.86 a este registro forzando la pantalla han sido rediseñados. Pulsar CBM y SHIFT cambia el juego de caracteres de modo inmediato. $9006/7 - registros del lightpen. No emulado. $9008/9 - registros de los paddles. No emulado. $900A/B/C - frequencia de voces alto/tenor/sopranos. Convertidos a un tosco equivalente en el AY-3-8912. $900D - frequencia del canal de ruido, pesimamente emulado! Los chips AY y VIC implementan el ruido de modo diferente. $900E - control de volumen emulado. Bits 4-7 fijan el color auxiliar - no es soportado. No hay multicolor. $900F - color del borde (bits 0-2), tinta (bit 3) y fondo (bits 4-7) soportados. Con la V1.90, el soporte para la ULA II (más colores) ha sido añadido. Esto le permite al Spectrum mostrar todos los 16 colores del VIC tanto como se vería en un VIC real. En un Spectrum estandar no todos los colores están disponibles. La V1.87 permitía al Spectrum estandar mostrar combinaciones de color que antes hubleran "colisionado" (clashed) al dar un toque "invisible" como el rosa sobre fondo rojo (antes salía rojo claro + rojo). Una tabla de color (256 bytes) es usada para coger un par de colores adecuado. Significa que se pueden cambiar los colores "indisponibles", por ejemplo, el purpura claro puede ser magenta claro o cyan claro. Sin modo multicolor, los cambios al ancho o altura de la pantalla y color de borde fuerzan a redibujar el borde virtual (fuera de la pantalla del VIC, pero dentro del area del borde del Spectrum) 2.e) El teclado del VIC El VIC tiene más teclas que el Spectrum, por lo que una curiosa combinación de teclas es requerida para el caso. Todo el teclado alfanumérico ZX ha sido mapeado a su equivalente VIC. SHIFT izq. es simulado por CAPS S. DEL es CAPS + 0 por DELETE. F1, F3, F5 y F7 son SYM + 1, 3, 5 y 7 respectivamente. F2, F4, F6 y F8 son obtenidas igual que en el real VIC, así que F2 es CAPS + SYM + 2. RUN/STOP es SYM + A (STOP en el Spectrum) La tecla C= es SYM + C por COMMODORE RESTORE + RUN/STOP es CAPS + SPACE (BREAK en el Spectrum) : SYM + Z [ CAPS + SYM + Z £ SYM + X / SYM + V ? CAPS + SYM + V * SYM + B _ CAPS + SYM + B , SYM + N < CAPS + SYM + N . SYM + M > CAPS + SYM + M ^ (↑) SYM + H PI (π) CAPS + SYM + H - SYM + J + SYM + K = SYM + L <- (←) SYM + R ; SYM + O ] CAPS + SYM + O @ SYM + 2 LEFT CAPS + SYM + 8 RIGHT SYM + 8 UP CAPS + SYM + 6 DOWN SYM + 6 HOME SYM + 4 CTRL y SHIFT LOCK no han sido emuladas. 2.f) Memoria La V 1.90 ahora soporta varias configuraciones de memoria del VIC=20. Una vez seleccionada ya no se puede cambiar hasta resetear y cargar de nuevo el programa. Los Spectrum modelos 48/128/+2 pueden simular un VIC=20 de 5.5k o uno expandido con 3k más. Los Spectrum +2a/+3 pueden usar su modo de 64k, para simular un VIC=20 con las sigtes. expansiones: 5.5k+8k, 5.5k+16k o 5.5k+3k+16k; o emular cartuchos ROM de 8 a 16k. ¡Así que sí se puede jugar "Radar Rat Race"! El dilema: el modo de 64k usa mayor contensión de la memoria, lo que hace que sea más lento que cuando se elige el modo de 5.5k o el expandido con 3k más. 2.g) Grabadora y dispositivos E/S. Esta versión no emula ni la grabadora ni ningún otro dispositivo IEE488. El único modo de cargar un juego, es importando un fichero binario de tal juego poniéndolo dentro de la RAM disponible del VIC=20. 2.h) Interrupciones El VIC=20 usa interrupciones normales y NMI. Pulsar RESTORE + RUN/STOP (BREAK) genera un NMI. Una interrupción regular es generada por el emulador cada 1/50 de segundo. El VIC opera en realidad a 1/60. El cursor parpadea por eso un poco más lento y las funciones de reloj como TI, pueden resultar erroneas. 2.i) Los cambios desde las versiones anteriores. La V 1.90 tiene muchas mejoras comparada con las versiones anteriores. La emulación del 6502 es más rápida, de menor tamaño y más segura que antes. El atrapamiento de E/S fue acelerado para que escribir en la pantalla sea más veloz que anteriormente. Al soportar la ULA-II, uno puede ver los juegos tal como se supone que deberían verse. La memoria de video puede ser movida y los cambios se ven de inmediato. RESTORE + RUN/STOP ha sido mejorado y diversos tamaños de memoria son soportados. 2.j) "Bugs" conocidos La lectura, modificación y escritura de los códigos del 6502 no opera muy bien respecto a los puertos de E/S y la memoria de pantalla. Esto hace que el sonido salga incorrecto y los puntajes no se actualicen en la pantalla. El modo doble altura no sirve en la V 1.90 y el emulador se pone lento cuando se mantiene presionada mucho una tecla. No sé si es un "bug" o un efecto secundario de cómo el kernal del VIC procesa la pulsación de teclas. 3) Respecto al software del VIC=20 3.a) Lo que sí funciona Muchos programas comerciales funcionarán, pero cualquier programa que dependa de los relojes del VIA dejará de funcionar - Wacky Waiters, por ejemplo. 3.b) Cómo cargar juegos Ya que no hay emulación de grabadora o disco, necesitamos un método alternativo para cargar juegos. El sigte. ejemplo os permitirá jugar al "Blitzkreig" de Llamasoft. Es perfectamente legal descargar y jugar este juego, ya que su autor Jeff Minter ha dado su pleno permiso para hacerlo. Primero descargamos el "Blitzkreig" en formato TAP. Tal vez uno quiera probar con otro juego como "Gridrunner" que está en formato PRG y corre bien en el emulador. Pero solamente parece cargar si se elige un VIC sin expansión alguna. Segundo, usar el emulador VICE y ejecutar el VIC=20. Configurarlo para cumplir las mismas especificaciones que la versión ZX. Verificar en el menú de opciones del VIC que está seleccionada la expansión de 3k en el bloque 0. Tercero, cargar el juego en TAP. Luego pulsar ALT+M para acceder al monitor. Salvamos ahora los 8K de RAM del VIC tipeando SAVE "filename.bin" 0 $0000 $1FFF. El problema es que VICE salva el bloque de memoria con una cabecera de dos bytes. Debemos removerlos. Yo uso "Filetweak" ya que es gratuito y es un muy buen editor lector hexadecimal. De lo contrario, tratamos de cargar el bloque de memoria dos bytes más antes (p.e.: $7FFE en vez de $8000), pero al hacerlo corrompemos el kernal. La V 1.90 tiene una rutina que puede deshacer la corrupción tras cargar el binario, poniendo PC a $B3F8. Esto resetea la memoria y ejecuta, sin importar lo que la máquina hiciera antes de la interrupción. Cuarto, cargamos el fichero binario (que debe tener 8192 bytes de largo) en la posición $8000 del Spectrum (lo cual es muy facil de hacer en un emulador). Si el emulador se bloquea con el borde puesto a rojo, hay que tratar de forzar un NMI pulsando BREAK. Usualmente eso funciona. De ser así, reaparecerá el prompt READY. Basta tipear RUN ahora y el juego deberá ejecutarse. Si queremos evitarnos todo este "prueba y error", debemos hacer lo sigte.: Cargar el binario en $8000 (primeros 8K RAM, recordemos que la RAM se cargará en $0200, $5E00, y $2000). Fijar DE igual al PC del 6502 Poner E' igual al registro del stack del 6502 Hacer IYH igual al reg. Y del 6502 Igualar IYL al registro X del 6502 Colocar A' igual al reg. A del 6502 Dejar F' igual al reg. F del 6502 (no es muy seguro ya que solo los flags del Z80 C, S y Z son usados por el nucleo del 6502) Saltar a la dirección en IX (ej.: JP (IX) ) para empezar a decodificar la sigte. instrucción 6502. 3.c) Cómo salvar los juegos Es más facil salvar la memoria del Spectrum como un "snapshot", si lo que uno desea es volver a cargar un juego del VIC=20 más tarde. Los 8K RAM ($0000-$1FFF) del VIC se encuentran en la posición $8000-$9FFF del Sinclair ZX. La memoria más allá de $2000 del VIC se encuentra en las posiciones $0200-$3FFF y $5E00-$5FFF del banco ZX de 64K RAM. Se puede exportar el contenido del Twenty C. y luego importarlo al VICE, para entonces pasarlo todo a discos o cintas reales de VIC. 4) Los mapas de memoria 4.a) La memoria del VIC=20 real $0000-$03FF 1K RAM más bajo - incluye página cero y páginas del stack $0400-$0FFF memoria extra de 3K de expansión $1000-$1FFF estandar 4K RAM - cabe en todos los VIC ($1E00-$1FFF video RAM) $2000-$3FFF memoria extra 8K de expansion. Fuerza la video RAM a ir a $1000 $4000-$5FFF no usada - puede usarse para otra expansión de 8K. $6000-$7FFF puede servir como expansión de 8K RAM u otro cartucho de 8K ROM $8000-$8FFF juego de caracteres en ROM usado por el chip VIC $9000-$900F registros 0-15 del chip VIC $9110-$911F VIA 1 $9120-$912F VIA 2 $9600-$97FF memoria del color (solo 4 bits validos en el VIC real) la expansión de 8K mueve este bloque a $9400-$95FF. $A000-$BFFF espacio para el cartucho de 8K ROM $C000-$DFFF 8K BASIC ROM $E000-$FFFF Kernal ROM (en realidad el BASIC se desborda hasta el area más baja del kernal) 4.b) La memoria del Spectrum 64K RAM: $0200-$1FFF 8K VIC=20 RAM ($2000-$3DFF) o segundo cartucho 8K ROM ($6000-$7FFF) $2000-$3FFF 8K VIC=20 RAM ($4000-$5FFF) o cartucho 8K ROM ($A000-$BFFF) $4000-$5AFF pantalla del Spectrum $5B00-$5DFF area del BASIC y variables del sistema $5E00-$5FFF última parte del 8K VIC=20 RAM ($3E00-$3FFF) Estandar 16K ROM + 48K RAM: $0000-$3FFF ZX 16K ROM $4000-$5AFF pantalla del Spectrum $5B00-$5FFF area del BASIC y variables del sistema Ambos: $6000-$7FFF Kernal ROM $8000-$9FFF 8K VIC=20 RAM ($0000-$1FFF) $A000-$AFFF juego de caracteres en la ROM $B000-$B1FF memoria de color $B200-$DFFF código del emulador $E000-$FFFF 8K BASIC ROM 5) Comentarios finales. Espero que disfruten de este programa. Si alguien más desea portar el código Z80 a otras plataformas, siéntase libre de modificar el código fuente. Se ensambla con TASM. Solamente pido que acrediten "Twenty Commodes" como la fuente y proveer enlaces a la competición "crap computer games 2008 (CSSCGC2008)". Cualquier duda consultar en los foros del World of Spectrum (www.worldofspectrum.org). Sería interesante ver alguna mejora al nucleo del 6502. Ya está bastante bien optimizado, pero de seguro ese raro estado T puede ser mejorado aquí y allí. El código no es demasiado claro, todo eso fue sacrificado a cambio de velocidad. Parte II Muy bien, hasta ahí las notas del autor sobre su emulador, pasamos ahora a hacer un breve resumen de las instrucciones del Basic del VIC=20. 1) El Basic 2.0 Palabras reservadas: Cont, List, Load, New, Run, Save, Verify, Clr, Data, Def Fn, Dim, End, For, To, Next, Step, Get, Goto, Gosub, Return, If, Then, Rem, Let, Input, Print, On, Poke, Read, Restore, Stop, Sys, Wait, Close, Cmd, Get#, Input#, Print#, Open, Not, And, Or, Abs, Asc, Atn, Chr$, Cos, Exp, Fre, Int, Left$, Log, Mid$, Pos, Right$, Sgn, Peek, Rnd, Len, Sin, Spc, Sqr, Status, Str$, Tab, Tan, Ti, Ti$, Usr, Val Abreviaciones usadas en este texto: exp - expresión aritmética var - nombre de variable val - un número ya sea entero o de coma flotante. <~ - representa la tecla ENTER [S] - tecla SHIFT COMANDOS CONT abrev.: C[S]O continua el programa detenido por la tecla STOP, las sentencias END o STOP. LIST sintaxis: LIST {x}{-y} abrev.: L[S]I Sin parámetros, lista todo el programa como LIST 0. ´x-´ lista desde x en adelante. ´-y´ lista desde el inicio hasta y. ´x-y´ lista solamente el bloque de lineas en ese rango x muestra solo esa linea LOAD sintaxis: LOAD {n$}{,di,co} abrev.: L[S]O donde: n$ = nombre de fichero, di = 1(cinta)/8(disco), co = comando 1-3 Sin parámetros, carga el primer programa que encuentra en la cinta. Acepta "*" como comodín. Ejemplo: LOAD "AB*",8 - cargará del disco el primer programa que cumpla la condición. NEW borra de la memoria el programa en curso. RUN sintaxis: RUN {x} abrev.: R[S]O Ejecuta desde línea x. Sin parámetros ejecuta el programa desde su primera línea. SAVE sintaxis: SAVE {n$}{,di,co} abrev.: S[S]O Sin parámetros, salva en la cinta el programa en curso. SAVE guarda dos veces el programa de modo automático, para que LOAD chequee errores a la hora de cargarlo. Cuando se salva con un nombre, le es más facil al VIC, ubicar y cargar. En un VIC sin expansión, se salva y carga en la posición 4096. Y en la 1024 con los 3k extras. Si co=1, se fuerza la posición de memoria. Si co=2, se crea una marca de fin de cinta. Si co=3, provoca 1 y 2 al mismo tiempo. VERIFY sintaxis: VERIFY {n$}{,di} abrev.: V[S]O Suele usarse luego de SAVE, para comparar el programa en memoria con el de la cinta o disco. En caso contrario genera mensaje de error. SENTENCIAS CLR abrev.: C[S]L borra cualquier variable definida, desDIMensiona las matrices y restaura el puntero de DATA a su inicio. DATA sintaxis: DATA lista de datos abrev.: D[S]A Esta instrucción contine los datos que serán leidos mediante la orden READ. DEF FN sintaxis: DEF FN var(x)= exp abrev.: D[S]E Permite definir una función matamática que normalmente debe ponerse al comienzo del programa. DIM sintaxis: DIM var (exp) {,var2 (exp2) , ...} abrev.: D[S]I dimensiona una matriz numérica o una cadena. Una vez hecho eso, ya no hay redimensionamiento. END abrev.: E[S]N termina la ejecución de un programa. FOR - NEXT sintaxis: FOR var = expl TO exp2 {STEP exp3} NEXT var donde: var = indice o contador del bucle exp1 = valor inicial exp2 = límite exp3 = incremento opcional abrevs.: F[S]O y N[S]E La sentencia FOR inicializa var y comprueba que termine el bucle. NEXT incrementa el contador de 1 en 1 a menos que se use STEP para cambiar eso. GET sintaxis: GET var{$} abrev.: G[S]E Espera a que se pulse una tecla y devuelve el caracter asociado a ella. Si no se pulsa nada, devuelve 0 si var es numérica, o una cadena vacía si es var$. GOSUB - RETURN sintaxis: GOSUB val abrev.: GO[S]S y RE[S]T GOSUB salta a una subrutina en la línea indicada por la constante val. RETURN debe estar al final de la subrutina para indicar el retorno al punto desde el que se la llamó. GOTO ó GO TO sintaxis: GOTO val donde: val = una constante numérica, jamás una variable. abrev.: G[S]O permite ejecutar líneas fuera de su orden numérico, saltando a la línea indicada por 'val'. IF ... THEN sintaxis: IF (expr) THEN st / val donde: st = una sentencia BASIC val = un número de línea válido Salta a un número de línea (como GOTO) o ejecuta la(s) sentencia(s) dependiendo de que se cumpla o no la condición exp. INPUT sintaxis: INPUT item donde: item = un texto opcional, var, var$ o matriz var()/var$() una sentencia INPUT puede tener varios items separados por una coma. INPUT imprime un signo "?" indicando que espera a que el usuario ingrese algo. LET sintaxis: {LET} var = exp abrev.: L[S]E evalúa la expresión y la asigna a una variable ya sea numérica, de cadena o matriz. ON sintaxis: ON exp GOTO/GOSUB val {, val2 ,val3, ....} Permite saltar a una línea o subrutina dependiendo del valor de exp. ON también admite formulas y operadores logicos como IF. De modo que todas las líneas IF del sigte ejemplo: IF A-7 THEN 400 IF A=3 THEN 900 IF A<3 THEN 1000 IF A>7 THEN 100 pueden ser reemplazadas por una sola línea ON: ON -(A-7) -2*(A-3) -3*(A<3) -4*(A>7) GOTO 400, 900, 1000, 100 POKE sintaxis: POKE expl, exp2 donde: exp1 = un valor de 0 a 65536 y exp2 = un valor de 0 a 255 abrev.: P[S]O coloca en la posición de memoria exp1 el valor exp2. PRINT sintaxis: PRINT item(s) abrev.: ? La inversa de INPUT, imprime en la pantalla cualquier item que se le dé. READ sintaxis: DATA lista de vars. abrev.: R[S]E como INPUT, pero para leer los contenidos DATA en sus variables correspondientes. REM permite añadir mensajes a un programa sin afectar su ejecución. RESTORE abrev.: RE[S]S Retorna el puntero a la primera sentencia DATA del programa. STOP abrev.: S[S]T detiene el programa de modo similar a END. SYS sintaxis: SYS exp abrev.: S[S]Y llama a la subrutina en codigo máquina alojada en la posición de memoria exp. WAIT sintaxis: WAIT exp, val1 {,val2} donde: exp = una posición de memoria val1 = máscara de bits a filtrar (0-255) val2 = el gatillador de la condición (0-255) abrev.: W[S]A Esta instrucción detiene el programa y espera que 'exp' reconozca una cierta conformación de bits. 'val1' filtra los bits que no queremos probar y 'val2' modifica los bits para probar si están en 1 o 0. Sentencias E/S CLOSE sintaxis: CLOSE exp abrev.: CL[S]O Cierra un fichero abierto por OPEN. Se recomienda le anteceda un PRINT#. CMD sintaxis: CMD exp abrev.: C[S]M redirige la salida de pantalla a cualquier otro dispositivo. De este modo, datos o listados pueden ser mandados a la impresora, al disco o cintas. Ejemplo: OPEN 1,4: CMD 1: PRINT "HELLO THERE!": PRINT# 1: CLOSE 1 GET# sintaxis: GET# exp, var lee los datos un byte a la vez de cualquier fichero abierto con OPEN. Ejemplo: 1O OPEN 1, 3 20 PRINT CHRS{147) "HELLO THERE" CHRS{19); 30 FOR L =1 TO 22 40 GET #1, BS : A$ =A$+BS 50 NEXT :PRINT A$ :CLOSE 1 INPUT# sintaxis: INPUT# exp, vars abrev.: I[S]N como INPUT, pero en vez del teclado, lee los datos almacenados en cinta o disco. INPUT# puede ser usado incluso como reemplazo de INPUT. No genera el signo "?". Ejemplo: 10 OPEN 1,0 20 PRINT "ENTER A NUMBER": INPUT#1, A 30 PRINT A "TIMES" 5 "EQUALS'1 A*5 OPEN sintaxis: OPEN exp{,di}{,co}{,n$} donde: exp = un valor de 1 a 255 para el fichero di = un valor también de 0 a 255 para elegir el periférico c0 = 0 - 255 como comando, depende del periferico seleccionado n$ = texto a imprimir, nombre de fichero o comando de disco abrev.: O[S]P abre un canal para lectura/escritura a un periférico, el cual puede ser la pantalla, el teclado, cintas, discos o impresoras. PRINT# sintaxis: PRINT# exp, items abrev.: P[S]R como PRINT, pero enviando los datos al periferico seleccionado mediante OPEN. Los datos pueden ser separados mediante ",", ";" y CHR$(13). Ejemplo: 100 OPEN 1,1,1,"TAPE FILE" 110 R$ =CHR${13) 120 PRINT#1, 1; R$; 2; R$; 3; R$; 4; RS; 5 130 PRINT#1, 6 140 PRINT#1, 7 FUNCIONES numéricas ABS(x) - abrev.: A[S]B. devuelve el valor absoluto de x ATN(x) - abrev.: A[S]T. devuelve arcotangente de x en radianes COS(x) - devuelve el coseno de x EXP(x) - abrev.: E[S]X. devuelve exponente para x <= 88.02969191 INT(x) - devuelve el valor entero de <= x LOG(x) - devuelve el logaritmo natural de x RND(x) - abrev.: R[S]N. donde: x = valor semilla, que sirve de base para calcular el número aleatorio. Devuelve un valor entre 0 y 1. Si x>0, devuelve la misma secuencia de valores aleatorios Si x<0, devuelve una secuencia diferente Si x=0, genera los números dependiendo del reloj interno SGN(x) - abrev.: S[S]G. devuelve 1 si x>0, 0 si x=0, y -1 si x<0 SIN(x) - abrev.: S[S]I. devuelve el seno de x SQR(x) - abrev.: S[S]Q. devuelve la raiz de x TAN(x) - devuelve la tangente de x en radianes FUNCIONES de cadenas ASC(x$) - abrev.: A[S]S. devuelve el valor ascii de la primera letra de x$ CHR$(x) - abrev.: C[S]H. devuelve el caracter cuyo ascii es x LEFT$(x$,n) - abrev.: LE[S]F. devuelve n caracteres a la izq. de x$ LEN(x$) - devuelve el numero de caracteres de x$ MID$(x$,x {,n}) - abrev.: M[S]I. devuelve n caracteres desde x RIGHT$(x$,n) - abrev.: R[S]I. devuelve n caracteres a la derecha de x$ SPC(n) - abrev.: S[S]P. genera n espacios, solamente sirve con PRINT STR$(x) - abrev.: ST[S]R. devuelve una cadena conteniendo el valor de x TAB(n) - abrev.: T[S]A. tabula o desplaza el cursor de PRINT n espacios VAL(x$) - abrev.: V[S]A. devuelve el numero contenido en x$ FUNCIONES especiales FRE(x) - abrev.: F[S]R. devuelve el numero de bytes libres sin importar x PEEK(x) - abrev.: P[S]E. lee la posición de memoria x, y devuelve su contenido POS(x) - devuelve la posición actual del cursor sin importar x STATUS - abrev.: ST. devuelve último estado de operación E/S TIME - abrev.: TI. devuelve valor del reloj en tiempo real una décima de segundo TIME$ - abrev.: TI$. lee o inicializa el reloj mediante una cadena de 6 dígitos USR(x) - abrev.: U[S]S. envía x a una rutina en C.M. direccionada mediante POKE. Operadores lógicos AND - devuelve 1 si ambos bits son 1, cero si no es así. OR - devuelve 1 siempre que al menos un bit sea 1, cero en caso contrario. NOT - devuelve 0 si el bit es no-cero, 1 si es cero. MENSAJES DE ERROR BAD DATA - debía leerse datos numéricos de un fichero, pero fue alfanumérico. BAD SUBSCRIPT - el sub-indice de la matriz está fuera del rango dado por DIM. CAN'T CONTINUE - CQNT no opera por un error, edición o nunca se ejecutó RUN. DEVICE NOT PRESENT - E/S no existe para OPEN, CLOSE, CMD, PRINT#. INPUT#, o GET#. DIVISION BY ZERO - se intentó hacer una división por cero. EXTRA IGNORED - se ignoraron los datos tipeados de más en una orden INPUT. FILE NOT FOUND - no se encontró el archivo en cinta o disco. FILE NOT OPEN - se intentó CLOSE, CMD, PRINT#, INPUT*, o GET#. sin un OPEN. FILE OPEN - se intentó abrir un fichero ya abierto. FORMULA TOO COMPLEX - la expresión de cadena debe ser dividida para ejecutarla ILLEGAL DIRECT - solo puede usarse INPUT dentro de un programa. ILLEGAL QUANTITY - número usado como argumento de función o sent. fuera de rango. LOAD - hubo un problema al cargar un programa de la cinta. NEXT WITHOUT FOR - hubo un Next sin su correspondiente For. NOT INPUT FILE - se intentó INPUT o GET con un fichero abierto para escritura. NOT OUTPUT FILE - se intentó PRINT a un fichero abierto para lectura. OUT OF DATA - se acabaron los datos para leer por READ. OUT OF MEMORY - no hay RAM disponible para el programa o sus variables. OVERFLOW - el resultado de un computo es mayor a lo permitido: 1.70141884E + 38. REDIM'D ARRAY - una matriz solo se puede DIMensionar una vez. REDO FROM START - se tipeó un caracter cuando INPUT esperaba un número. RETURN WITHOUT GOSUB - se encontró un RETURN sin su GOSUB correspondiente. STRING TOO LONG - la cadena contenía más de 255 caracteres. SYNTAX - el VIC no acepta la sintaxis, por mal escrita, muchos parentesis, etc. TYPE MISMATCH - se usó un número en vez de una cadena, y viceversa. UNDEF'D FUNCTION - se usó FN pero sin definirla mediante DEF FN. UNDEF'D STATEMENT - se hizo un GOTO, GOSUB o RUN a una línea que no existe. VERIFY - el programa en cinta o disco no equivale al programa en la memoria. Parte III a) Sobre el teclado emulado Pulsar HOME pone al cursor arriba en la pantalla, posición esquina izq. Pulsar CLR/HOME hace lo mismo que HOME, pero borrando la pantalla. En el VIC=20 se obtiene pulsando SHIFT + HOME. En el emulador para Spectrum se obtiene pulsando CAPS + SYM + 4 (*) La tecla C= + SHIFT cambia todo cuanto aparece en pantalla de mayúsculas a minúsculas. En el emulador se obtiene mediante CAPS + SYM + C (*). Cuando se está en este modo, se debe pulsar SHIFT más la tecla que se quiera ver en mayúsculas, o saldrá tipeada en minúsculas. En el VIC, la tecla SHIFT imprime el signo gráfico a la derecha en las teclas, mientras C= imprime la de la izq. Pero en la práctica, no ha sido correctamente emulada, así que pulsar SYM + C, equivale al modo E, o sea CAPS + SYM. Lo cual significa que no todos los caracteres gráficos del VIC=20, pueden ser tipeados directamente con el teclado del Spectrum. El único modo es mediante CHR$. Pulsar CAPS + SYM + A (SHIFT + RUN/STOP) automaticamente tipea LOAD y genera un mensaje en espera de que uno pulse PLAY en la grabadora (*). En el VIC real, carga lo primero que encuentre en la cinta. En el emulador se queda esperando. Curiosamente, si se genera un error sintactico, entonces ejecuta (RUN) el programa residente en memoria. En el VIC pulsar RESTORE + RUN/STOP provoca RESET (*). Es decir "restaura" o reactiva el sistema en caso de cuelgue o si se desea interrumpir una ejecución y limpia la pantalla, pero sin borrar el programa en memoria. En el VIC pulsar RESTORE sólo, no parece hacer nada, pero sí la combinación ya mencionada. Posiblemente para evitar que uno resetee por accidente. El VIC permite borrar o insertar espacios entre caracteres, mediante la tecla INS/DEL (*) por insertar/borrar la cual no ha sido emulada, sólo DEL para borrar. (*) NOTA: NO MENCIONADO POR EL AUTOR b) Sobre los colores Al igual que el Spectrum, el VIC=20 tiene colores asociados a las teclas numéricas y se obtienen mediante: CTRL + 1 2 3 4 5 6 7 8 negro blanco rojo cyan purpura verde azul amarillo Tanto el VIC como el Spectrum tienen opciones de cambiar el color de tinta directamente desde el teclado. El Spectrum con las teclas numericas y modo E. El VIC con las teclas numéricas y CTRL. Pero el emulador carece de esta tecla así que es imposible cambiar el color desde el teclado, por lo mismo tampoco hay RVS ON (ctrl+9) y RVS OFF (ctrl+0). El único modo es mediante CHR$: 5 (blanco), 18 (rvs on), 28 (rojo), 30 (verde), 31 (azul), 144 (negro), 146 (rvs off), 156 (purpura), 158 (amarillo), 159 (cian). c)Salvando y cargando datos El programa consta de un cargador BASIC llamado "vic 20", el cual carga varias rutinas en C.M. que son basic2, kernal, chargen, emu, ula2 y ram64. Los cuatro primeros son los únicos que se requieren para un sistema estandar. Es decir, en caso de que uno quisiera pasar el emulador de una cinta a un sistema de discos, ya sea el Discovery, Didaktik, +D, Beta128 ó Microdrive y Wafadrive. El quinto, como su nombre lo indica es en caso de que el sistema incluya el ULA II. Y el último, se carga exclusivamente si se quiere trabajar con un +3 o +2a, para poder explotar otras configuraciones de expansión de RAM o cartuchos de juego. EN SPECTRUM REAL.- si es un Spectrum 48k, podremos ejecutar el programa pero sin sonido a menos que tengamos un AY conectado. En el caso de sistemas de disco o Microdrive, podemos pasar el emulador, pero los programas estarán limitados a unos 6k máximo, encima habrá que tipearlos y luego salvarlos mediante el Multiface (siempre que se tenga uno). Los Didaktik, +D y Beta128, tienen todos su botón mágico para hacer esa tarea. EN SPECTRUM EMULADO.- podemos hacer todo lo antes dicho para el caso de los Spectrum reales, pero además de salvar ficheros SNA, también es posible como dice el autor del emulador, intercambiar archivos binarios con VICE. Luego los podemos pasar a discos físicos y ejecutarlos con Spectrum reales. d) Para cerrar Hasta aquí todo lo referente al emulador Twenty Commodes y el Basic 2.0 del VIC. Lo relacionado a los gráficos, sonido, así como una comparación del VIC, el C=64 y el Spectrum, será tratado con más detenimiento en la segunda parte de este artículo. (c)2018 (2021) zx_if1@hotmail.com