Historia de DZX-Forth en 2014

Descripción del contenido de la página

Historia del desarrollo en 2014 de DZX-Forth, un Forth para ZX Spectrum +3e.

Etiquetas:
Esta página muestra apuntes tomados durante el desarrollo de DZX-Forth en 2014.

2014-11-03

Idea: Proyecto DZX-Forth, una adaptación de DX-Forth a ZX Spectrum...

DX-Forth es un Forth moderno para CP/M. Bastaría adaptar el código relacionado con el sistema operativo...

Primeros cambios en las fuentes de Z80 para poder ensamblarlas con Pasmo. Inicio de la versión A-00.

2014-12-15

Reviso el proyecto y hago algunos cambios.

Descubrimiento: Pasmo hace los include antes de los if.

La adaptación de las fuentes será muy difícil sin la documentación del ensamblador original.

2014-12-16

Logro compilar todas las fuentes con Pasmo. Tuve que hacer varios cambios automáticos con Vim, y otros manuales. Necesité consultar un manual de MASM para confirmar algunas instrucciones específicas de la plataforma.

La adaptación de CP/M a ZX Spectrum será larga.

2014-12-17

Para facilitar el trabajo, junto en un solo fichero, <dzx-forth.z80s>, todas las fuentes originales salvo, de momento, <float.z80s>.

Tras hacer los cambios necesarios en el módulo de coma flotante, el ensamblado tuvo éxito.

Tamaño del fichero TAP resultante:

2014-12-18T04-08

La macro header está terminada: adaptada, mejorada y comprobada:

previous_nfa defl  0   ; initial link pointer (end of chain)

_ header macro enabled,name,immediate,fl,alias_xt
  ; enabled  = enable the header? (0=disable)
  ; name = name string
  ; immediate  = immediate
  ; fl  = application/system flag ; XXX OLD not used anymore
  ; XXX TODO remove 'fl' from the macro header calls
  ; alias_xt = alias xt
  if enabled

    ; the name field
    last_nfa defl  $ ; link address for next word
    bits  defl  0
    if not nul immediate
      bits  defl  bits+0x40  ; set immediate bit
    endif
    if not nul alias_xt
      bits  defl  bits+0x80  ; set alias bit
    endif
    local _first ; address of the first char of the name
    local _next  ; address after the last char of the name
    db _next-_first+bits    ; count and flags byte
    _first db  name
    _next

    ; the link field
    dw  previous_nfa

    ; the code field
    if nul alias_xt
      last_xt defl $+2
    else
      last_xt defl alias_xt
    endif
    dw last_xt
    previous_nfa defl  last_nfa

  endif

  endm

2014-12-18T04:37

Ya están corregidas las palabras cuyo código continuaba en el de la palabra siguiente. Esto funcionaba en DX-Forth porque las cabeceras estaban en otra zona de memoria.

2014-12-18T20:50

Tras incorporar los cambios de DX-Forth 4.09, la última versión disponible, y rehacer los cambios perdidos en la operación, el código puede ser compilado de nuevo.

2014-12-19T00:18

Nuevas palabras toupper, lower y tolower para completar upper, que ya existe. Todas van al módulo de cadenas.

También la rutina cls es convertida en una palabra de Forth.

2014-12-19T03:34

Más cambios. Más palabras nuevas. Primera purga de código original anulado desde hace tiempo porque es específico de CP/M e inútil para ZX Spectrum.

Primera prueba de ejecución con una versión de cold que solo cambia el borde y queda en un bucle sin fin. Hasta ahí parece que el intérprete funciona. Pero si añado a cold la palabra decimal, el sistema estalla...

2014-12-20

El problema es que la zona de variables de usuario no está creada. Por eso decimal no funciona: base es una variable de usuario.

Ajustes masivos en el formato del código. Más cambios de nombre de etiquetas. Todo para hacer el código más legible.

Completada la palabra border, que sirve para las pruebas de ejecución.

  _header _public,'BORDER'
border_:
  ; Code based on Lennart Benschop's Spectrum Forth-83 System:
  ;   : BORDER  ( n -- )
  ;     DUP DUP 4 < 7 AND SWAP 8 * + 23624 C! 254 P! ;
  ; This is my translation to Z80:
  pop hl
border_.l:
  if 0

    ; XXX OLD -- the screen will be used as a whole, not like Sinclair BASIC,
    ; so this is not needed.

    ; Set the paper of the bottom screen
    ld a,l
    cp 4 ; dark color?
    jp nc,border_.a
    ; dark color
    sla a
    sla a
    sla a ; *8 (converted to paper_)
    add a,7 ; white ink
    ld (sys_bordcr),a

  endif
  ld a,l
border_.a:
  out (254),a
  jp next

2014-12-22

Completadas las palabras bye, return, key? y key.

2014-12-23

Corregido error grave que arruinaba el intérprete: (next) continuaba su ejecución en la palabra definida a continuación, execute. Esto en DX-Forth era posible, porque las cabeceras estaban separadas.

Completadas las palabras type y bootmessage.

DZX-Forth

2014-12-25

La mayoría de las etiquetas ya tiene nombres significativos. Esto hace el código más legible.

Siguen los trabajos con el mapa de memoria, las variables de usuario y el proceso de arranque en frío.

up (user area pointer) pasa a ser udp (user data pointer), más estándar y claro.

Eliminado el antiguo parámetro fl de las llamadas a la macro hdr.

2014-12-26

Comienza la tarea de adaptar quit, lo que supone reescribir (accept).

2014-12-27

DZX-Forth

(accept) es reescrito desde cero, con varias palabras pequeñas para facilitar su ampliación posterior con más teclas de control.

cf0 es renombrada como cs0, por coherencia con las demás palabras de pila.

Nueva palabra 0<>branch y nuevas etiquetas con sinónimos para las direcciones de ejecución tanto de ella como de ?branch.

Primer borrador de .s, útil durante el desarrollo; después irá en un fichero fuente opcional.

Corregido un error oscuro en 2dup, provocado por un despiste durante la adaptación: todas las conversiones del original dpush están mal: debe meterse en pila también el registro HL. Corrijo la rutina, que ahora llamo push_de_hl. Después busco los puntos en que en la fuente original de DX-Forth se salta a dpush y los corrijo en la fuente de DZX-Forth.

Corregido un error en (of), que continuaba la ejecución en branch suponiendo, como pasaba en DX-Forth, que no había cabecera entre medias.

2014-12-28

Nueva palabra alias, tomada de Gforth; usa el código final de aka. Sería más lógico al revés: Mover ese código a alias y llamarlo desde aka.

; ALIAS  ( xt "newname" -- )

; XXX NEW -- after Gforth; alias doesn't copy the precedence bit of the xt
; XXX TODO -- test

  hdr _public,'ALIAS'
alias:
  call do_colon
  dw lit,-1 ; flag for a not immediate word
  dw branch,aka.alias

; AKA  ( "oldname" "newname" -- )
;   defined tuck ?defined (header)
;   $80 xnfa 0> if immediate then

  hdr _public,'AKA'
aka:
  call do_colon
  dw defined_         ; ( ca|xt -1|0|1 )
  dw tuck             ; save for later
  dw question_defined ; abort if not defined
aka.alias:
  ; ( -1|1 xt "newname" )
  dw header           ; ( -1|1 )
  dw c_lit
  db alias_mask
  dw xnfa             ; set the alias mask of the header
  dw zero_greater     ; is the old word immediate?
  dw branch_if_false,aka.end
  dw immediate        ; make the new word immediate
aka.end:
  dw exit

La corrección de push_de_hl en todo el programa, hecha ayer, permite que funcione la palabra . (el punto), y presumiblemente muchas otras palabras.

2014-12-30

DZX-Forth

Eliminado el código que quedaba del puntero de diccionario de sistema (dph), así como la palabra ?protected, que está relacionada. Esta separación en dos diccionarios no se hará en DZX-Forth.

Corregido un error en (loop), que continuaba su ejecución en unloop sin tener en cuenta la cabecera, que en DX-Forth no estaba en medio.

Despiste en el original: el salto a inte3 puede ser directo a inte14:

  dw  bran,inte3
inte2:  dw  exec
inte3:  dw  bran,inte14
inte4:  dw  count
  dw  base,at,tor

Palabras que cambian de nombre:

En <dzx-forth.z80s>:

En <tools.fs>:

Cambio las extensiones predeterminadas de ficheros fuente (.FB y .FS en lugar de .SCR y .F).