Hablemos de... Beta Basic y como personalizarlo Esta vez quiero compartir mis notas sobre como a~adir o modificar el juego de sentencias y funciones del Beta Basic. La primera parte de este texto es dedicado a traducir info del dr. Wright extraida de sus boletines y la segunda es la dedicada a mis propios experimentos. I - Tomado de los boletines: I.a - A~ADIENDO UN NUEVO COMANDO AL BETABASIC " Hace tiempo recibi la sigte. carta: Hola Andy Cual es la posibilidad de usar los BLANKs (B y H) en BB x.xx para dos comandos INCremento y DECremento? Si, ya puedo oirlo decir: Es tan facil de hacer como una linea como esta: 1 DEF PROC inc REF a: LET a=a+1: END PROC pero para darle un buen uso a un comando como INC no debe tomar mas tiempo para ejecutar que el comando "LET num=num+1" y mis pruebas me muestran que el PROC inc toma cerca de 0.06 mas si el DEF PROC esta al comienzo de un programa y unos 0.08 mas si la definicion esta al final de un programa largo. Supongo que es debido a que el paso de nombres de variables toma algo de tiempo hacerlo. Que me puede decir? Esos comandos ya existen en el Z8O asi que no deberia ser tan dificil implementarlos, o es un error de mi parte? Esperare con mucho gusto su proximo boletin!!! Dan Olsson, Helsingborg, Sweden Bueno, estaba reservando las dos teclas sin usar o tokens para algo realmente importante - y ya no estoy seguro para que! Por el otro lado, la carta de Dan me recordo que algunos lectores podrian estar interesados en a~adir nuevos comandos BB mediante el cod. maquina, en vez de usar procedimientos. La principal ventaja es, claro esta la velocidad. Pasarle variables toma algo de tiempo; en particular porque el Beta Basic esta "injertado" en el Basic del Spectrum, antes que ser una total reescritura. (Y eso nos ahorra mucha RAM!) Voy a describirles como a~adir la instruccion INC de Dan. No es tan simple como Dan supone, ya que el INC del Z8O solo incrementa un registro o una posicion de memoria, mientras que nosotros tenemos que verificar la sintaxis, hallar la variable, quizas dar algun mensaje de error, y alterar dos posiciones de memoria. (Dos pos. de memoria nos permiten tratar con numeros enteros positivos entre 0 y 65535. Las cosas se ponen mas complicadas si queremos INC negativos o en coma flotante.) Todo esto podria usar cientos de bytes si lo escribimo de cero, pero afortunadamente la ROM esta llena de rutinas utiles que nos ayudaran. Si alguien quiere escribir sus propios comandos, seria bueno que consiga la ROM Desensamblada de Ian Logan para que vean como han sido hechas las cosas. (La verdad, mas util y menos tedioso seria tener una lista de unas 2 paginas de las rutinas mas importantes y sus condiciones de entrada y salida- pero no me se de ninguna!) La sintaxis de todas las nuevas palabras clave del Beta Basic esta definida en una tabla en la memoria. El interprete tiene que hallar las entradas sintacticas tan rapido como le sea posible; ya que son de longitud variable, otra tabla (un puntero) es usada para suplir la posicion de cada entrada en la tabla de sintaxis. La forma como esto se hace solo tiene realmente sentido en hexadecimal. La tabla puntero esta en F800H a F824H. La primera entrada es para el comando KEYWORDS (CHR$ 128). El valor del puntero es 25H, y la entrada de sintaxis esta en F800H+25H. La sigte. entrada es para DEF PROC (CHR$ 129); su puntero esta en F801H con 29H, y su entrada de sintaxis en F800H+29H. Cada entrada de sintaxis empieza con uno o mas bytes que especifican el tipo de comando. La ROM usa el mismo sistema. Por ejemplo, un byte de "permite solo el comando, sin parametros" - ejm. CLS o COPY. Un byte 6, seguido de 0, significa "insiste con una expresion numerica sigte." - ejm. BORDER, GOTO o KEYWORDS. Existe tambien un tipo "miscelanea", especificado por un byte 5. Eso significa que el comando mismo debe hacer la verificacion sintactica, debido a que es un caso aislado, antes pertenecer a una clase de comandos. Un ejemplo puede ser DATA o DIM. Luego del byte(s) de tipo hay dos bytes que dan la direccion de la rutina de ese comando, con el byte menos significativo primero segun el modo usual. La palabra reservada BLANK (Grafico-B CHR$ 145) tiene un puntero en F811H y su entrada de sintaxis en F892H (63634 decimal). Su entrada es 5 (tipo miscelanea), seguido de la dir. 7306 decimal. Si tipean RANDOMIZE USR 7306, obtendran un mensaje de error. Esto explica el por que BLANK normalmente no hace nada; el error es generado cuando se intenta tipear ese comando y la linea es rechazada. Si modificamos el byte tipo a cero (POKE 63634,0) un chwequeo de sintaxis se hace a un comando sin parametros y asi se puede tipear BLANK. El error aun es generado cuando uno hace RUN, pero, eso es lo que la dir. 7306 hace. Como sea, no hay un tipo "variable numerica solamente", asi que tenemos que usar un byte tipo 5 (miscellanea) y proveer codigo para chequear su sintaxis. El programa que viene a continuacion hace esto, POKEa el codigo en el area de graficos UDG; deberiamos ponerlo debajo del CODIGO del BB si es que queremos incorporar el comando INC permanentemente. (Ver boletines anteriores sobre este tema.) 10 LET adr=65376 20 POKE 63634,5 30 DPOKE 63635,adr 40 FOR n=adr TO adr+26 50 READ a POKE n,a NEXT n 60 DATA 205,178,40,253 203,1,118,202,138,28,205,238,252,218, 46,28,35,35,35,94,35,86,19,114,43,115,201 A continuacion, la conversion de la linea DATA en len. ensamblador por si estan interesados: CALL LOOK VARS ;chequea: una variable BIT 6,(FLAGS) JP Z,N,NONSENSE_IN_BASIC ;give an error if it is a string CALL CHECK_END ;check this is the statement end. ;Stop here if this is a syntax ;check. JP C,VARIABLE_NOT-FOUND ;error if variable didn't exist. INC HL ;The HL register has been set INC HL ;to point before the variable's INC HL ;value, so advance it. LD E,(HL) ;Get the value into INC HL ;the DE register. LD D,(HL) INC DE ;INC value (or DEC if you want a LD (HL),D ;DEC command) and shove it back DEC HL ;into the variable. LD (HL),E RET Pueden usar las sigtes. lineas para probar el nuevo comando: 70 LET test=0 80 BLANK test 90 PRINT test 100 GO TO 80 El comando aun es BLANK en vez de INC, pero ya vamos a ver eso en un minuto. Este nuevo comando es considerablemente mas rapido que LET test=test+l; pero que tan rapido depende del modo como uno lo mida. Yo use: 10 DPOKE 23672,0: REM usa la variable del sistema FRAMES 20 LET test=0 20 FOR n=1 TO 1000 30 BLANK test 40 NEXT n 50 PRINT DPEEK(23672)/50 Anote el resultado, luego borre la linea 30 y lo ejecute de nuevo para encontrar la diferencia (1.66 s.). Tal vez prefieran 30 REM o 30 (espacio) como la base de su comparacion. Usando: 30 LET test= test+l, menos el tiempo sin la linea 30, da 4.86 s. - asi que INC es casi - veces mas rapido. ******************************************************************** I.b - MODIFICANDO LA PALABRAS RESERVADAS. Continuando con la adicion del comando INC, es necesario modificar la lista de palabras clave para que BLANK (graf. B) aparezca ahora como INC, y se pueda tipear i-n-c. (Beta Basic 3.0 tiene dos BLANK - vamos a alterar solo el primero. Beta Basic 4.0 tiene un END IF a medio implementar asociado a graf. H en lugar del segundo BLANK.) No existen razones para no modificar toda la lista de palabras reservadas, siempre que no sea muy larga. (El programa verifica esto.) Listas similares existen para las funciones numericas y de cadena. Las puedes encontrar con INSTRING y MEMORY$ para alterarlas tanto como puedas - dejo los detalles como ejercicio a los estudiantes! Cada palabra tiene 128 a~adida a su ultima letra. El programa sigte. crea una larga sentencia LET en la linea 110 conteniendo todas las palabras. EDITe esta linea, alterando BLANK a INC, luego RUN 110 para POKEar la nueva lista en memoria. 10 LET a$="110 let a$=""" 20 FOR n=60721 TO 60905 30 LET p=PEEK n 40 IF p>127 THEN LET p=p-128 50 LET a$=a$+CHR$ p 60 IF PEEK n>127 THEN LET a$=a$+"," 70 NEXT n 80 LET a$=a$+"""" 90 KEYIN a$ 100 STOP 120 LET b$="" 130 FOR n=1 TO LEN a$ 140 IF a$(n+l)="," THEN LET b$=b$+CHR$ (CODE a$(n)+128) LET n=n+1 ELSE LET b$=b$+a$(n) 150 NEXT n 160 IF LEN b-$<=185 THEN POKE 60721,b$ ELSE PRINT "Too long by ";LEN b$-185 170 STOP " II - Como modifique mi Beta Basic Y bueno, esa es toda la info que he considerado pertinente al tema que pude encontrar en los boletines del BB, pero que en su momento es decir, fines de los 80 y comienzos de los 90, yo no tuve acceso alguno, por lo que tuve que, por prueba y error, hallar el modo de modificar el BB a mi manera y gusto. Paso 1- PEEKear en la RAM Para ello me vali de un bucle FOR NEXT y PEEK para ver donde se encuentra cada cosa. El bucle original fue: 10 FOR n=RT TO USR "a": REM rt = el inicio en RAM del BB 20 LET p=PEEK n:PRINT n;"/";p, 30 IF p>30 THEN PRINT CHR$ p: ELSE PRINT "???" 40 INPUT; 50 NEXT n Un BB 3.0 sin modificar por ejemplo, empieza en la dir. 47271 y tiene un largo de 18097 de codigo, asi que tras ejecutar mi rutina obtuve las sigtes direcciones: 56664 - 56672 tabla de las letras asociadas a funciones de cadena 56678 - 56694 " " " " " " numericas 56698 - 56739 palabras reservadas de las funciones de cadena 56748 - 56821 " " " " " numericas 60721 - 60905 area de los comandos del BB3 61102 - 61119 variables reservadas error, stat y lino 62043 - 62119 area conteniendo los mensajes de error Muy bien, con esto ya sabia donde POKEar para poder modificar el BB 3 y asi poder personalizarlo a mi gusto, lo que me lleva a... Paso 2- POKEear en la RAM Sabiendo lo que ya se... que cambios podia hacerle a sus tokens? En mi caso, elegi recortar algunas palabras muy largas por otras mas breves, como MEMORY$ por MEM$, TIME$ por TI$, LENGTH e INARRAY por LENG e INARR. Renombrar INSTRING, CHAR$, NUMBER y DPEEK por INSTR, MKI$, CVI y DEEK. Eso para las funciones, en cuanto a las sentencias, las que cambie fueron ALTER, ON ERROR, DEFPROC, DPOKE, PROC, ENDPROC, RENUM, AUTO, DEFKEY, DEFAULT, DELETE, LOCAL, KEYIN, EDIT, JOIN, REF y CSIZE por ALT, ONERR, DEFP, DOKE, P!, ENDP, REN, A!, DEL, LOC, KEY, ED, J!, R! y WIDTH entre otras cosas. Por ultimo las variables ERROR, LINO y STAT decidi darles un nombre mas breve pero reconocible como ERR, ERL y ST. Claro que debido a que LINO es usada tambien por TRACE, no lo hace tan claro pero si cuando es usada en combinacion con ONERR. A continuacion mi peque~a rutina para modificar los tokens: 200 RESTORE 220: FOR n=56712 TO 56732 210 READ m:POKE n,m:NEXT n 220 DATA 77,69,205,83,84,82,73,78,199,84,73,77,197,85,211, 83,72,73,70,212 230 RESTORE 250: FOR n=56761 TO 56807 240 READ m:POKE n,m:NEXT n 250 DATA 70,73,76,204,73,78,83,84,210,76,69,78,199,77,69, 205,78,85,205,79,210,68,69,69,203,82,78,68,205,83,73, 78,197,73,212,73,78,65,82,210,77,79,196,88,79,210 260 RESTORE 280: FOR n=60721 TO 60855 270 READ m:POKE n,m:NEXT n 280 DATA 75,69,89,215,80,82,79,195,80,170,69,78,68,208,82,69, 206,87,73,78,68,79,215,65,170,68,69,204,82,161,74,170,69, 196,75,69,217,76,79,195,68,69,198,75,69,89,196,83,73,90, 197,65,76,212,66,69,71,73,206,67,76,79,67,203,68,207,69, 76,83,197,70,73 290 DATA 76,204,71,69,212,69,78,196,69,88,73,212,87,72,73,76, 197,85,78,84,73,204,76,170,83,79,82,212,79,78,32,69,82, 210,79,208,82,79,76,204,83,67,82,79,76,204,84,82,65,208, 85,83,73,78,199 300 RESTORE 320: FOR n=61102 TO 661114 310 READ m:POKE n,m:NEXT n 320 DATA 69,82,82,61,83,84,65,84,61,69,82,76,61 Paso 3- LEFT$, RIGHT$ y MID$ EN BB? Claro esta que podemos definir estas tres funciones propias del Basic Microsoft como son Left$, Mid$ y Right$ en el Basic Sinclair pero se verian siempre como FN L$, FN M$ y FN R$. No hay forma de verlos como nombres completos. Vamos pues a superar esa limitacion propia del Basic Sinclair y los a~adiremos al BetaBasic mediante... EL TRUCO: 10 POKE 56662,"BCHKMSTUZLNR COPY " 20 POKE 56712,"ME STEP STR DEF FN T<>U OPEN #SHIF CLOSE # LEF CLOSE #MIBIN RIGH CLOSE #FN POP " Nota: excepto las palabras reservadas, todas las definiciones deben ser tipeadas letra a letra, asi el COPY al final de la linea 10 es el token completo COPY y asi con todos los tokens en la linea 20. L, N y R asignan a dichas letras las funciones DE LEFT$, MID$ y RIGHT$ respectivamente. Tuve que elegir N$ para MID$ ya que M$ esta reservado para MEM$. Ahora hay que definirlas como linea 1 y agregarlas a la linea 0 por medio de JOIN y al final deben quedar asi: 0 DEF FN ....: ...: ... DEF FN L$(v$,x)=v$(TO x):DEF FN R$(v$,x)=v$(LEN v$-x+1 TO): DEF FN M$(v$,x,y)=v$(x TO ((x+y-1)AND y>0)+(LEN v$ AND y<1)) Nota: mi version de MID$ permite que la sigte. MID$("MORGAN",4) se pueda tipear pero como FN M$("MORGAN",4,0) y hara lo mismo. Ahora si queremos tambien podemos definir un procedimiento MID para tener el MID$ como comando. Y listo ya tenemos las funciones LEFT$, RIGHT$ y MID$ en Betabasic. Y eso fue todo lo que se me ocurrio hacer entonces por mi cuenta. Ahora si alguien quiere y sabe que o como dotar al BB de un nuevo comando tiene al menos una letra libre en las versiones que agregan ENDIF o dos letras en aquellas que no lo tienen, siguiendo todas las instrucciones del autor del BB en sus boletines. Y PARA CERRAR Actualizando sobre el BB y los sistemas de disco Kempston-dos Finalmente hay emulacion del Kempston-dos y su sistema K-dos, por medio del REAL Spectrum version 16 para Windows, gracias al cual he podido finalmente probar si es compatible o no con el BetaBasic. con BB 1.0 No es compatible para nada, incluso si se logra cargar o pasar a un disco, el BB 1.0 no reconoce los comandos del Kdos. BB 1.8 y 1.9 Se carga de cinta correctamente y acepta los comandos de disco, pero al parecer no es posible copiarlo al disco del modo usual. La copia en disco del BB 1.8 se corrompe y ya no sirve. En cambio, todos los programas que uno crea con el BB si se pueden pasar a disco. Asi que quizas el Multiface 1 modificado para el Kdos sea la unica forma de copiarlo optimamente al disco. Igual con la 1.9. BB 3.0 y 3.1 Pasa lo mismo que con las versiones anteriores, es posible salvarlo a disco pero no cargarlo. Ahora si bien acepta CAT, SAVE y LOAD, no acepta ERASE. Tal es asi que no todos los comandos del Kdos corren cuando se esta en Betabas. Curiosamente si se intenta usar RAND USR 59904 para desactivar el BB y enseguida probar un comando de disco provoca un cuelgue. Tampoco es posible hacer MERGE a un archivo creado con Betabasic, intentarlo genera error de memoria insuficiente, sin espacio en RAM. Y con eso me detengo. (c)2023 zx_if1@hotmail.com