Jupiter Ace Forth: Copia del Búfer de Entrada

Elurdio
Mensajes: 311
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 74 veces
Agradecimiento recibido: 76 veces

Jupiter Ace Forth: Copia del Búfer de Entrada

Mensajepor Elurdio » 30 Abr 2022 16:51

.
He hecho una rutina en código máquina para disponer de una copia del último contenido del Búfer de Entrada.

USO

Para recuperar la copia basta pulsar simultáneamente las teclas Z y X (son las que he escogido, podría haber sido cualquier otro par de teclas con tal que pulsadas simultáneamente no generen ningún carácter)

Cada vez que se pulsa la tecla ENTER estando en el Búfer de Entrada Inicial se guarda automáticamente una copia de su contenido. Más adelante, si pulsamos las teclas Z y X simultáneamente "estando en el Búfer de Entrada Inicial, se repone el contenido anterior (el actual se pierde).

Cuando digo "Búfer de Entrada Inicial" (aka BEI) me refiero al por defecto del JA. No sirven ni el Búfer de Entrada de Edición ni los generados por palabras como QUERY, RETYPE, etc.

Concretamente, si cometemos un error que el JA te permite corregir (cuando se pone el "?" en video inverso al principio) este contenido no se guarda al pulsar ENTER con lo que se mantiene el anterior contenido salvado.

Si usamos EDIT tampoco salva nada, ni es necesario, pues si abortamos la edición de una palabra, siempre podemos volverla a Editar.

Es útil cuando estamos trabajando en modo interactivo. Pues nos permite recuperar una línea (o parrafada) de comandos y volverlos a ejecutar (iguales o modificados).

También es útil si estamos definiendo una palabra nueva y tras escribirla de una tangada, al entrarla se genera un ERROR 5 (estructuras mal puestas como por ejemplo olvidarnos el THEN de un IF anterior o el LOOP de un DO, etc) pues en este caso tendríamos que volver a escribirlo todo desde el principio. Ahora basta con pulsar Z+X y recuperamos todo.

Si pulsamos ENTER con el BEI vacío, se pierdo lo guardado pues siempre se guarda el último contenido del BEI al pulsar el ENTER y en este caso es un espacio en blanco.

REQUISITOS

Tal como lo he programado (se puede modificar) espera un JA con 48K de memoria extra (64 en total: ROM+RAM).
En mi caso he usado el emulador EightyOne versión 1.28 pues con otras más antiguas (como la 1.23) no me funcionó.
Se reserva cerca de 1KB de la memoria superior (Desde $FC20 hasta $FFFF) de los cuales 734 son espacio para almacenar el BEI (734 es el tamaño máximo posible)

Incluyo un diccionario llamado oldbuff.tzx que contiene tres palabras:

  • LIMIT que reserva la zona de memoria superior desde $FC20 hasta $FFFF ambos incluidos
  • PUTBUFF que carga y arranca la rutina guardada en el PF de SAVEBUFF
  • SAVEBUFF es una palabra tipo CREATE que almacena la rutina en código máquina en su PF.

INSTALACION y Puesta en Marcha

  1. Ejecutar LIMIT
  2. Ejecutar PUTBUFF
  3. (opcional) FORGET SAVEBUFF para borrar estas tres palabras (una vez arrancada la rutina ya no hacen falta)

Se han de ejecutar por separado LIMIT y PUTBUFF, pues LIMIT realiza internamente un QUIT necesario para que entre en vigor el RAMTOP (límite de memoria usable) y esto provoca que cualquier palabra que venga después no se ejecute.

FUNDAMENTO

Al arrancar la rutina se pone el JA en modo de Interrupción 2 (ver hilo Jupiter Ace Interrupción Modo 2) apuntando a la rutina que llamaré "Linicio" (es la etiqueta dónde empieza en el código fuente correspondiente). Así esta rutina se ejecuta 50 veces por segundo y después de cada ejecución prosigue con la rutina de interrupción original del JA.

Lo que hace es:

1- Comprobar si se ha pulsado ENTER (lee el último carácter tecleado de la variable del sistema del JA KEYCOD) y en caso afirmativo copia el BEI a un bloque de memoria con la etiqueta Buffer y también se guardan los valores de las cuatro variables del sistema del JA relacionadas con el BEI que son CURSOR, L_HALF, INSCRN y ENDBUF (ver manual del JA página 141)

2- Comprobar si se han pulsado simultáneamente las teclas Z y X leyendo el puerto $FEFE y en caso afirmativo se restaura lo almacenado en el bloque de memoria Buffer y también se restauran los valores de las cuatro variables del sistema del JA relacionadas con el BEI a los valores que tenían cuando se copió el BEI.

En ambos casos comprueba que estemos en el BEI y no en "otro" Búfer de entrada. Para ello comprueba el valor de registro SP que debe ser un valor concreto (función del valor de ORIGEN del programa escogido)

(Opcional)

Se puede volver al modo 1 de interrupción, con lo que deja de funcionar la copia/restauración del búfer, haciendo:

65489 CALL

Para volver al modo 2 de interrupción nuevamente reactivando la copia/restauración:

65292 CALL o ejecutando de nuevo PUTBUFF

OJO: No usar el que activa el modo 1 si ya estamos en modo 1 ni el que activa el modo 2 si ya estamos en modo 2. Puede colgarse el JA.

LIMIT Coloca en la variable del sistema RAM (15384/3C18) del JA la dirección del primer byte del bloque de memoria (64544/FC20) que NO puede utilizar FORTH. Este bloque empieza en la dirección almacenada en RAM y se extiende hasta el final de la memoria que en nuestro caso es 65535/FFFF.

Código: Seleccionar todo

: LIMIT
 -992 15384 ! QUIT
;


NOTA: El JA cuando lista/edita palabras con LIST/EDIT interpreta los números CON SIGNO. Es por ello que al listar LIMIT se muestra -992 que es 64544 considerado CON SIGNO:

-992 DUP . U. <ENTER>

Imprimirá en pantalla (INVIS activado):

-992 64544

PUTBUFF Copia la rutina en código máquina almacenada en SAVEBUFF en la zona de memoria reservada. Empieza en 64544/FC20 y llega hasta 65492/FFD4 (949 bytes en total). Antes comprueba que se haya modificado RAM al valor correspondiente y una vez copiada la rutina la arranca. A partir de este momento se pueden borrar las tres palabras, pues ya no son necesarias.

NOTA: Por lo mismo dicho con LIMIT, los números se muestran CON SIGNO:

-992 es 64544/FC20
-43 es 65493/FFD5
-244 es 65292/FF0C

Código: Seleccionar todo

: PUTBUFF
 15384 @ -992 = 0=
 IF
  CR CR ." RAMTOP Incorrect!"
  CR CR ." Use LIMIT before this one."
  CR QUIT
 THEN
 SAVEBUFF -43 -992
 DO
  DUP C@ I C! 1+
 LOOP
 DROP -244 CALL CR CR
 ." Z+X keys to retrieve Old buffer "
 CR
;


SAVEBUFF Solo almacena el código máquina que ha de cargar en memoria PUTBUFF. EL listado que pongo a continuación es un "cargador" Forth generado a partir del SAVEBUFF original.

El SAVEBUFF original se hizo de otra manera:

Primero generamos con TASM el fichero restbuff.BIN con el código máquina de la rutina (cuyo Código Fuente listo más abajo). Ocupa 949 bytes.

Ahora hacemos: CREATE SAVEBUFF 949 ALLOT con lo que tenemos SAVEBUFF con un PF (Parameter Field) de 949 bytes.

Al ejecutar SAVEBUFF nos deja en la pila la dirección de inicio de su PF. Con este dato y con la opción "Load Memory Block" del menú "File" del EightyOne (es el que he usado, pero también servirían otros emuladores) cargo en memoria restbuff.BIN poniendo como "Address" la dirección del inicio del PF de SAVEBUFF. Con esto ya tenemos el SAVEBUFF original (el que incluyo en el fichero oldbuff.tzx).

Código: Seleccionar todo

BASE C@ DECIMAL 16 BASE C!
CREATE SAVEBUFF
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 26 C, FC C,
 2E C, 20 C, 36 C, 1D C, 23 C,
 36 C, FF C, 3E C, FC C, ED C,
 47 C, ED C, 5E C, FD C, E9 C,
 F3 C, F5 C, 08 C, F5 C, C5 C,
 D5 C, E5 C, 21 C, 12 C, FC C,
 B7 C, ED C, 72 C, C2 C, CE C,
 FF C, 21 C, 26 C, 3C C, 7E C,
 21 C, 22 C, FC C, FE C, 0D C,
 7E C, 20 C, 32 C, FE C, 01 C,
 28 C, 30 C, 36 C, 01 C, 2A C,
 1E C, 3C C, 22 C, 28 C, FC C,
 2A C, 20 C, 3C C, 22 C, 24 C,
 FC C, 2A C, 24 C, 3C C, 22 C,
 26 C, FC C, 44 C, 4D C, 2A C,
 22 C, 3C C, 22 C, 2A C, FC C,
 B7 C, ED C, 42 C, 28 C, 0F C,
 44 C, 4D C, 2A C, 24 C, 3C C,
 11 C, 2C C, FC C, ED C, B0 C,
 C3 C, 6D C, FF C, 36 C, 00 C,
 01 C, FE C, FE C, 16 C, 00 C,
 ED C, 58 C, 3E C, 0C C, A3 C,
 21 C, 23 C, FC C, 20 C, 50 C,
 7E C, FE C, 01 C, 28 C, 4D C,
 36 C, 01 C, ED C, 4B C, 26 C,
 FC C, 2A C, 2A C, FC C, B7 C,
 ED C, 42 C, 28 C, 3F C, E5 C,
 21 C, FF C, 26 C, ED C, 5B C,
 24 C, 3C C, B7 C, ED C, 52 C,
 44 C, 4D C, 21 C, FF C, 26 C,
 36 C, 20 C, 54 C, 5D C, 1B C,
 0B C, ED C, B8 C, C1 C, ED C,
 5B C, 26 C, FC C, 21 C, 2C C,
 FC C, ED C, B0 C, 2A C, 26 C,
 FC C, 22 C, 24 C, 3C C, 2A C,
 24 C, FC C, 22 C, 20 C, 3C C,
 2A C, 28 C, FC C, 22 C, 1E C,
 3C C, 2A C, 2A C, FC C, 22 C,
 22 C, 3C C, C3 C, CE C, FF C,
 36 C, 00 C, C3 C, 40 C, 01 C,
 ED C, 56 C, FD C, E9 C,
BASE C!


Código fuente Rutina en código máquina:

Código: Seleccionar todo

; Jupiter Ace (aka JA) TOPRAM (RAM variable: $3C18) must be EXACTLY $FC20
; Interrupt mode 2: At each interrupt executes the routine whose
; address is the one stored at memory address $nn20 where $nn is the value
; of the I register.


                .list
CURSOR          .equ $3C20              ; Address of the cursor in the input buffer.
L_HALF          .equ $3C24              ; Address of the start of the input buffer.
INSCRN          .equ $3C1E              ; Address of the start of the current logical line
ENDBUF          .equ $3C22              ; Address of the end of the current logical line
KEYCOD          .equ $3C26              ; ASCII last key pressed
                                        ; These five address above are part of JA's System Variables.
ENDSCR          .equ $26FF              ; Address of video ram's last byte
ORIGIN          .equ $FC20              ; Address where the program is to be loaded
                .org ORIGIN
Vector:         .word 0                 ; Space to store the Interrupt vector.
Keyflag         .byte 0                 ; Flag: End of pressing <ENTER>
Keyflag2        .byte 0                 ; Flag: End of pressing <Z+X>
cursorB         .word 0                 ; Old value of CURSOR
l_halfB         .word 0                 ; Old value of L_HALF
inscrnB         .word 0                 ; Old value of INSCRN
endbufB         .word 0                 ; Old value of ENDBUF
Buffer          .fill 736,32            ; Space to save the input buffer copy (+2 safety bytes)
First:          ld h,Vector / $100      ; (1) Store in Vector ($nn20=$FC20) the value of "Linicio" (the vector to the routine
                ld l,$20                ; to be executed at each interrupt). This routine begins at "Linicio"   
                ld (hl),Linicio % $100 
                inc hl
                ld (hl),Linicio / $100  ; ----End 1----
                ld a,Vector / $100      ; (2) Set I register to $nn and interrupt mode 2 is activated.
                ld i,a
                im 2                    ; ----End 2----
                jp (iy)                 ; Back to Forth
;------------------------------         ; (4) INTERRUPT ROUTINE
Linicio:        di                      ; (3) Dissable interrupts and save registers.
                push af                 ; after our interrupt routine is finished the program jumps to the original
                ex af,af'               ; JA interrupt routine that, when terminated, will restore interrupts and
                push af                 ; and saved registers (see --End 4-- below).
                push bc
                push de
                push hl                 ; ----End 3----
                ld hl,ORIGIN - 14       ; (5) Test we are at standar input buffer
                or a                    ; NOT in any other (QUERY, RETYPE, etc.)
                sbc hl,sp               ; Test: SP = ORIGIN - 14
                jp nz,Fin2              ; ----End 5----
                ld hl,KEYCOD            ; (6) Test <ENTER> pressed (Input buffer -> Copia)
                ld a,(hl)
                ld hl,Keyflag
                cp 13
                ld a,(hl)
                jr nz,NotRet
                cp 1
                jr z,Finito             ; If Keyflag=1 -> Already evaluated. Wait until key depressed
                ld (hl),1
                ;--------------------Input buffer and associated variables -> Copy
                ld hl,(INSCRN)
                ld (inscrnB),hl
                ld hl,(CURSOR)
                ld (cursorB),hl
                ld hl,(L_HALF)
                ld (l_halfB),hl
                ld b,h
                ld c,l
                ld hl,(ENDBUF)
                ld (endbufB),hl
                or a
                sbc hl,bc               ; number of bytes to copy = (ENDBUF) - (L_HALF)
                jr z,Finito
                ld b,h
                ld c,l
                ld hl,(L_HALF)
                ld de,Buffer
                ldir
                jp Finito
                ;--------------------
NotRet:         ld (hl),0
Finito:                                 ; ----End 6----
                ld bc,$fefe             ; (7) Test Z and X keys pressed at same time. (Copy -> Input buffer)
                ld d,0
                in e,(c)                ; Read Keyboard port: Z=bit 2 X=bit 3 (1->off, 0->pressed)
                ld a,1100b
                and e
                ld hl,Keyflag2
                jr nz,NotRet2           ; If (z) -> Z and X pressed at a time.
                ld a,(hl)
                cp 1
                jr z,Fin2               ; If Keyflag2=1 -> Already evaluated. Wait until keys depressed.
                ld (hl),1
                ;--------------------Copy restored as Input buffer (also restore system variables)
                ld bc,(l_halfB)         ; number of bytes to restore = (endbufB) - (l_halfB)
                ld hl,(endbufB)
                or a
                sbc hl,bc
                jr z,Fin2
                push hl                 ; (9) Clean actual input buffer before restoring old one
                ld hl,ENDSCR
                ld de,(L_HALF)
                or a
                sbc hl,de               ; number of bytes to clean (fill with spaces). Never = 0 (at least will be 31)
                ld b,h
                ld c,l
                ld hl,ENDSCR
                ld (hl),$20
                ld d,h
                ld e,l
                dec de
                dec bc
                lddr
                pop bc                   ; ----End 9----
                ld de,(l_halfB)
                ld hl,Buffer
                ldir
                ld hl,(l_halfB)
                ld (L_HALF),hl
                ld hl,(cursorB)         
                ld (CURSOR),hl
                ld hl,(inscrnB)
                ld (INSCRN),hl
                ld hl,(endbufB)
                ld (ENDBUF),hl
                jp Fin2
NotRet2:        ld (hl),0   
                ;------------------------------ END of INTERRUPT ROUTINE.
Fin2:                                   ; ----End 4----   
                JP $0140                ; Jump to original interrupt routine of the JA. (avoiding repeat what alreay
                                        ; have been done here (save registers...)
Inter1:         im 1                    ; Interrupt mode 1 activation (must be called from Forth)
                jp (iy)                 ; Back to Forth
                .end


oldbuff.TZX
(1.22 KiB) Descargado 6 veces


EDICION (4-5-2022)

Se han corregido un par de efectos que se daban en ciertas circunstancias. Ahora, antes de restaurarse un Búfer de entrada, se limpia el actual primero a fin de evitar que queden caracteres sobrantes en el búfer de entrada o en la pantalla.

Avatar de Usuario
jolugoro
Mensajes: 249
Registrado: 03 Abr 2017 23:02
Ubicación: Algeciras
Agradecido : 104 veces
Agradecimiento recibido: 73 veces

Re: Jupiter Ace Forth: Copia del Búfer de Entrada

Mensajepor jolugoro » 30 Abr 2022 17:17

Encomiable el esfuerzo que dedicas. Gracias por todo Elurdio.

Elurdio
Mensajes: 311
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 74 veces
Agradecimiento recibido: 76 veces

Re: Jupiter Ace Forth: Copia del Búfer de Entrada

Mensajepor Elurdio » 02 May 2022 00:05

Cuando probé este programa (aún sin terminar, solo había hecho la parte de guardar el búfer, faltaba la de recuperarlo) lo probé en el trabajo y me falló (se reseteaba el Forth). Resultó que en el trabajo usaba la versión 1.23 del EightyOne mientras en casa usaba la 1.25. Ahora tengo la 1.28 en ambos sitios.

Hoy he probado en otros dos emuladores del Jupiter Ace: SpuedAce y ZEsarUX. La última versión del primero y del segundo una compilada en Windows 10 del 5 de enero del corriente. Pues en ambos falla. Se resetea el Forth en cuanto arranca la rutina, igual que me pasaba con la versión 1.23 del EightyOne...

Así que solo me funciona en el EightyOne y con la versión 1.24 o superior.

Si alguien tuviera la posibilidad de probarlo en máquina física/FPGA/Clon/etc. pero no tuviera la memoria completa, puedo modificarlo para que trabaje con menos.

Elurdio
Mensajes: 311
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 74 veces
Agradecimiento recibido: 76 veces

Re: Jupiter Ace Forth: Copia del Búfer de Entrada

Mensajepor Elurdio » 02 May 2022 12:20

He he estado haciendo pruebas y llego a la conclusión que, muy probablemente, los emuladores que fallan no tienen en cuenta el funcionamiento concreto del modo 2 de interrupción en el Jupiter Ace.

Las prueba que he hecho es:

Uso el EightyOne versión 1.23 como emulador que falla y la versión 1.28 como emulador que funciona. Más adelante comprobaré con los otros dos emuladores que también me fallan.

Me he hecho un programa muy simple que utiliza el modo interrupción 2. Simplemente suma uno a un posición de memoria concreta. Como la interrupción se repite 50 veces por segundo, pues la suma es rápida. Uso un pequeño programa en Forth que me imprime continuamente en pantalla el valor que hay en esa posición de memoria.

Pues, como era de esperar la v.1.23 falla y la v.1.28 funciona.

Ahora lo que hago es modificar el programa que utiliza el modo interrupción 2 pero "dando por hecho" que el emulador NO se comporta como se supone lo hace el Jupiter Ace (*). Entonces sí que funciona, tanto en la v1.23 como en la v1.28. De ahí que concluyo que, muy probablemente, el fallo se debe a que hay emuladores que no "emulan" el comportamiento del Jupiter Ace en modo interrupción 2.

(*) Este otro enfoque es bastante más liado y consume más memoria comparado con el caso en que el emulador contempla el modo real de comportarse del JA. Por si a alguien le pudiera interesar, daré los detalles técnicos en el hilo Jupiter Ace Interrupción Modo 2

Elurdio
Mensajes: 311
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 74 veces
Agradecimiento recibido: 76 veces

Re: Jupiter Ace Forth: Copia del Búfer de Entrada

Mensajepor Elurdio » 02 May 2022 16:31

Elurdio escribió:·
·
Uso el EightyOne versión 1.23 como emulador que falla y la versión 1.28 como emulador que funciona. Más adelante comprobaré con los otros dos emuladores que también me fallan.
·
·
[/url]


Acabo de probarlos (SpudAce y ZEsarUX):

Ambos fallan con el programa simple usando interrupción 2 según modelo Jupiter Ace
Ambos funcionan con el programa simple usando interrupción 2 genérica

NOTA: Aparte de ser más pesada de programar la genérica, la primera ocupa 38 bytes mientras la genérica se va a 556 bytes...

Ahora solo me resta hacer el programa completo (el copiador/restaurador de búfer de entrada) en versión genérica como comprobación final (a falta de poder probarlo en un Jupiter Ace real).

Elurdio
Mensajes: 311
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 74 veces
Agradecimiento recibido: 76 veces

Re: Jupiter Ace Forth: Copia del Búfer de Entrada

Mensajepor Elurdio » 03 May 2022 00:39

Acabo de hacer la versión compatible con emuladores que fallan. Es igual que la anterior.

Lo he probado con EightyOne versiones 1.28 y 1.20, con SpudAce versión 1.02 y con ZEsarUX versión 10.1-B1 y funciona con todas

Para funcionamiento ver primer post.

Los cambios:

Los nombres de los ficheros ahora son:

LIMIT2
PUTBUFF2
SAVEBUFF2

Código: Seleccionar todo

: LIMIT2
 -1286 15384 ! QUIT
;

: PUTBUFF2
 15384 @ -1286 = 0=
 IF
  CR CR ." RAMTOP Incorrect!"
  CR CR ." Use LIMIT2 before this one."
  CR QUIT
 THEN
 SAVEBUFF2 -13 -1286
 DO
  DUP C@ I C! 1+
 LOOP
 DROP -21 CALL CR CR
 ." Z+X keys to retrieve Old buffer "
 CR
;

BASE C@ DECIMAL 16 BASE C!
CREATE SAVEBUFF2
 F3 C, F5 C, 08 C, F5 C, C5 C,
 D5 C, E5 C, 21 C, EC C, FA C,
 B7 C, ED C, 72 C, C2 C, AB C,
 FB C, 21 C, 26 C, 3C C, 7E C,
 21 C, 01 C, FD C, FE C, 0D C,
 7E C, 20 C, 32 C, FE C, 01 C,
 28 C, 30 C, 36 C, 01 C, 2A C,
 1E C, 3C C, 22 C, 07 C, FD C,
 2A C, 20 C, 3C C, 22 C, 03 C,
 FD C, 2A C, 24 C, 3C C, 22 C,
 05 C, FD C, 44 C, 4D C, 2A C,
 22 C, 3C C, 22 C, 09 C, FD C,
 B7 C, ED C, 42 C, 28 C, 0F C,
 44 C, 4D C, 2A C, 24 C, 3C C,
 11 C, 0B C, FD C, ED C, B0 C,
 C3 C, 4A C, FB C, 36 C, 00 C,
 01 C, FE C, FE C, 16 C, 00 C,
 ED C, 58 C, 3E C, 0C C, A3 C,
 21 C, 02 C, FD C, 20 C, 50 C,
 7E C, FE C, 01 C, 28 C, 4D C,
 36 C, 01 C, ED C, 4B C, 05 C,
 FD C, 2A C, 09 C, FD C, B7 C,
 ED C, 42 C, 28 C, 3F C, E5 C,
 21 C, FF C, 26 C, ED C, 5B C,
 24 C, 3C C, B7 C, ED C, 52 C,
 44 C, 4D C, 21 C, FF C, 26 C,
 36 C, 20 C, 54 C, 5D C, 1B C,
 0B C, ED C, B8 C, C1 C, ED C,
 5B C, 05 C, FD C, 21 C, 0B C,
 FD C, ED C, B0 C, 2A C, 05 C,
 FD C, 22 C, 24 C, 3C C, 2A C,
 03 C, FD C, 22 C, 20 C, 3C C,
 2A C, 07 C, FD C, 22 C, 1E C,
 3C C, 2A C, 09 C, FD C, 22 C,
 22 C, 3C C, C3 C, AB C, FB C,
 36 C, 00 C, C3 C, 40 C, 01 C,
 ED C, 56 C, FD C, E9 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, FA C,
 FA C, FA C, FA C, FA C, 00 C,
 00 C, 00 C, 00 C, 00 C, 00 C,
 00 C, 00 C, 00 C, 00 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 20 C, 20 C, 20 C, 20 C, 20 C,
 3E C, FC C, ED C, 47 C, ED C,
 5E C, FD C, E9 C,
BASE C!


Y, el mayor cambio, la rutina en código máquina. Ahora utiliza el modo de interrupción 2 genérico del Z80: el Low byte de la dirección dónde se almacena el vector de interrupción es aleatorio en vez de ser fijo ($20). He reordenado todo para aprovechar más la memoria y disminuir el impacto. La nueva rutina ocupa 1273 bytes frente a los 949 de la específica del JA. No parece mucho (36% mayor), pero hay que tener en cuenta que 736 bytes son de espacio para copiar el búfer de entrada en ambas rutinas. Si los descontamos hablamos de unos 200 bytes frente a unos 520 de la nueva (160% mayor).

Código: Seleccionar todo

; Jupiter Ace (aka JA) TOPRAM (RAM variable: $3C18) must be EXACTLY $FAFA
; In this generic approach to interrupt mode 2 we have to cope whith the
; fact that the Lowbyte of the address where the interrupt vector is stored
; is now random (can be any value from 00 to FF) instead of a hardware fixed
; value of $20 that happens in Jupiter Ace.
; Interrupt mode 2 (generic): At each interrupt executes the routine whose
; address is the one stored at memory address $nnxx where $nn is the value of
; the I register and $xx is a random value (00 to FF).
; To cope with these we reserve a block of memory filled with $FA in a way that
; we are sure that for any random value of the LowByte ($xx) the address
; $nnxx correspond to a position of that reserved block. Then we can be sure that
; the address stored at $nnxx will be $FAFA independently of the random value $xx.
 
                .list
CURSOR          .equ $3C20              ; Address Cursor en el input búfer
L_HALF          .equ $3C24              ; Address Start input búfer.
INSCRN          .equ $3C1E              ; Address of the start of the current logical line
ENDBUF          .equ $3C22              ; Address of the end of the current logical line
KEYCOD          .equ $3C26              ; ASCII last key pressed
                                        ; These five address above are part of JA's System Variables.
ENDSCR          .equ $26FF              ; Address of video ram's last byte
ORIGIN          .equ $FAFA              ; Address where the program is to be loaded
                .org $FD01
Keyflag         .byte 0                 ; Flag: End of pressing <ENTER>
Keyflag2        .byte 0                 ; Flag: End of pressing <Z+X>
cursorB         .word 0                 ; Old value of CURSOR
l_halfB         .word 0                 ; Old value of L_HALF
inscrnB         .word 0                 ; Old value of INSCRN
endbufB         .word 0                 ; Old value of ENDBUF
Buffer          .fill 736,32            ; Space to save the input buffer copy (+2 safety bytes)
First:          ld a,$FC                ; (2) I = $FC and activate interrupt mode 2
                ld i,a
                im 2                    ; ----Fin 2----
                jp (iy)                 ; Back to Forth
                                        ; --------Trick to cope with random lowbyte.
Trick:          .org $FC00              ; Reserved Memory Block
                .fill 257,$FA           ; filled with $FA
                                        ; ------------------------------------------
                .org ORIGIN              ; Interrupt Routine
;------------------------------         ; (4) INTERRUPT ROUTINE
Linicio:        di                      ; (3) Dissable interrupts and save registers.
                push af                 ; after our interrupt routine is finished the program jumps to the original
                ex af,af'               ; JA interrupt routine that, when terminated, will restore interrupts and
                push af                 ; and saved registers (see --End 4-- below).
                push bc
                push de
                push hl                 ; ----End 3----
                ld hl,ORIGIN - 14       ; (5) Test we are at standar input buffer
                or a                    ; NOT in any other (QUERY, RETYPE, etc.)
                sbc hl,sp               ; Test: SP = ORIGIN - 14
                jp nz,Fin2              ; ----End 5----
                ld hl,KEYCOD            ; (6) Test <ENTER> pressed (Input buffer -> Copia)
                ld a,(hl)
                ld hl,Keyflag
                cp 13
                ld a,(hl)
                jr nz,NotRet
                cp 1
                jr z,Finito             ; If Keyflag=1 -> Already evaluated. Wait until key depressed
                ld (hl),1
                ;--------------------Input buffer and associated variables -> Copy
                ld hl,(INSCRN)
                ld (inscrnB),hl
                ld hl,(CURSOR)
                ld (cursorB),hl
                ld hl,(L_HALF)
                ld (l_halfB),hl
                ld b,h
                ld c,l
                ld hl,(ENDBUF)
                ld (endbufB),hl
                or a
                sbc hl,bc               ; number of bytes to copy = (ENDBUF) - (L_HALF)
                jr z,Finito
                ld b,h
                ld c,l
                ld hl,(L_HALF)
                ld de,Buffer
                ldir
                jp Finito
                ;--------------------
NotRet:         ld (hl),0
Finito:                                 ; ----End 6----
                ld bc,$fefe             ; (7) Test Z and X keys pressed at same time. (Copy -> Input buffer)
                ld d,0
                in e,(c)                ; Read Keyboard port: Z=bit 2 X=bit 3 (1->off, 0->pressed)
                ld a,1100b
                and e
                ld hl,Keyflag2
                jr nz,NotRet2           ; If (z) -> Z and X pressed at a time.
                ld a,(hl)
                cp 1
                jr z,Fin2               ; If Keyflag2=1 -> Already evaluated. Wait until keys depressed.
                ld (hl),1
                ;--------------------Copy restored as Input buffer (also restore system variables)
                ld bc,(l_halfB)         ; number of bytes to restore = (endbufB) - (l_halfB)
                ld hl,(endbufB)
                or a
                sbc hl,bc
                jr z,Fin2
                push hl                 ; (9) Clean actual input buffer before restoring old one
                ld hl,ENDSCR
                ld de,(L_HALF)
                or a
                sbc hl,de               ; number of bytes to clean (fill with spaces). Never = 0 (at least will be 31)
                ld b,h
                ld c,l
                ld hl,ENDSCR
                ld (hl),$20
                ld d,h
                ld e,l
                dec de
                dec bc
                lddr
                pop bc                   ; ----End 9----
                ld de,(l_halfB)
                ld hl,Buffer
                ldir
                ld hl,(l_halfB)
                ld (L_HALF),hl
                ld hl,(cursorB)         
                ld (CURSOR),hl
                ld hl,(inscrnB)
                ld (INSCRN),hl
                ld hl,(endbufB)
                ld (ENDBUF),hl
                jp Fin2
NotRet2:        ld (hl),0   
                ;------------------------------ END of INTERRUPT ROUTINE.
Fin2:                                   ; ----End 4----   
                JP $0140                ; Jump to original interrupt routine of the JA. (avoiding repeat what alreay
                                        ; have been done here (save registers...)
Inter1:         im 1                    ; Interrupt mode 1 activation (must be called from Forth)
                jp (iy)                 ; Back to Forth
                .end


(Opcional)

Se puede volver al modo 1 de interrupción, con lo que deja de funcionar la copia/restauración del búfer, haciendo:

64430 CALL

Para volver al modo 2 de interrupción nuevamente reactivando la copia/restauración:

65515 CALL o ejecutar PUTBUFF2 de nuevo.

OJO: No usar el que activa el modo 1 si ya estamos en modo 1 ni el que activa el modo 2 si ya estamos en modo 2. Puede colgarse el JA.

oldbuff2.TZX
(1.54 KiB) Descargado 6 veces


oldbuff2.tap
(1.49 KiB) Descargado 6 veces


EDICION (4-5-2022) Ver la explicación al final del primer post (lo mismo se aplica aquí)
EDICION (10-5-2022) Las direcciones de los CALL para desactivar/reactivar estaban mal.

Elurdio
Mensajes: 311
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 74 veces
Agradecimiento recibido: 76 veces

Re: Jupiter Ace Forth: Copia del Búfer de Entrada

Mensajepor Elurdio » 10 May 2022 23:16

Ahora tiene dos funciones:

  • Copia/Restauración del Búfer de Entrada <Z+X>
  • BREAK en modo FAST <SHIFT+ESPACIO>

El BREAK estando en modo FAST pone el JA en modo SLOW excepto si estamos en el Búfer de Entrada Estándar (BEI), en cuyo caso se mantiene el modo FAST. En cualquier otro caso (incluidos cuando la palabra está a la espera que se teclee algo) tras un BREAK en modo FAST el JA se pone en modo SLOW.

Que el BREAK en modo FAST detenga la palabra en ejecución se rige por las mismas normas que el BREAK normal (en modo SLOW). Por ejemplo, estando una palabra esperando que se teclea, el BREAK no detiene la palabra. Tampoco la interrumpe si estamos en EDICION. Etc.

IMPORTANTE: El uso de esta rutina apenas si afecta a la velocidad de ejecución de las palabras. En general la pérdida de velocidad es del orden del 0.1% (una parte entre 1000) por lo que con esta rutina activa, no solo disponemos de una copia del búfer de entrada sino también disfrutamos de las ventajas del BREAK en modo FAST si afectar a la velocidad de ejecución.

Como antes, incluyo dos versiones:

buffbreak.tzx: Compatible con el JA real y emuladores/clones que emulan el comportamiento real del JA respecto al modo 2 de interrupción (LowByte h20). Por ejemplo funciona con el EigthyOne versión 1.28

buffbreak2.tzx/.tap: Compatible universal o genérico. Funciona con el JA real o con cualquier emulador/clon del mismo que emulen el modo 2 de interrupción del Z80 (Cualquier LowByte hxx) al precio de ocupar algo más de memoria con respecto al buffbreak

NOTA: En realidad solo los he probado con emuladores (concretamente ZEsarUX, EigthyOne y SpudAce). NUNCA con el JA real ni ningún clon o FPGA. Mi afirmación de que funcionan en tal o cual sistema se debería traducir a "debería funcionar"

Para su Ejecución/Requisitos, ver los casos anteriores oldbuff y oldbuff2 respectivamente. aunque los CALL opcionales NO se corresponden (no utilizarlos)

Código fuente Rutina en código máquina (buffbreak):

Código: Seleccionar todo

; Jupiter Ace (aka JA) TOPRAM (RAM variable: $3C18) must be EXACTLY $FC20
; Interrupt mode 2: At each interrupt executes the routine whose
; address is the one stored at memory address $nn20 where $nn is the value
; of the I register.


                .LIST
CURSOR          .EQU    $3C20                   ; Address of the cursor in the input buffer.
L_HALF          .EQU    $3C24                   ; Address of the start of the input buffer.
INSCRN          .EQU    $3C1E                   ; Address of the start of the current logical line
ENDBUF          .EQU    $3C22                   ; Address of the end of the current logical line
KEYCOD          .EQU    $3C26                   ; ASCII last key pressed
                                                ; These five address above are part of JA's System Variables.
ENDSCR          .EQU    $26FF                   ; Address of video ram's last byte
ORIGIN          .EQU    $FC20                   ; Address where the program is to be loaded
                .ORG    ORIGIN
VECTOR:         .WORD   0                       ; Space to store the Interrupt vector.
KEYFLAG:        .BYTE   0                       ; Flag: End of pressing <ENTER>
KEYFLAG2:       .BYTE   0                       ; Flag: End of pressing <Z+X>
CURSORB:        .WORD   0                       ; Old value of CURSOR
L_HALFB:        .WORD   0                       ; Old value of L_HALF
INSCRNB:        .WORD   0                       ; Old value of INSCRN
ENDBUFB:        .WORD   0                       ; Old value of ENDBUF
BUFFER:         .FILL   736,32                  ; Space to save the input buffer copy (+2 safety bytes)
FIRST:          LD      H,VECTOR / $100         ; (1) Store in Vector ($nn20=$FC20) the value of "Linicio" (the vector to the routine
                LD      L,$20                   ; to be executed at each interrupt). This routine begins at "Linicio"   
                LD      (HL),LINICIO % $100     
                INC     HL
                LD      (HL),LINICIO / $100     ; ----End 1----
                LD      A,VECTOR / $100         ; (2) Set I register to $nn and interrupt mode 2 is activated.
                LD      I,A
                IM      2                       ; ----End 2----
                JP      (IY)                    ; Back to Forth
;------------------------------                 ; (4) INTERRUPT ROUTINE
LINICIO:        DI                              ; (3) Dissable interrupts and save registers.
                PUSH    AF                      ; after our interrupt routine is finished the program jumps to the original
                EX      AF,AF'                  ; JA interrupt routine that, when terminated, will restore interrupts and
                PUSH    AF                      ; and saved registers (see --End 4-- below).
                PUSH    BC
                PUSH    DE
                PUSH    HL                      ; ----End 3----
                LD      HL,ORIGIN - 14          ; (5) Test we are at standar input buffer
                OR      A                       ; NOT in any other (QUERY, RETYPE, etc.)
                SBC     HL,SP                   ; Test: SP = ORIGIN - 14
                JP      NZ,PBREAK               ; Test for a PBREAK
                                                ; ----End 5----
                LD      HL,KEYCOD               ; (6) Test <ENTER> pressed (Input buffer -> Copia)
                LD      A,(HL)
                LD      HL,KEYFLAG
                CP      13
                LD      A,(HL)
                JR      NZ,NOTRET
                CP      1
                JR      Z,FINITO                ; If Keyflag=1 -> Already evaluated. Wait until key depressed
                LD      (HL),1
                ;--------------------           ; Input buffer and associated variables -> Copy
                LD      HL,(INSCRN)
                LD      (INSCRNB),HL
                LD      HL,(CURSOR)
                LD      (CURSORB),HL
                LD      HL,(L_HALF)
                lD      (L_HALFB),HL
                LD      B,H
                LD      C,L
                LD      HL,(ENDBUF)
                LD      (ENDBUFB),HL
                OR      A
                SBC     HL,BC                   ; number of bytes to copy = (ENDBUF) - (L_HALF)
                JR      Z,FINITO
                LD      B,H
                LD      C,L
                LD      HL,(L_HALF)
                LD      DE,BUFFER
                LDIR
                JP      FINITO
                ;--------------------
NOTRET:         LD      (HL),0
FINITO:                                         ; ----End 6----
                LD      BC,$FEFE                ; (7) Test Z and X keys pressed at same time. (Copy -> Input buffer)
                LD      D,0
                IN      E,(C)                   ; Read Keyboard port: Z=bit 2 X=bit 3 (1->off, 0->pressed)
                LD      A,1100B
                AND     E
                LD      HL,KEYFLAG2
                JR      NZ,NOTRET2              ; If (z) -> Z and X pressed at a time.
                LD      A,(HL)
                CP      1
                JR      Z,FIN2                  ; If Keyflag2=1 -> Already evaluated. Wait until keys depressed.
                LD      (HL),1
                ;--------------------           ; Copy restored as Input buffer (also restore system variables)
                LD      BC,(L_HALFB)            ; number of bytes to restore = (endbufB) - (l_halfB)
                LD      HL,(ENDBUFB)
                OR      A
                SBC     HL,BC
                JR      Z,FIN2
                PUSH    HL                      ; (9) Clean actual input buffer before restoring old one
                LD      HL,ENDSCR
                LD      DE,(L_HALF)
                OR      A
                SBC     HL,DE                   ; number of bytes to clean (fill with spaces). Never = 0 (at least will be 31)
                LD      B,H
                LD      C,L
                LD      HL,ENDSCR
                LD      (HL),$20
                LD      D,H
                LD      E,L
                DEC     DE
                DEC     BC
                LDDR
                POP     BC                      ; ----End 9----
                LD      DE,(L_HALFB)
                LD      HL,BUFFER
                LDIR
                LD      HL,(L_HALFB)
                LD      (L_HALF),HL
                LD      HL,(CURSORB)   
                LD      (CURSOR),HL
                LD      HL,(INSCRNB)
                LD      (INSCRN),HL
                LD      HL,(ENDBUFB)
                LD      (ENDBUF),HL
                JP      FIN2
NOTRET2:        LD      (HL),0
FIN2:           JP      $0140                   ; Jump to original interrupt routine of the JA. (avoiding repeat what alreay
                                                ; have been done here (save registers...)
PBREAK:                                         ; Test for shift+space: Break (Fast->Slow) In any situation except while in standard input buffer.

                ; >>> Plagiarized & Adapted from the ROM Listing at JA archive site <<<
               
                LD      A,$FE                   ; read port $FEFE -
                IN      A,($FE)                 ; keys SPACE, SYMSHIFT, M, N, B.
                RRA                             ; test bit for outermost key
                JP      C,$140                  ; Conitnue JA interupt if not pressed.
                LD      A,$7F                   ; read port $7FFE -
                IN      A,($FE)                 ; keys SHIFT, Z, X, C, V.
                RRA                             ; test bit for outermost key
                JP      C,$140                  ; Conitnue JA interupt if not pressed.
               
                ; >>> End Plagiarism <<<

                LD      IY,$04C8                ; Sets the Ace to SLOW mode.
                JP      $140
                ;----------------------- END OF INTERRUPT ROUTINE.
                                                ; ----End 4----
INTER1:         IM      1                       ; Interrupt mode 1 activation (must be called from Forth)
                JP      (IY)                    ; Back to Forth
                .END


Código fuente Rutina en código máquina (buffbreak2):

Código: Seleccionar todo

; Jupiter Ace (aka JA) TOPRAM (RAM variable: $3C18) must be EXACTLY $FAFA
; In this generic approach to interrupt mode 2 we have to cope whith the
; fact that the Lowbyte of the address where the interrupt vector is stored
; is now random (can be any value from 00 to FF) instead of a hardware fixed
; value of $20 that happens in Jupiter Ace.
; Interrupt mode 2 (generic): At each interrupt executes the routine whose
; address is the one stored at memory address $nnxx where $nn is the value of
; the I register and $xx is a random value (00 to FF).
; To cope with these we reserve a block of memory filled with $FA in a way that
; we are sure that for any random value of the LowByte ($xx) the address
; $nnxx correspond to a position of that reserved block. Then we can be sure that
; the address stored at $nnxx will be $FAFA independently of the random value $xx.
 
                .list
CURSOR          .EQU    $3C20           ; Address Cursor en el input búfer
L_HALF          .EQU    $3C24           ; Address Start input búfer.
INSCRN          .EQU    $3C1E           ; Address of the start of the current logical line
ENDBUF          .EQU    $3C22           ; Address of the end of the current logical line
KEYCOD          .EQU    $3C26           ; ASCII last key pressed
                                        ; These five address above are part of JA's System Variables.
ENDSCR          .EQU    $26FF           ; Address of video ram's last byte
ORIGIN          .EQU    $FAFA           ; Address where the program is to be loaded
                .ORG    $FD01
KEYFLAG:        .BYTE   0               ; Flag: End of pressing <ENTER>
KEYFLAG2:       .BYTE   0               ; Flag: End of pressing <Z+X>
CURSORB:        .WORD   0               ; Old value of CURSOR
L_HALFB:        .WORD   0               ; Old value of L_HALF
INSCRNB:        .WORD   0               ; Old value of INSCRN
ENDBUFB:        .WORD   0               ; Old value of ENDBUF
BUFFER:         .FILL   736,32          ; Space to save the input buffer copy (+2 safety bytes)
FIRST:          LD      A,$FC           ; (2) I = $FC and activate interrupt mode 2
                LD      I,A
                IM      2               ; ----Fin 2----
                JP      (IY)            ; Back to Forth
                                        ; --------Trick to cope with random lowbyte.
TRICK:          .ORG    $FC00           ; Reserved Memory Block
                .FILL   257,$FA         ; filled with $FA
                                        ; ------------------------------------------
                .ORG    ORIGIN          ; Interrupt Routine
;------------------------------         ; (4) INTERRUPT ROUTINE
LINICIO:        DI                      ; (3) Dissable interrupts and save registers.
                PUSH    AF              ; after our interrupt routine is finished the program jumps to the original
                EX      AF,AF'          ; JA interrupt routine that, when terminated, will restore interrupts and
                PUSH    AF              ; and saved registers (see --End 4-- below).
                PUSH    BC
                PUSH    DE
                PUSH    HL              ; ----End 3----
                LD      HL,ORIGIN - 14  ; (5) Test we are at standar input buffer
                OR      A               ; NOT in any other (QUERY, RETYPE, etc.)
                SBC     HL,SP           ; Test: SP = ORIGIN - 14
                JP      NZ,PBREAK       ; Test for a PBREAKp
                                        ; ----End 5----
                LD      HL,KEYCOD       ; (6) Test <ENTER> pressed (Input buffer -> Copia)
                LD      A,(HL)
                LD      HL,KEYFLAG
                CP      13
                LD      A,(HL)
                JR      NZ,NOTRET
                CP      1
                JR      Z,FINITO        ; If Keyflag=1 -> Already evaluated. Wait until key depressed
                LD      (HL),1
                ;-----------------------Input buffer and associated variables -> Copy
                LD      HL,(INSCRN)
                LD      (INSCRNB),HL
                LD      HL,(CURSOR)
                LD      (CURSORB),HL
                LD      HL,(L_HALF)
                LD      (L_HALFB),HL
                LD      B,H
                LD      C,L
                LD      HL,(ENDBUF)
                LD      (ENDBUFB),HL
                OR      A
                SBC     HL,BC           ; number of bytes to copy = (ENDBUF) - (L_HALF)
                JR      Z,FINITO
                LD      B,H
                LD      C,L
                LD      HL,(L_HALF)
                LD      DE,BUFFER
                LDIR
                JP      FINITO
                ;--------------------
NOTRET:         LD      (HL),0
FINITO:                                 ; ----End 6----
                LD      BC,$FEFE        ; (7) Test Z and X keys pressed at same time. (Copy -> Input buffer)
                LD      D,0
                IN      E,(C)           ; Read Keyboard port: Z=bit 2 X=bit 3 (1->off, 0->pressed)
                LD      A,1100B
                AND     E
                LD      HL,KEYFLAG2
                JR      NZ,NOTRET2      ; If (z) -> Z and X pressed at a time.
                LD      A,(HL)
                CP      1
                JR      Z,FIN2          ; If Keyflag2=1 -> Already evaluated. Wait until keys depressed.
                LD      (HL),1
                ;-----------------------Copy restored as Input buffer (also restore system variables)
                LD      BC,(L_HALFB)    ; number of bytes to restore = (endbufB) - (l_halfB)
                LD      HL,(ENDBUFB)
                OR      A
                SBC     HL,BC
                JR      Z,FIN2
                PUSH    HL              ; (9) Clean actual input buffer before restoring old one
                LD      HL,ENDSCR
                LD      DE,(L_HALF)
                OR      A
                SBC     HL,DE           ; number of bytes to clean (fill with spaces). Never = 0 (at least will be 31)
                LD      B,H
                LD      C,L
                LD      HL,ENDSCR
                LD      (HL),$20
                LD      D,H
                LD      E,L
                DEC     DE
                DEC     BC
                LDDR
                POP     BC              ; ----End 9----
                LD      DE,(L_HALFB)
                LD      HL,BUFFER
                LDIR
                LD      HL,(L_HALFB)
                LD      (L_HALF),HL
                LD      HL,(CURSORB)   
                LD      (CURSOR),HL
                LD      HL,(INSCRNB)
                LD      (INSCRN),HL
                LD      HL,(ENDBUFB)
                LD      (ENDBUF),HL
                JP      FIN2
NOTRET2:        LD      (HL),0 
FIN2:           JP      $0140           ; Jump to original interrupt routine of the JA. (avoiding repeat what alreay
                                        ; have been done here (save registers...)

PBREAK:         ; Test for shift+space: Break (Fast) In any situation except while in standard input buffer.

                ; >>> Plagiarized and adapted from the ROM Listing at JA archive site <<<
               
                LD      A,$FE           ; read port $FEFE -
                IN      A,($FE)         ; keys SPACE, SYMSHIFT, M, N, B.
                RRA                     ; test bit for outermost key
                JP      C,$140          ; jump to JA interrupt if not pressed.
                LD      A,$7F           ; read port $7FFE -
                IN      A,($FE)         ; keys SHIFT, Z, X, C, V.
                RRA                     ; test bit for outermost key
                JP      C,$140          ; jump to FA interrupt if not pressed.
               
                ; >>> End Plagiarism <<<

                LD      IY,$04C8        ; Sets the Ace to SLOW mode.
                JP      $140
                ;----------------------- END of INTERRUPT ROUTINE.
                                        ; ----End 4----
INTER1:         IM      1               ; Interrupt mode 1 activation (must be called from Forth)
                JP      (IY)            ; Back to Forth
                .END


buffbreak.TZX
(1.29 KiB) Descargado 6 veces

buffbreak2.tap
(1.53 KiB) Descargado 6 veces

buffbreak2.TZX
(1.58 KiB) Descargado 6 veces

Elurdio
Mensajes: 311
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 74 veces
Agradecimiento recibido: 76 veces

Re: Jupiter Ace Forth: Copia del Búfer de Entrada

Mensajepor Elurdio » 31 May 2022 11:26

Tengo por costumbre cargarme esta rutina cada vez que trabajo con el JA y en lo que respecta al copiado del búfer de entrada, encuentro que disponer de la copia del último contenido lo hace de una utilidad reducida.

El motivo principal por el que lo hice fue para el caso que creas una nueva palabra definiéndola de un tirón y te encuentras con el temido ERROR 5 al entrarla. Esto te obliga a escribir toda la definición de nuevo. Situación que queda remediada con la copia almacenada del último búfer. Para esto va muy bien.

También es útil cuando editas muchas veces la misma palabra. En vez de redefinir cada vez que editas, la vas editando/probando/editando/... y cuando ya tienes la versión final, haces REDEFINE <nombre> y luego te limitas a Z+X <ENTER> tantas veces como sea necesario. Mucho más cómodo.

También cuando haces ejecutas en modo interactivo una serie de comandos y los has de repetir iguales o con alguna modificación, etc.

Pero en la mayoría de los casos tener solo una copia del último búfer es claramente insuficiente, pues te interesa otro anterior.

Dándole vueltas creo que puede ser interesante guardar más de una copia. Para no gastar mucha memoria, voy a dividir los 734 bytes (tamaño máximo del búfer) que reservo para copiar el búfer de entrada en 4 porciones. Pues en la práctica es muy raro guardar un búfer del tamaño máximo. Si hago copias de 192 bytes cada una (768 bytes totales) solo gasto 34 bytes más y dispongo de los 4 últimos búfers.

Almacenar los 192 primeros bytes (6 líneas) de cada uno es, en general, más que suficiente. Incluso dudo si sería más conveniente 8 copias de 96 bytes (3 líneas) cada uno. Pues en la práctica el 95% de los casos son de una línea, 2 a lo sumo.

Así cada vez que pulsemos Z+X iríamos recuperando cíclicamente los contenidos almacenados, empezando por el más reciente.

Elurdio
Mensajes: 311
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 74 veces
Agradecimiento recibido: 76 veces

Re: Jupiter Ace Forth: Copia del Búfer de Entrada

Mensajepor Elurdio » 03 Jun 2022 22:24

Por fin acabo de probar la primera versión que parece que funciona de la rutina Copia-Buffer/FAST Breal que guarda los cuatro últimos búffers de entrada.

Pensaba que sería coser y cantar partiendo de la versión anterior, pero la cosa se complicó bastante.

Cuando hice la versión mono-copia, la cosa era sencilla, pues me limitaba a entender por encima el funcionamiento interno del búfer de entrada, lo justo para poder copiarlo/restaurarlo. Lo copiaba entero y copiaba también las 4 variables del sistema relacionadas con el búfer de entrada. Para reponerlo, simplemente hacer lo contrario: Copiar el búfer de entrada almacenado a la pantalla y reponer las variables (y alguna cosa más, como limpieza previa del búfer actual antes de copiar el almacenado). No necesitaba más.

Pero ahora he tenido que hacer pruebas y ver el funcionamiento exacto del búfer de entrada (el estándar, que es el que copio) porque al copiar solo los primeros 192 caracteres como máximo, había que mover la copia a una zona distinta de la original, reconstruir las variables del sistema, controlar la posición del cursor (incluso, dado el caso, poner el símbolo del mismo en la posición adecuada), etc.

Todo esto unido a lo malo que soy programando en ensamblador me ha llevado mi tiempo...

Voy a probarlo a fondo, pulir un poco algunos aspectos, como que NO copie búferes de entrada vacíos, y ver si puedo arreglar un poco el lío de código ensamblador que he generado...

Elurdio
Mensajes: 311
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 74 veces
Agradecimiento recibido: 76 veces

Re: Jupiter Ace Forth: Copia del Búfer de Entrada

Mensajepor Elurdio » 07 Jun 2022 12:37

Versión Multicopia

Este programa instala una rutina en código máquina que tiene dos funcionalidades:

  1. Cada vez que presiona la tecla ENTER mientras está en el búfer de entrada estándar, se guarda una copia. Más tarde, puede restaurar el contenido del búfer de entrada guardado presionando simultáneamente las teclas Z y X. Se pueden almacenar hasta cuatro búferes de entrada. El más antiguo se sobrescribe. Cada vez que se presionan las teclas z+x a la vez, se restaura el búfer anterior (cíclicamente). Por defecto las cuatro copias son un espacio cada una. Los búferes de entrada vacíos no se guardan. OJO: Como máximo almacena los 192 primeros caracteres (las 6 primeras líneas) en cada copia.
  2. Al estar en modo FAST y no en el búfer de entrada, hacer un BREAK (shift+espacio) revertirá el Jupiter Ace al modo SLOW, lo que producirá un BREAK normal inmediatamente.
NOTA: El búfer de entrada estándar es cuando el Jupiter Ace está esperando que escriba algo y no hay ninguna palabra en ejecución ni está en modo EDIT/RETYPE/QUERY.

La rutina reservará espacio de memoria en memoria alta alterando el valor de la variable del sistema RAM. ¡NO SE DEBE CAMBIAR!

La rutina solo se puede usar en un Jupiter Ace con memoria de expansión de 48K (64k RAM+ROM)

El diccionario mfasbrek incluye 3 palabras:

LIMIT
PUTBUFF
SAVBUFF

Instalar:

Ejecute LIMIT Esto reservará memoria de F920 a FFFF para el código de máquina.
Ejecute PUTBUFF Esto cargará la rutina de código máquina contenida en SAVBUFF en la memoria de Jupiter Ace y activará la rutina.

############################################
NOTA: LIMIT y PUTBUFF deben ejecutarse por separado, ya que LIMIT ejecuta un QUIT para activar el límite RAM TOP. Así que si escribes:

LIMIT PUTBUFF <ENTRAR>

Solo se ejecutará LIMIT. Debes escribir:

LIMIT <ENTRAR>

y luego

PUTBUFF <ENTRAR>
############################################


Después de la instalación (después de ejecutar PUTBUFF) estas tres palabras se pueden eliminar.

Esta rutina funciona activando el Modo de Interrupción 2 por lo que primero se ejecuta el núcleo de su rutina y luego continúa con la rutina de interrupción original de Jupiter Ace.

Lo he probado en EightyOne versiones 1.28 y 1.23, ZEsarUX versión 10.1 y SpudAce versión 1.02 y 0.323

IMPORTANTE: El uso de esta rutina tiene un efecto insignificante en la VELOCIDAD de ejecución de las Palabras (en modos SLOW y FAST). En general la velocidad se reduce menos del 0,1% (1/1000).

Código: Seleccionar todo


; ###########
; # WARNING # Jupiter Ace (aka JA) TOPRAM (RAM system variable: $3C18) must be EXACTLY $F920
; ###########                       >>>> DO NOT CHANGE IT <<<<

; Interrupt mode 2:

; At each interrupt (Jupiter Ace triggers 50 interrupts every second) executes the routine whose
; address is the one stored at memory address $nn20 where $nn is the value
; of the I register.

; In some clones/emulators the memory address used is $nnFF instead.

; This routine takes into account both cases ($nn20 and $nnFF) at the cost of reserving more memory than if only the
; first case ($nn20) were considered. Specifically there is a difference of 256 bytes more.

; But memory ranges $FF3E to $FFFF (194 bytes) and $F922 to $F9FE (221 bytes) are available to the user. However, the
; last range is overwritten when the routine is loaded.

; While in the version only for the case of $nn20, only the range from $FF59 to $FFFF (165 bytes) is available to the
; user.

; This Routine has two functions:

; a) In FAST mode if a BREAK is executed (shift+space) while not in Input Buffer, SLOW mode is activated and BREAK is
;    done.

; b) While in Standard Input Buffer if ENTER key is pressed a copy of the Input Buffer is done (max. first 6 lines:
;    192 bytes). It can save up to four input buffers. While in Standard Input Buffer (SIB), each time Z and X keys
;    are pressed simultaneously a saved buffer is restored starting with the last saved and continuing cyclically
;    with the rest.

; Each Copy Zone is called a Block and are numbered 0 to 3 respectively. Each block has a 7 bytes Header for data
; and 192 bytes to store the buffer to be saved, giving a total size of 192+7=199 bytes each one. The structure of
; each block is:

;       1 bytes to store length of the buffer saved (max. 192)
;       2 bytes to store a copy of the value of CURSOR (aka CURSOR_B)
;       2 bytes to store a copy of the value of L_HALF (aka L_HALF_B)
;       2 bytes to store a copy of the value of ENDBUF (aka ENDBUF_B)
;     192 bytes to store a copy of the input buffer.

; This routine uses IX register as an indexer for the Header data of each Block. IX = BLOCK# label address (# can be
; 0-3). Then:

;       IX+0 points to Length byte

;       IX+1 points to Low byte of CURSOR_B
;       IX+2 points to High byte of CURSOR_B

;       IX+3 points to Low byte of L_HALF_B
;       IX+4 points to High byte of L_HALF_B

;       IX+5 points to Low byte of ENDBUF_B
;       IX+6 points to High byte of ENDBUR_B

;       There is a Subroutine called GETBLK that when called sets IX to the value correspondign with a given Block
;       number. It waits the Block number (0-3) in Register A

; NOTE: We need to store a copy of the value of INSCRN too, but since while in standard input buffer (SIB) its value
;       is equal to the value of L_HALF always, it is not neccesary to store it.

; NOTE-2: "Standard Input Buffer" (aka SIB) refers to the input buffer while not in EDIT, QUERY, RETYPE, etc. It is
;         detected by checking the size of the Return Stack. Therefore it is important that the system variable RAM
;         is exactly $F920. If changed, this check will fail and the routine will not work when it is supposed to.


                .LIST

                ; JA's System Variables Used:

CURSOR          .EQU    $3C20                   ; Address of the cursor in the input buffer.
L_HALF          .EQU    $3C24                   ; Address of the start of the input buffer.
INSCRN          .EQU    $3C1E                   ; Address of the start of the current logical line
ENDBUF          .EQU    $3C22                   ; Address of the end of the current logical line
KEYCOD          .EQU    $3C26                   ; ASCII last key pressed

                                                ; Note that while in SIB there is only one logical line which can span
                                                ; multiple screen lines.
                                                ; That's why L_HALF and INSCRN are the same in SIB.
                                               
ENDSCR          .EQU    $26FF                   ; Address of video ram's last byte
INTERPT1        .EQU    $0140                   ; Address to continue with Original JA's Interrupt
ORIGIN          .EQU    $F920                   ; Address where the program is to be loaded and where VECTOR has to be.
ORIGIN_A        .EQU    $F9FF                   ; The address where VECTOR_A has to be.

                .ORG    ORIGIN
               
VECTOR:         .WORD   0                       ; Space to store the Interrupt vector. Its address is equal to ORIGIN.
                                                ; This one is called when the machine/emulator uses $nn20

                .ORG    ORIGIN_A
               
VECTOR_A        .WORD   0                       ; Space to store the Interrupt vector. Its address is equal to ORIGIN_A
                                                ; This one is called when the machine/emulator uses $nnFF

KEYFLAG:        .BYTE   0                       ; Flag: SET if <ENTER> is hold pressed.
KEYFLAG2:       .BYTE   0                       ; Flag: SET if <Z+X> are hold pressed.
TEMPOR          .WORD   0                       ; For internal use. (used to copy IX to other pair of registers)
LHALF_S         .WORD   0                       ; For internal use. (tempory store of the shift of L_HALF)
BLOCK:          .BYTE   0                       ; Block's number to copy to (0-3)
BLOCK_R         .BYTE   0                       ; Block's number of the next block to retreave.

                ; Blocks to store up to four input buffers (All 4 precharged whith a space character+cursor)

BLOCK0:         .BYTE   3                       ; Header: Lenght, CURSOR_B, L_HALF_B, ENDBUF_B for BLOCK #0
                .WORD   $26E2,$26E0,$26E3
                .BYTE   0,$20,$97               ; Space to copy corresponding buffer to BLOCK #0
                .FILL   189,$20
               
BLOCK1:         .BYTE   3                       ; Header: Lenght, CURSOR_B, L_HALF_B, ENDBUF_B for BLOCK #1
                .WORD   $26E2,$26E0,$26E3
                .BYTE   0,$20,$97               ; Space to copy corresponding buffer to BLOCK #1
                .FILL   189,$20
               
BLOCK2:         .BYTE   3                       ; Header: Lenght, CURSOR_B, L_HALF_B, ENDBUF_B for BLOCK #2
                .WORD   $26E2,$26E0,$26E3
                .BYTE   0,$20,$97               ; Space to copy corresponding buffer to BLOCK #2
                .FILL   189,$20
               
BLOCK3:         .BYTE   3                       ; Header: Lenght, CURSOR_B, L_HALF_B, ENDBUF_B for BLOCK #3
                .WORD   $26E2,$26E0,$26E3
                .BYTE   0,$20,$97               ; Space to copy corresponding buffer to BLOCK #3
                .FILL   189,$20                 


                ; Interrupt mode 2 Initialization
               
                ; Store in Vector ($nn20=$F920) the value of LINICIO (the vector to the routine
                ; to be executed at each interrupt). The interrupt routine begins at LINICIO   
               
FIRST:          LD      HL,VECTOR               ; HL = $F920
               
                LD      (HL),LINICIO % $100     ; Low byte of LINICIO
                INC     HL
                LD      (HL),LINICIO / $100     ; High byte of LINICIO
               
                LD      HL,(VECTOR)             ; (VECTOR_A) = (VECTOR) -> both vectors point to LINICIO.
                LD      (VECTOR_A),HL
               
                LD      A,VECTOR / $100         ; Set I register to $nn (High byte of VECTOR & VECTOR_A)
                LD      I,A
               
                DI                              ; Interrupt mode 2 is activated.
                IM      2
                EI
               
                JP      (IY)                    ; Back to Forth
               
;----------------------------------------------   INTERRUPT ROUTINE

LINICIO:        DI                              ; Dissable interrupts and save registers.
                PUSH    AF                      ; After our interrupt routine is finished the program will jump to
                EX      AF,AF'                  ; the original JA interrupt routine that, when terminated, will
                PUSH    AF                      ; restore saved registers and enable interrupts.
                PUSH    BC
                PUSH    DE
                PUSH    HL
               
                PUSH    IX                      ; Saves IX. This routine uses IX as an indexer for the Header data.
                       
                LD      HL,ORIGIN - 16          ; Check if we are at standard input buffer,
                OR      A                       ; NOT in any other (QUERY, RETYPE, EDIT, etc.)
                SBC     HL,SP                   ; Test: SP = ORIGIN - 16
               
                JP      NZ,FBREAK               ; Test for a BREAK (ONLY done while NOT in standard input buffer)
               
                ; Test <ENTER> pressed (Input buffer -> Copy)
                               
                LD      A,(KEYCOD)              ; A = ascii code key pressed
                LD      HL,KEYFLAG
                CP      13
                LD      A,(HL)
                JP      NZ,NOTRET               ; Key pressed is NOT <ENTER> key => jump NOTRET
                CP      1
                JP      Z,FINITO                ; If KEYFLAG=1 -> Already evaluated (<ENTER> hold pressed).
                LD      (HL),1                  ; SET KEYFLAG: <ENTER> changed from depressed to pressed.
                                                ; While holding down <ENTER> -> KEYFLAG=1
               
                LD      A,(BLOCK)               
                CALL    GETBLK                  ; IX = Initial Address BLOCK to copy buffer
                                                                               
                ; Get size in bytes of the input buffer
                       
                LD      DE,(L_HALF)             ; DE = Start Input buffer               
                LD      HL,(ENDBUF)             ; HL = End Input buffer = End current logical line
               
                DEC     HL                      ; When SIB is empty, ENDBUFF is 2 bytes greater than L_HALF
                DEC     HL                      ; We decremente ENDBUF by 2, so that the substraction below
                                                ; returns 0 if SIB is empty.
               
                OR      A                       ; Clears Carry flag
                SBC     HL,DE                   ; HL = size in bytes of the input buffer-2
                JP      Z,FORTH                 ; If SIB is empty, ends. (Empty SIB is not stored)
                INC     HL
                INC     HL                      ; HL = Size in bytes of the input buffer       
               
                ; Check that SIB's length is <=  maximum length to copy (192). If greater then set it to 192
               
                PUSH    HL                      ; Save size input buffer
               
                OR      A
                LD      DE,193
                SBC     HL,DE
                POP     DE                      ; DE = Size input buffer
                JP      C,FIT_IN                ; Carry Set if size <= 192
                LD      DE,192                  ; Only 192 first characters saved if size > 192
               
FIT_IN:                                         ; DE = length of the buffer to save (max. 192)

                LD      (IX),E                  ; Save input buffer's length in Block's Header
               
                ; Save length & system variables to Block's Header. Only correct if SIB's Lenght is <= 192.
                ; If not the case it will be corrected later.
               
                LD      HL,(L_HALF)
                ADD     HL,DE                   ; HL = Address of the End of input buffer to copy
               
                LD      (IX+5),L                ; Store ENDBUF_B in Blocks's Header
                LD      (IX+6),H
               
                LD      HL,(L_HALF)             ; Store L_HALF_B in Blocks's Header
                LD      (IX+3),L
                LD      (IX+4),H               
               
                LD      HL,(CURSOR)             ; Store CURSOR_B in Blocks's Header
                LD      (IX+1),L
                LD      (IX+2),H
                                                               
                ; Copy buffer to Block #
               
COPY:           LD      C,E                     ; BC = Number of bytes to copy
                LD      B,0
               
                LD      DE,7
                PUSH    IX                      ; Saves Block Base
                ADD     IX,DE                   ; IX = Initial address block to copy on
                LD      HL,(L_HALF)             ; HL = Start address of the Input buffer
                LD      (TEMPOR),IX
                LD      DE,(TEMPOR)             ; DE = Initial address block to copy on
                LDIR
                               
                POP     IX                      ; IX = Block base
               
                LD      HL,0                    ; Shift = 0 by Default.
                LD      (LHALF_S),HL
               
                ; If length = 192 then set L_HALF_B= $2640 & ENDBUF_B = $2700
               
                LD      A,(IX)
                CP      192
                JP      NZ,NEXT2                ; NZ -> Length <> 192 -> jump
               
                        ; Calculate "possible" shift of input buffer before changing L_HALF_B value to $2640
               
                LD      HL,$2640                ; Future value of L_HALF_B
               
                LD      E,(IX+3)                ; DE = Actual value of L_HALF_B (as stored above)
                LD      D,(IX+4)
                                                ; LHALF_S (Shift) is the # of bytes to be added to L_HALF_B so that
                                                ; the last line of the copied buffer be at bottom screen line.
                OR      A
                SBC     HL,DE
                LD      (LHALF_S),HL            ; Shift stored at LHALF_S for later use.
               
                LD      (IX+3),$40              ; L_HALF_B = $2640
                LD      (IX+4),$26
               
                LD      (IX+5),$00              ; ENDBUF_B = $2700
                LD      (IX+6),$27
               
                ; If CURSOR greater than ENDBUF, then adjust CURSOR to end position.
               
                LD      HL,(L_HALF)             ; DE = L_HALF + 192 = ENDBUF when only 192 chars are taken.
                LD      DE,192
                ADD     HL,DE
                EX      DE,HL                           
               
                LD      HL,(CURSOR)             ; HL = CURSOR
                OR      A
                SBC     HL,DE                   ; Check that cursor is inside de 192 characters to be saved.
                JP      C,IS_OK                 ; Jumps if inside.
               
                LD      (IX+1),$FF              ; CURSOR_B = $26FF Fix cursor position to the end of saved buffer.
                LD      (IX+2),$26
               
                LD      DE,198                  ; 198 = 7 of the Header + 191 to be saved (the "192" pos. is reserved
                                                ; for cursor symbol)
                ADD     IX,DE
                LD      (IX),151                ; Put cursor symbol at CURSOR position (cursor symbol = ascii 151)
                JP      NOT_OK
                       
IS_OK:          LD      L,(IX+1)                ; Add (LHALF_S) to saved CURSOR. LHALF_S contains the "shift".
                LD      H,(IX+2)                ; Shift is 0 if SIB's length is <= 192. If greater, it can be 32, 64,
                LD      DE,(LHALF_S)            ;  ... n*32 depending of SIB's length.
                ADD     HL,DE                   ; It is a correction of the cursor position. It is only neccessary in
                LD      (IX+1),L                ; this case, that is, when SIB is shortenned to fit 192 bytes and
                LD      (IX+2),H                ; cursor was inside it.

NEXT2:
       
                ; Last correction. This is to change the saved buffer so that the last line is on the bottom line.
                ;                  Normally it is, but in some  cases it may not be.
                ; Only neccessary when buffer length < 192. When >= 192 it has been corrected above.
               
                LD      HL,ENDSCR+1
               
                LD      E,(IX+5)        ; DE = ENDBUF_B
                LD      D,(IX+6)
                OR      A
                SBC     HL,DE           ; HL = number of bytes from ENDBUF_B to ENDSCR+1
               
                LD      A,L
                AND     224             ; 224 = Binary 11100000
                LD      L,A             ; HL = (HL/32)*32 (each screen line has 32 chars long)
               
                EX      DE,HL           ; DE = SHIFT
                                        ; The SHIFT to be applied to the saved buffer header values (normally it will
                                        ; be 0). But in the case where you have written an input buffer say 5 lines
                                        ; long, and then deleted the last 3 lines, you have an input buffer two lines
                                        ; long, but it starts 5 lines above the bottom line of the screen, instead of
                                        ; 2 lines above. This is to correct this in the saved copy so that when it is
                                        ; retrieved later, it starts two lines above the bottom line of the screen and
                                        ; not 5 lines above.
               
                LD      L,(IX+1)
                LD      H,(IX+2)
                ADD     HL,DE
                LD      (IX+1),L
                LD      (IX+2),H        ; CURSOR_B = CURSOR_B + SHIFT
               
                LD      L,(IX+3)
                LD      H,(IX+4)
                ADD     HL,DE
                LD      (IX+3),L
                LD      (IX+4),H        ; L_HALF_B = L_HALF_B + SHIFT
               
                LD      L,(IX+5)
                LD      H,(IX+6)
                ADD     HL,DE
                LD      (IX+5),L
                LD      (IX+6),H        ; ENDBUF_B = ENDBUF_B + SHIFT
                       
NOT_OK:
               
                ; Update BLOCK 0->1, 1->2, 2->3, 3->0 (cyclic)
               
                LD      A,(BLOCK)
                INC     A
                CP      4
                JP      NZ,NOTZERO
                XOR     A
NOTZERO:
                LD      (BLOCK),A               ; next Block to be saved.
                LD      (BLOCK_R),A             ; next Block to be retrieved+1.
               
                JP      FORTH                   ; End of interrupt
               
NOTRET:         LD      (HL),0                  ; RESET KEYFLAG: <ENTER> is depressed:
                               
                ; Test Z and X keys pressed at same time. (Copy -> Input buffer)

FINITO:         LD      BC,$FEFE               
                LD      D,0
                IN      E,(C)                   ; Read Keyboard port: Z=bit 2 X=bit 3 (1->off, 0->pressed)
                LD      A,1100B
                AND     E
                LD      HL,KEYFLAG2
                JP      NZ,NOTRET2              ; If (z) -> Z and X pressed at a time.
                LD      A,(HL)
                CP      1
                JP      Z,FORTH                 ; If KEYFLAG2=1 -> Already evaluated. Wait until keys depressed.
                LD      (HL),1                  ; KEYFLAG2 SET -> Z and X keys hold pressed.

                ; Get last buffer saved
               
                LD      A,(BLOCK_R)             ; A = # Block next to save.
                DEC     A                       ; Previous buffer saved is the one to be restored.
                JP      M,ISTHREE               ; if A < 0 then set it to 3 (cyclic 0-3)
                JP      NEXT1
ISTHREE:        LD      A,3
NEXT1:          LD      (BLOCK_R),A             ; Save new BLOCK_R value
               
                LD      A,(BLOCK_R)
                CALL    GETBLK                  ; IX = Block base
                               
                ; Restores Old Buffer Copy
               
                ; Clean actual input buffer before restoring old one
                ; Fill with spaces from Star of SIB to END of Screen.
               
                LD      HL,ENDSCR
                LD      DE,(L_HALF)
                OR      A
                SBC     HL,DE                   ; number of bytes to clean (fill with spaces).
                LD      B,H                     ; Never = 0 (at least will be 31)
                LD      C,L
                LD      HL,ENDSCR
                LD      (HL),$20
                LD      D,H
                LD      E,L
                DEC     DE
                DEC     BC
                LDDR
               
                ; Calculate Address where to copy on
               
                LD      E,(IX+3)
                LD      D,(IX+4)                ; DE = L_HALF_B (input buffer start address)

                PUSH    IX                     
                PUSH    DE                      ; PUSH L_HALF_B
               
                LD      C,(IX)
                LD      B,0                     ; BC = length to copy
               
                LD      DE,7                    ; to skip Header
                ADD     IX,DE                   ; IX = Initial address block to copy from.
                LD      (TEMPOR),IX
                LD      HL,(TEMPOR)             ; HL = Initial address block to copy from.
                POP     DE
                LDIR
               
                ; Restore system variables from copy
               
                POP     IX
               
                LD      E,(IX+1)                ; CURSOR = CURSOR_B
                LD      D,(IX+2)
                LD      (CURSOR),DE

                LD      E,(IX+3)                ; L_HALF = INSCRN = L_HALF_B
                LD      D,(IX+4)
                LD      (L_HALF),DE
                LD      (INSCRN),DE

                LD      E,(IX+5)                ; ENDBUF = ENDBUF_B
                LD      D,(IX+6)
                LD      (ENDBUF),DE
               
                JP      FORTH                   ; Continue with original JA's interrupt.

NOTRET2:        LD      (HL),0                  ; Reset KEYFLAG2: Z and/or X Keys depressed
                JP      FORTH                   ; Conitnue JA's original interupt.
               
FBREAK:                                         
                ; Test for shift+space: Break (Fast->Slow) In any situation except while in input buffer.

                ; >>> Adapted from the ROM Listing at JA archive site <<<
               
                LD      A,$FE                   ; read port $FEFE -
                IN      A,($FE)                 ; keys SPACE, SYMSHIFT, M, N, B.
                RRA                             ; test bit for outermost key
                JP      C,FORTH                 ; Conitnue JA interupt if not pressed.
                LD      A,$7F                   ; read port $7FFE -
                IN      A,($FE)                 ; keys SHIFT, Z, X, C, V.
                RRA                             ; test bit for outermost key
                JP      C,FORTH                 ; Conitnue JA interupt if not pressed.
               
                ; >>> End <<<

                LD      IY,$04C8                ; Sets the Ace to SLOW mode.

FORTH:          POP     IX
                JP      INTERPT1                ; Jump to original interrupt routine of the JA. (avoiding repeat what
                                                ; alreay have been done here (save registers...)
                               
;==============================================         
                ; Subrutine to get BLOCK base fromm Block number making IX = Block base:
                ; 0 -> BLOCK0 .... 3-> BLOCK3
                ; It waits Block # in Register A
               
GETBLK:         CP      0
                JP      NZ,SIG1
                LD      IX,BLOCK0
                RET
SIG1:           CP      1
                JP      NZ,SIG2
                LD      IX,BLOCK1
                RET             
SIG2:           CP      2
                JP      NZ,SIG3
                LD      IX,BLOCK2
                RET             
SIG3:           LD      IX,BLOCK3
                RET
               
; ----------------- Optional code ------------

INTER1:         DI                              ; Interrupt mode 1 activation (must be called from Forth)
                IM      1                       
                EI
                JP      (IY)                    ; Back to Forth
               
                .END


Código: Seleccionar todo


: LIMIT
 -1760 15384 ! QUIT
;
 
: PUTBUFF
 15384 @ -1760 = 0=
 IF
  CR CR ." RAMTOP Incorrect!"
  CR CR ." Use LIMIT before this one."
  CR QUIT
 THEN
 SAVBUFF -194 -1760
 DO
  DUP @ I ! 2+
  2
 +LOOP
 DROP -731 CALL CR CR
 ." Z+X keys to retrieve Old buffer "
 CR ." Up to 4 stored buffers"
 CR CR ." BREAK now works on FAST mode too"
 CR CR
;
 


mfasbrek.tzx
(1.86 KiB) Descargado 5 veces

mfasbrek.tap
(1.84 KiB) Descargado 5 veces

Elurdio
Mensajes: 311
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 74 veces
Agradecimiento recibido: 76 veces

Re: Jupiter Ace Forth: Copia del Búfer de Entrada

Mensajepor Elurdio » 08 Jun 2022 22:51

Hoy he estado estudiando a fondo como funciona la rutina de la ROM del JA que se encarga de escribir el carácter correspondiente a la última tecla pulsada al búfer de entrada (incluyendo la auto-repetición de la tecla si se mantiene pulsada).

Es para hacer que la rutina "Keybeep" (versión simple que comenté no hace mucho en el hilo sobre la interrupción modo 2 del JA ) que emite un pitido a cada pulsación, funcione como es debido y no como lo hace actualmente y que NO me dejó contento.

Bueno, pues me he dado cuenta que la rutina de Copia del Búfer de Entrada (tanto la nueva versión Multi-copia como la anterior) no se ajusta al proceder del JA y puede fallar también:

Si habiendo escrito algo en el búfer de entrada, se pulsa la tecla <ENTER> muy rápidamente, el JA no lo acepta (no se interpreta el input búfer) pero la rutina de Copia sí lo acepta y hace una copia del mismo.

Había pensado en corregirlo, pero como no es nada grave, pues que haya hecho una copia imprevista no tiene mayor importancia, he preferido dejarlo como está. Además, normalmente la tecla <ENTER> se pulsa con contundencia, es raro que se pulse muy rápido.

Lo comento para que quede constancia del BUG, por si "¿alguien?" al usar la rutina se encontrara alguna copia de más inesperada.

Elurdio
Mensajes: 311
Registrado: 07 Dic 2021 21:33
Ubicación: Barcelona
Agradecido : 74 veces
Agradecimiento recibido: 76 veces

Re: Jupiter Ace Forth: Copia del Búfer de Entrada

Mensajepor Elurdio » 21 Jun 2022 11:55

Lo de tener que ejecutar LIMIT y PUTBUFF por separado me resulta un poco incordio. He modificado ligeramente la carga de la rutina para poder ejecutarla con una sola palabra.

Ahora solo hay que ejecutar PUTBUFF.

Eso sí, como PUTBUFF ejecuta QUIT internamente, cualquier cosa que venga a continuación de PUTBUFF en el búfer de entrada se perderá.

El programa consta de dos palabras:

PUTBUFF que carga la rutina y la arranca.
SAVBUFF que contiene la rutina a cargar.

La rutina en código máquina no ha cambiado, es la misma que en MFASBREK, por lo que no la listo de nuevo.

Al igual que con MFASBREK, el programa es válido para los dos casos ($nn20 y $nnFF).

PUTBUFF

Código: Seleccionar todo

: PUTBUFF
 SAVBUFF -194 -1760
 DO
  DUP @ I ! 2+
  2
 +LOOP
 DROP -731 CALL CR CR
 -1760 15384 ! ." Z+X keys to retrieve Old buffer "
 CR ." Up to 4 stored buffers"
 CR CR ." BREAK now works on FAST mode too"
 CR CR QUIT
;
 


putbuff.TZX
(1.8 KiB) Descargado 1 vez


Volver a “Jupiter Ace”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado