Programar extensiones para el BASIC

Todo sobre la creación, diseño y programación de nuevo software para
nuestro Spectrum

Moderador: Sir Cilve Sinclair

Avatar de Usuario
mcleod_ideafix
Johnny Jones
Mensajes: 3985
Registrado: Vie Sep 21, 2007 1:26 am
Ubicación: Jerez de la Frontera
Contactar:

Programar extensiones para el BASIC

Mensaje por mcleod_ideafix » Mar Dic 02, 2008 2:55 pm

¿Conocéis algún libro (escaneado), tutorial, web, etc. que enseñe cómo escribir extensiones al BASIC del Spectrum? Es decir, cómo hacer para poder escribir extensiones que permitan escribir comandos BASIC "extendidos" tales como LOAD %"programa" o cosas así.

Sé que todo comienza por trapear la RST 8, lo que implica usar una ROM alternativa que se mapee cuando ocurra esto. ¿Y después? He leído hace tiempo sobre usar ciertas rutinas de la ROM para ir parseando la línea de comandos, meter en pila los valores según sean numéricos, alfanuméricos, etc. pero lo tengo todo muy difuso y es por lo que estoy buscando esta información.

También sé que se usa el área de canales, para que cuando se hace OPEN # se asigna un nuevo canal, y con él, las direcciones de lectura y escritura para ese canal, pero no sé qué más hace falta para poder usarlos. Es decir, no sé qué argumentos se espera que recojan esas rutinas de lectura/escritura y qué deben devolver.

Gracias :)
Web: ZX Projects | Twitter: @zxprojects

Avatar de Usuario
na_th_an
Nonamed
Mensajes: 1889
Registrado: Lun May 07, 2007 10:16 am
Ubicación: Andalucía

Re: Programar extensiones para el BASIC

Mensaje por na_th_an » Mar Dic 02, 2008 3:47 pm

Mira esta página y las siguientes: http://microhobby.speccy.cz/mhf/MHEs4/mhes4_45.jpg

Aquí se proponen comandos para extender el BASIC, y además se explica cómo se añaden.

Avatar de Usuario
mcleod_ideafix
Johnny Jones
Mensajes: 3985
Registrado: Vie Sep 21, 2007 1:26 am
Ubicación: Jerez de la Frontera
Contactar:

Re: Programar extensiones para el BASIC

Mensaje por mcleod_ideafix » Mar Dic 02, 2008 3:51 pm

Gracias!!!!! :)
Web: ZX Projects | Twitter: @zxprojects

Avatar de Usuario
Rafa
Jack The Nipper
Mensajes: 181
Registrado: Lun May 07, 2007 11:59 am

Re: Programar extensiones para el BASIC

Mensaje por Rafa » Mié Dic 03, 2008 8:46 pm

Esto está bien, pero veo más fácil hacer esto:

100 RANDOMIZE USR 64000: REM &MOVESPRITE(10,0)

La rutina ubicada en 64000 leería qué instrucción hay detrás del REM, y saltar a la correspondiente dirección donde estaría ubicada la rutina correspondiente. Además como los números y/o cadenas se almacenan detrás de un REM como modo texto, no haría falta usar el calculador de la ROM, ni números en coma flotante. Esto yo lo veo más rápido y valdría para los Spectrums originales.

La información de referencia para saber cómo "incrustar" nuevos comandos utilizando el editor de la ROM en "la Enciclopedia" del Spectrum está en el libro "The Complete Rom Dissassembly". Es increíble las virguerías que hizo tio Clive para meter todo el sistema operativo del Spectrum en sólo 16K, para ahorrar costes. Pero vamos, todo se basa en el uso del Stack y saber exactamente cúal es el último valor introducido en el stack.

Están los canales, el calculador de la ROM (lento y lioso), la configuración de pantalla, ...
RANDOMIZE USR 0

Gandulf
Nonamed
Mensajes: 1067
Registrado: Lun May 07, 2007 10:06 pm

Re: Programar extensiones para el BASIC

Mensaje por Gandulf » Jue Dic 04, 2008 11:52 am

@Rafa:Esto yo lo veo más rápido y valdría para los Spectrums originales.

¿Que quiere decir spectrums originales? El método descrito en la microhobby funciona lógicamente en un spectrum sin modificar, no entiendo lo que quieres decir con esto :?: :?: :?:

Por otra parte veo mucho más legible y cómodo el método descrito en la microhobby, amén de que los programas ocuparían menos, ya que con tu método cualquier comando tiene que ir precedido de un randomize usr <dirección> y luego un REM, si es un programa largo con muchas líneas y muchas llamadas a las extensiones del basic quedaría el programa super ilegible y realmente largo.
Un saludo,

Gandulf

Avatar de Usuario
mcleod_ideafix
Johnny Jones
Mensajes: 3985
Registrado: Vie Sep 21, 2007 1:26 am
Ubicación: Jerez de la Frontera
Contactar:

Re: Programar extensiones para el BASIC

Mensaje por mcleod_ideafix » Jue Dic 04, 2008 4:41 pm

Rafa escribió:100 RANDOMIZE USR 64000: REM &MOVESPRITE(10,0)
La rutina ubicada en 64000 leería qué instrucción hay detrás del REM, y saltar a la correspondiente dirección donde estaría ubicada la rutina correspondiente. Además como los números y/o cadenas se almacenan detrás de un REM como modo texto, no haría falta usar el calculador de la ROM, ni números en coma flotante. Esto yo lo veo más rápido y valdría para los Spectrums originales.

El método de Microhobby, como señala Gandulf, funciona sin problemas en los Spectrums originales, además de ser más legible. Pero es que además, la presunta ventaja de tener todo el comando almacenado como "sólo texto" se torna un gran inconveniente cuando lo que necesitas es, de hecho, que el calculador de la ROM use su evaluador de expresiones para que puedas usar cosas como MOVESPRITE(fila+2*x,col+y)

De todas formas, lo que quería conocer es el mecanismo para acceder desde el ejecutor de BASIC a la línea actual y, bueno, lo que es el parser, ya que esto es para escribir una rutina que estaría en una shadow-ROM al estilo del interface 1, que se paginara automáticamente al ejecutarse un RST 8. Los nuevos comandos que quisiera implementar quiero que estén disponibles tanto desde BASIC como desde C/M usando hooks al estilo del mencionado Interface 1.

Por cierto: me da a mi que el artículo de Microhobby se basa en una rutina que no ha escrito el que ha hecho el artículo: el código fuente no está para nada documentado, no hay etiquetas en las subrutinas que llaman a la ROM, y las etiquetas de saltos son sospechosamente "automáticas", como BUCLE1, BUCLE2, DATA1, DATA2... Vamos, que parece que tenían el código objeto, lo han desensamblado así como han podido, y en el artículo sólo hablan muy claramente de cómo se actualiza la variable del sistema de marras (23613), pero muy poco sobre cómo funciona el parseo interno de las nuevas instrucciones; señal de que no han estudiado ese código a fondo, o ni siquiera se han molestado en ello.

Rafa escribió:Están los canales, el calculador de la ROM (lento y lioso), la configuración de pantalla, ...

Lento quizás, pero.... ¿lioso? No es más que un intérprete de FORTH. Es muy versátil, la verdad, y de hecho, el coprocesador matemáticos de los PC's usa un método similar.

Y sí que el Complete Spectrum..... es LA referencia, pero eso te vale cuando ya sabes dónde mirar, y qué ejecutar, y necesitas algún detalle. De otra forma, yo al menos me pierdo con las rutinas del ejecutivo BASIC. Supongo que será cuestión de leérselo más detenidamente.

Si tengo tiempo, me imprimo una copia, la encuaderno, y me la voy leyendo :)
Web: ZX Projects | Twitter: @zxprojects

Avatar de Usuario
Rafa
Jack The Nipper
Mensajes: 181
Registrado: Lun May 07, 2007 11:59 am

Re: Programar extensiones para el BASIC

Mensaje por Rafa » Jue Dic 04, 2008 9:21 pm

Gracias por decirme que sí a un punto... de verdad, estoy adulado.

mcleod_ideafix escribió:El método de Microhobby, como señala Gandulf, funciona sin problemas en los Spectrums originales, además de ser más legible


Creo que fuiste tú quien dijo que " lo que implica usar una ROM alternativa que se mapee". ¿Y eso de mapear una ROM alternativa sirve para un Spectrum original normal (no emulador)?

Para acceder a una línea determinada y ejecutarla, hay que pokear en las variables de sistema que llevan el número de línea actual y el número de sentencia dentro de la línea. Después yo saltaría a la dirección donde empieza el GOTO en la ROM, seteando el bit 5 de FLAGSX para que ejecute y no edite. Creo que es así. Bien enfocado con un solo CALL puedes ejecutar (si quieres) una sola línea, porque al encontrar el retorno de carro o fin de línea, retorna.

EL tema del evaluador de expresiones, usa preferencias, prevee paréntesis, de verdad, yo he estudiado la rutina (se llama SCANNING, dirección hex 24BF), para mí es un prodigio de la sintetización en programación y prevee todos los casos posibles. En el libro explican que sólo tiene un fallo, y es que la rutina se encuentre con el número -65536 (tio Clive lo arregló con otra rutina aparte).

Yo tengo el libro en formato original (en inglés) y de verdad tendrás lectura para meses, tratando de comprender los métodos que usa, todo en aras en ahorro de memoria (aunque al final le sobra poco más de 1K).

Si pudiera comprender el funcionamiento de SCANNING, de ahí al compilador Basic perfecto un paso. Velocidad casi C/M, el consumo de memoria muy pequeño... pero sobre todo la velocidad.
RANDOMIZE USR 0

Avatar de Usuario
mcleod_ideafix
Johnny Jones
Mensajes: 3985
Registrado: Vie Sep 21, 2007 1:26 am
Ubicación: Jerez de la Frontera
Contactar:

Re: Programar extensiones para el BASIC

Mensaje por mcleod_ideafix » Vie Dic 05, 2008 3:57 am

Rafa escribió:Gracias por decirme que sí a un punto... de verdad, estoy adulado.

mcleod_ideafix escribió:El método de Microhobby, como señala Gandulf, funciona sin problemas en los Spectrums originales, además de ser más legible


Creo que fuiste tú quien dijo que " lo que implica usar una ROM alternativa que se mapee". ¿Y eso de mapear una ROM alternativa sirve para un Spectrum original normal (no emulador)?


Sí, porque lo que quiero hacer es un programa, pero que se ejecutará no como la rutina de Microhobby, sino como parte de un firmware para DivIDE, y éste mapea su ROM cuando se ejecuta una RST 8, lo mismo que el Interface 1. Por eso pensé que "todo" empezaba por ahí, por RST 8. El artículo de Microhobby aporta un enfoque que desconocía: usar ERR SP para alterar la dirección a ejecutar cuando ocurre un error.
Mapear una ROM alternativa (o una ROM shadow, como quieras llamarlo) se lleva haciendo en el Spectrum desde la aparición del Interface 1. En mi caso, como digo, usaré el DivIDE.

mcleod_ideafix escribió:EL tema del evaluador de expresiones, usa preferencias, prevee paréntesis, de verdad, yo he estudiado la rutina (se llama SCANNING, dirección hex 24BF), para mí es un prodigio de la sintetización en programación y prevee todos los casos posibles. En el libro explican que sólo tiene un fallo, y es que la rutina se encuentre con el número -65536 (tio Clive lo arregló con otra rutina aparte).

Yo tengo el libro en formato original (en inglés) y de verdad tendrás lectura para meses, tratando de comprender los métodos que usa, todo en aras en ahorro de memoria (aunque al final le sobra poco más de 1K).


Yo también he llegado a SCANNING traceando el código de la ROM. De todas formas, sospecho que no hará falta usarla "a pelo". Hay unas rutinas, mencionadas en las tablas de comandos, que me permiten, dependiendo de la clase de comando que sea, hacer chequeos de sintaxis y demás. De todas formas, si hay que mirarse SCANNING, pues se mira :)

mcleod_ideafix escribió:Si pudiera comprender el funcionamiento de SCANNING, de ahí al compilador Basic perfecto un paso. Velocidad casi C/M, el consumo de memoria muy pequeño... pero sobre todo la velocidad.

En un compilador no te vale el evaluador de expresiones del Spectrum, ya que la gracia de la compilación es realizar esa evaluación en tiempo de compilación, y generar código máquina con las instrucciones necesarias para remedar esa expresión. Te sale más a cuenta escribir un evaluador de expresiones para compilador desde 0, usando lex, yacc, etc.
Web: ZX Projects | Twitter: @zxprojects

Avatar de Usuario
mcleod_ideafix
Johnny Jones
Mensajes: 3985
Registrado: Vie Sep 21, 2007 1:26 am
Ubicación: Jerez de la Frontera
Contactar:

Re: Programar extensiones para el BASIC

Mensaje por mcleod_ideafix » Vie Dic 05, 2008 6:04 am

Bueno, pues esta es mi primera tontería con SCANNING :D

Código: Seleccionar todo

PRINT_FP        equ 2de3h
SCANNING        equ 24fbh
CHAN_OPEN       equ 1601h

                org 32768

Main            proc
                ld hl,(5c5dh)   ;guardo CD_ADD
                push hl         ;en pila, para restaurarlo después
                ld hl,Expresion
                ld (5c5dh),hl   ;apunto CH_ADD a mi expresión a evaluar
                set 7,(iy+1)    ;FLAGS en modo ejecución (evaluación)
                call SCANNING
                ld a,2
                call CHAN_OPEN  ;abrir canal S para imprimir
                call PRINT_FP   ;imprimimos el resultado
                pop hl
                ld (5c5dh),hl   ;restauramos CH_ADD
                ret
                endp

Expresion       db "16",14,0,0,16,0,0,"+16",14,0,0,16,0,0,13,128

                end Main

La expresión tiene ya añadidos los números en notación de "coma flotante escondida" que usa el Spectrum, es decir, justo después de cada literal numérico se almacena el 14 (indicativo de "número") seguidos de los 5 bytes que codifican un número en el Spectrum, sea real o entero. En este caso, los números son enteros, lo que simplifica la codificación :D

Esto de añadir la versión "escondida" del número dentro de la expresión lo realiza automáticamente la rutina SCANNING cuando se ejecuta en modo "chequeo de sintaxis". Esto lo hace la ROM del Spectrum cuando tecleamos una línea de programa y pulsamos ENTER. Así, cuando esa línea se ejecuta, no hay que volver a generar el número en notación de coma flotante cada vez, sino que se coge la versión que dejó allí "preparada" el chequeador de sintaxis. De esto se encarga una parte de SCANNING, la rutina S-DECIMAL:

Código: Seleccionar todo

; This important routine is called during runtime and from LINE-SCAN
; when a BASIC line is checked for syntax. It is this routine that
; inserts, during syntax checking, the invisible floating point numbers
; after the numeric expression. During runtime it just picks these
; numbers up. It also handles BIN format numbers.

; ->
;; S-BIN
;; S-DECIMAL

Por tanto, para poder saltarnos la fase de chequeo de sintaxis, y dado que SCANNING necesita esa representación interna, la he añadido "a pelo" en la expresión, que pasa de ser 16+16 a ser 16(version interna de 16)+16(version interna de 16), es decir:

Código: Seleccionar todo

Expresion       db "16",14,0,0,16,0,0,"+16",14,0,0,16,0,0,13,128

Y por último, uso el 13 y el 128 para indicar fin de expresión (creo que bastaría con uno de los dos).

SCANNING, como usa el calculador de la ROM, deja su resultado en lo alto del stack. Aquí estoy asumiendo que dicho resultado va a ser numérico (esto se comprueba con el bit 6 de FLAGS, que si es 1 significa que el resultado es numérico, y si es 0, es alfanumérico). Entonces, sólo me falta hacer algo con ese resultado, por ejemplo, imprimirlo con PRINT-FP.

Me queda cambiar el programa para que chequee sintaxis y evalue la expresión, así puedo codificar la expresión de la forma habitual: "16+16" por ejemplo. Miraré a ver cómo se ejecuta la función VAL, que tiene toda la pinta de ser lo que necesito :D He intentado hacerlo tal cual, chequeando la sintaxis de la expresión, pero parece que la rutinilla que inserta el número "escondido" no funciona bien si la expresión está más allá de STKEND, ya que hace uso de MAKE-ROOM y otras, que sólo funcionan bien (eso parece) en zonas de memoria por debajo de STKEND.

Es por esto de la necesidad de chequear la sintaxis, que no convendría usar lo de "RAND USR 64000: REM sentencia nueva", ya que esa sentencia nueva tendría que ser chequeada en sintaxis y evaluada cada vez que se ejecutara, en lugar de sólo evaluarse.

NOTA: ¿será posible? ¿¿Pues no acabo de descubrir que las variables en BASIC pueden contener espacios??

Código: Seleccionar todo

; -----------------
; THE 'LET' COMMAND
; -----------------
; Sinclair BASIC adheres to the ANSI-78 standard and a LET is required in
; assignments e.g. LET a = 1  :   LET h$ = "hat".
;
; Long names may contain spaces but not colour controls (when assigned).
; a substring can appear to the left of the equals sign.


Vamos, que un LET esto es una variable = 4 funciona!! y el correspondiente PRINT esto es una variable también funciona. Ahora acabo de comprobar que realmente esto se dice en el apéndice C del manual de BASIC, si bien lo que dice expresamente es que los espacios en blanco se ignoran cuando se crea la variable, o cuando se usa. O sea, que realmente PRINT estoesunavariable también funciona. Curioso :)
Web: ZX Projects | Twitter: @zxprojects

Avatar de Usuario
mcleod_ideafix
Johnny Jones
Mensajes: 3985
Registrado: Vie Sep 21, 2007 1:26 am
Ubicación: Jerez de la Frontera
Contactar:

Re: Programar extensiones para el BASIC

Mensaje por mcleod_ideafix » Vie Dic 05, 2008 6:44 am

Segunda tontería con SCANNING:

Código: Seleccionar todo

PRINT_FP        equ 2de3h
SCANNING        equ 24fbh
CHAN_OPEN       equ 1601h
CH_ADD          equ 5c5dh

                org 32768

Main            proc
                ld hl,(CH_ADD)  ;guardo CD_ADD
                push hl         ;en pila, para restaurarlo después
;------------------------------------------------------------------------------
                ld bc,LongExpr
                rst 30h         ;abro un hueco en el área de trabajo. Inicio del hueco abierto en DE
                ld (CH_ADD),de  ;apunto CH_ADD a la expresion, que copiaré al hueco abierto
                push de         ;Guardo la dirección de inicio al hueco
                ld hl,Expresion ;Copio mi expresión...
                ldir            ;...al hueco abierto en el área de trabajo
                res 7,(iy+1)    ;primero señalizamos que queremos chequear la sintaxis
                call SCANNING   ;llamada a scanning para chequear sintaxis y construir los valores ocultos en punto flotante.
                pop hl          ;recuperamos el puntero al inicio al hueco (expresión ya chequeada en sintaxis)
;------------------------------------------------------------------------------
                ld (CH_ADD),hl  ;apunto CH_ADD a mi expresión a evaluar
                set 7,(iy+1)    ;ya está chequeado, ahora ponemos FLAGS en modo ejecución (evaluación)
                call SCANNING   ;evaluo la expresión: resultado en el stack del calculador

                ld a,2
                call CHAN_OPEN  ;abrir canal S para imprimir
                call PRINT_FP   ;imprimimos lo que haya en la cima del stack del calculador.

                pop hl
                ld (5c5dh),hl   ;restauramos CH_ADD
                ret
                endp

Expresion       db "1+2*3/4",13
LongExpr        equ $-Expresion

                end Main


Ahora sí: la expresión se copia al área de trabajo, se chequea en sintaxis y se evalúa. Lo bueno de esto es que la primera parte, el chequeo de sintaxis (lo que está enmarcado entre líneas), sólo necesito hacerlo una vez. Después de eso, puedo evaluar la expresión cuantas veces quiera. Si en la expresión hay variables, pues tendré un valor distinto en función del valor de esas variables. A ver si tengo un ratito más y hago otro ejemplo más elaborado...
Web: ZX Projects | Twitter: @zxprojects

Avatar de Usuario
mcleod_ideafix
Johnny Jones
Mensajes: 3985
Registrado: Vie Sep 21, 2007 1:26 am
Ubicación: Jerez de la Frontera
Contactar:

Re: Programar extensiones para el BASIC

Mensaje por mcleod_ideafix » Vie Dic 05, 2008 7:39 am

Y tercera tontería con SCANNING

Código: Seleccionar todo

;Rutinas ROM
PRINT_FP        equ 2de3h
SCANNING        equ 24fbh
CHAN_OPEN       equ 1601h
CLS             equ 0d6bh
PLOT_CB         equ 22e5h
STK_TO_A        equ 2314h

;Variables del sistema
CH_ADD          equ 5c5dh

;Tokens para la expresión
SIN             equ 178


                org 32768

Main            proc
                ld hl,(CH_ADD)  ;guardo CD_ADD
                push hl         ;en pila, para restaurarlo después

                ld bc,LongExpr
                rst 30h         ;abro un hueco en el área de trabajo. Inicio del hueco abierto en DE
                ld (CH_ADD),de  ;apunto CH_ADD a la expresion, que copiaré al hueco abierto
                push de         ;Guardo la dirección de inicio al hueco
                ld hl,Expresion ;Copio mi expresión...
                ldir            ;...al hueco abierto en el área de trabajo
                res 7,(iy+1)    ;primero señalizamos que queremos chequear la sintaxis
                call SCANNING   ;llamada a scanning para chequear sintaxis y construir los valores ocultos en punto flotante.

                pop hl          ;recuperamos el puntero al inicio al hueco (expresión ya chequeada en sintaxis)
                ld de,ExpresionCheq   ;Este bucle copia la expresión chequeada desde el área de trabajo hasta ExpresionCheq, hasta encontrar un retorno de carro
BucCopia        ld a,(hl)
                ld (de),a
                inc hl
                inc de
                cp 13
                jr nz,BucCopia

                call CLS
                set 7,(iy+1)    ;ya está chequeado, ahora ponemos FLAGS en modo ejecución (evaluación)

                ld c,0          ;C será la coordenada X, desde 0 a 255
BucPlot         push bc
                ld ix,ExpresionCheq
                ld (ix+24),c    ;Aquí parcheamos la expresión para que el 0 se convierta en el valor de C
                ld (CH_ADD),ix  ;apunto CH_ADD a mi expresión a evaluar
                call SCANNING   ;evaluo la expresión: resultado en el stack del calculador
                call STK_TO_A   ;resultado a A
                pop bc
                ld b,a          ;que es nuestra coordenada Y
                push bc
                call PLOT_CB    ;punto el puntito en coordenadas C,B
                pop bc
                inc c
                jr nz,BucPlot

                pop hl
                ld (5c5dh),hl   ;restauramos CH_ADD
                ret
                endp

Expresion       db "88+80*",SIN,"(0*0.02463994238)",13
LongExpr        equ $-Expresion
ExpresionCheq   ds 128   ;128 bytes para guardar la expresión ya chequeada en sintaxis

                end Main


Bueno, no sirve de mucho, excepto para probar lo obvio, que el C/M es más rápido que el BASIC, aunque el 90% del tiempo de ejecución se realiza en las mismas rutinas de la ROM que se usan durante la interpretación del BASIC.

Un pequeño benchmark podría ser éste:
Imagen

Cuyo resultado es:
Imagen

Los casi dos segundos que se ganan son porque en C/M no se pierde tiempo interpretando el bucle, y la expresión no tiene que buscar el valor de ninguna variable durante su evaluación, sino que lo parcheo directamente en el número "escondido" que SCANNING genera para el 0 que aparece en la expresión: al ser un entero positivo que cabe en un byte, el parcheo es directamente al byte menos significativo de la representación en complemento a 2 del número en cuestión.

Supón que PLOT no existiera en el BASIC del Spectrum y quisiéramos incluirla con algo así:

Código: Seleccionar todo

RANDOMIZE USR 64000: REM PLOT n,88+80*SIN (n*0.02463994238)


Como lo que hay tras el REM no se evalua en sintaxis, en ejecución habría que usar SCANNING dos veces con cada expresión: una para chequearla en sintaxis y generar los números "escondidos" en el área de trabajo, y otra para la evaluación, propiamente dicha. ¡Sería casi el doble de lenta!
Web: ZX Projects | Twitter: @zxprojects

Avatar de Usuario
mcleod_ideafix
Johnny Jones
Mensajes: 3985
Registrado: Vie Sep 21, 2007 1:26 am
Ubicación: Jerez de la Frontera
Contactar:

Re: Programar extensiones para el BASIC

Mensaje por mcleod_ideafix » Vie Dic 05, 2008 10:00 am

Y ya, la prueba definitiva.

Usando el método de Rafa, que ciertamente es el más sencillo de implementar, he hecho como si no existiera la orden PLOT en BASIC, y la he implementado así:

Código: Seleccionar todo

RANDOMIZE USR 64000: REM: PLOT a,b

Donde a,b son los dos parámetros del PLOT, que por supuesto, pueden ser cualesquiera dos expresiones numéricas.

Este es el código. Como REM no chequea sintaxis, he de hacerlo en tiempo de ejecución, llamando a EXPT_2NUM dos veces. EXPT_2NUM es una rutina de la ROM que se encarga de comprobar (en modo chequeo de sintaxis) o evaluar (en modo ejecución) un bloque de dos parámetros numéricos separados por una coma.

Para ello, copio el bloque de parámetros a un área del espacio de trabajo. Podría hacer el chequeo en la misma línea del programa, pero eso significaría que la siguiente vez que pasara por ahí, el chequeo de sintaxis fallaría, al encontrarse los números ocultos que se pusieron la primera vez (NOTA MENTAL: esto me da una idea para mejorar el algoritmo, dejando una marca para indicar que ya he chequeado la sintaxis).

Después de copiar al área de trabajo, es ahí donde hago primero el chequeo sintáctico y luego la evaluación de parámetros. Recojo los resultados usando STACK_TO_BC y seguidamente, llamada a PLOT para pintar el puntito.

Código: Seleccionar todo

;Implementación de nuevos comandos usando REM

;Rutinas ROM
SCANNING        equ 24fbh
EXPT_2NUM       equ 1c7ah
PLOT_CB         equ 22e5h
STK_TO_A        equ 2314h
STK_TO_BC       equ 2307h

;Variables del sistema
CH_ADD          equ 5c5dh

;Tokens
REM             equ 234
PLOT            equ 246
                org 64000

Main            proc
                ld hl,(CH_ADD)    ;Guardamos CH_ADD
                push hl

                rst 18h         ;token/carácter presente
                cp ":"          ;Deben ser los dos puntitos
                jr nz,Fin       ;Si no, fuera
                rst 20h
                cp REM          ;El próximo debe ser un REM
                jr nz,Fin
                rst 20h
                cp ":"          ;El próximo, otros dos puntitos
                jr nz,Fin
                rst 20h         ;Y el próximo ya es nuestro comando!!!
                cp PLOT         ;Aquí habría que preguntar cuál de ellos es, pero como sólo tenemos uno...
                jr nz,Fin       ;...si no es ese, pues nada, no se hace nada.
                rst 20h         ;Apuntamos al bloque de parámetros

                ;Procesamiento del comando PLOT. Necesitamos dos parámetros numéricos separados por coma.
                push hl         ;Guardamos inicio del bloque de parámetros
                ld bc,0
                ;Miramos cuánto ocupan los dos parámetros (hasta encontrar un retorno de carro o un ":")
CheckLong       ld a,(hl)
                inc bc
                inc hl
                cp 13
                jr z,FinLong
                cp ":"
                jr z,FinLong
                jr CheckLong

FinLong         rst 30h     ;Abro un hueco en el espacio de trabajo para los parámetros. Inicio del hueco en DE
                pop hl
                push de     ;Guardo inicio del bloque de par. en el área de trabajo
                ldir        ;Copio bloque de parámetros

                pop de
                push de
                ld (CH_ADD),de   ;CH_ADD apunta a nuestro bloque de parámetros copiado al espacio de trabajo
                res 7,(iy+1)     ;Señalamos que vamos a chequear sintaxis
                call EXPT_2NUM   ;Chequeamos sintaxis de dos parámetros numéricos separados por una coma

                pop de
                ld (CH_ADD),de   ;restauramos CH_ADD de nuevo al principio de nuestros dos parámetros
                set 7,(iy+1)     ;Señalamos que vamos a evaluar las dos expresiones
                call EXPT_2NUM   ;Evaluamos las dos expresiones, dejando el resultado en las dos últimas posiciones del stack

                call STK_TO_BC   ;Los dos resultados numéricos, a BC
                call PLOT_CB     ;y hacemos el PLOT

Fin             pop hl
                ld (CH_ADD),hl
                ret
                endp

                end


El benchmark para comprobar la velocidad de ejecución de este "comando extendido", respecto del original, es éste:
Imagen

Y los resultados:
Imagen

Donde se observa que la penalidad por tener que chequear sintaxis en tiempo de ejecución hace que la versión con REM tarde 1,6 veces más tiempo que la original.

Ah! Como imaginaba al empezar a leer el desensamble de la ROM, no es necesario, en la mayoría de los casos, llamar directamente a SCANNING, sino que puedo usar las rutinillas auxiliares como EXPT_2NUM se encargan de llamar a SCANNING todas las veces que haga falta y además chequear que los parámetros están separados por coma, etc.

Voy a probar con la modificación para que chequee la sintaxis sólo una vez, a ver si me sale...

Pues va a ser que no me sale: parece que al editor del BASIC, y al propio intérprete, no le gusta nada que dentro del texto del REM haya cosas no legibles. En fin, luego probaré la versión que realmente quiero hacer, sin el REM.
Web: ZX Projects | Twitter: @zxprojects

Avatar de Usuario
Rafa
Jack The Nipper
Mensajes: 181
Registrado: Lun May 07, 2007 11:59 am

Re: Programar extensiones para el BASIC

Mensaje por Rafa » Vie Dic 05, 2008 12:10 pm

Para no gastar tiempo en chequear sintaxis, lo mejor es no hacer un chequeo de sintaxis, o sea PRESUPONER que va a estar bien tecleado
RANDOMIZE USR 0

Avatar de Usuario
mcleod_ideafix
Johnny Jones
Mensajes: 3985
Registrado: Vie Sep 21, 2007 1:26 am
Ubicación: Jerez de la Frontera
Contactar:

Re: Programar extensiones para el BASIC

Mensaje por mcleod_ideafix » Vie Dic 05, 2008 12:17 pm

No es suficiente. El chequeo de sintaxis además construye la versión "escondida" de cada número que aparece en la expresión, y que necesita el evaluador (lee el post "primera tontería con SCANNING"), con lo que sigue siendo necesario... a menos que en tu expresión no haya ni una sola constante, sino que todo sean variables, o bien que a mano calcules los valores "escondidos", que es lo que hago precisamente en lo que llamo "tontería 1 con SCANNING".

Lo malo es que ese precálculo "a mano" de los números escondidos hay que hacerlo antes o después, y si no se hace cuando la línea se añade al programa BASIC (lo habitual), entonces habrá que hacerlo cuando se ejecute (que es lo que tengo que hacer en la última versión del programa).
Web: ZX Projects | Twitter: @zxprojects

Avatar de Usuario
winston
Sabreman
Mensajes: 469
Registrado: Mar Ago 19, 2008 4:17 pm
Ubicación: Isla de Man
Contactar:

Re: Programar extensiones para el BASIC

Mensaje por winston » Mar Dic 09, 2008 6:06 pm

mcleod_ideafix escribió:Sí, porque lo que quiero hacer es un programa, pero que se ejecutará no como la rutina de Microhobby, sino como parte de un firmware para DivIDE, y éste mapea su ROM cuando se ejecuta una RST 8, lo mismo que el Interface 1.


Ya he hecho esto para el Spectranet. Aquí está el codigo fuente que puede ser modificado para otro hardware:

http://spectrum.alioth.net/svn/filedeta ... icextn.asm

Esta página muestra cómo puedes usar (en inglés)

http://spectrum.alioth.net/doc/index.ph ... Tutorial_6

...incluyedo cómo analizar sintácticamente los variables etc.

Lo he hecho con mucha ayuda desde el "Complete Shadow ROM Disassembly" para el Interface 1, y ayuda de Garry Lancaster, quien explicó el evaluador de expresiones.
Tarjeta ethernet para el Spectrum - http://spectrum.alioth.net/doc

Debemos practicar un quirkafleeg

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: Ahrefs [Bot] y 23 invitados