BBimport
Descripción del contenido de la página
Programa para importar en el intérprete de Beta BASIC un código fuente creado en el sistema anfitrión del emulador de ZX Spectrum.
BBimport es el último eslabón de la utilería BBim. Es un programa en Beta BASIC que importa en la ZX Spectrum el código en formato BBim, preparado por BBim2BB.
Hay seis versiones del programa, cuyas características se detallan a continuación. La última versión es la recomendada.
Comandos y errores durante la importación
El programa BBim2BB elimina los números de línea de aquellas líneas que comiencen por el signo de dos puntos («:»). Esto permite incluir en el código fuente comandos de Beta BASIC que se ejecutarán durante la importación.
Esto por ejemplo permite ejecutar, al final del código, una línea para borrar las líneas de BBimport y grabar en disco el programa recién importado. Como cabe esperar, tras ejecutar esos comandos Beta BASIC provoca un error porque la línea de BBimport que estaba siendo ejecutado ha sido borrada. Pero eso no quiere decir que la importación haya fallado. Un ejemplo puede verse a continuación en los pantallazos.
Cuando durante la importación se produce un error debido a una línea con sintaxis errónea que KEYIN
no puede interpretar, el programa se detendrá con el mensaje correspondiente. La línea causante de un error de sintaxis estará en la variable l$
.
Otro tipo de errores detectados durante el proceso provocaran que el programa se detenga con un simple STOP
.
Pantallazos
Hasta la versión BBimport 4, el método para mostrar el código fuente que está siendo leído es el siguiente: Las líneas interpretadas se sobreescriben en la misma posición de pantalla, bajo la zona de almacenamiento de los sectores del disco, y a continuación se borra el equivalente a dos saltos de tabulación para facilitar la lectura. Pero a pesar de usar un juego de caracteres de 4x8 puntos, las líneas muy largas pueden llegar al final de la pantalla y provocar el mensaje de confirmación de desplazamiento, desplazamiento que evidentemente corrompe el almacén de sectores.
La siguiente imagen muestra este fallo, que fue corregido en BBimport 4a:
La siguiente imagen muestra BBimport 5 durante el proceso de importación. Como siempre, la parte superior de la pantalla se usa como almacén del contenido de los sectores del disquete, pero las líneas importadas se muestran en una ventana independiente:
La siguiente imagen muestra el final exitoso del proceso de importación, con un mensaje de error causado por el comando que ha borrado las líneas del propio BBimport 5 (la línea que comienza por delete 59 to
:
Código fuente
BBimport 1
BBimport 1 importa el código desde una falsa imagen de disquete MGT. Es una traducción del programa análogo MBimport 2 de MBim.
BBimport 1 no resultó útil porque el comando LOAD@
de Beta DOS hace inestable el sistema cuando se ejecuta en procedimientos, bucles o subrutinas en Beta BASIC. Para soslayar este inconveniente se escribió BBimport 3.
1 REM BBimport 1
(C) 2011 Marcos Cruz (programandala.net)
2 DEF PROC import drive
3 DEFAULT drive=2
4 LOCAL buffer,sectorLen,bufferLen,l$,buffer,bufferEnd,c$,endOfSource,side,track,sector,sliceStart,CRPos,lastTrack
5 LET c$=CHR$ VAL "13",endOfSource=NOT PI,buffer=VAL "22528",sectorLen=VAL "512",bufferLen=sectorLen+SGN PI,bufferEnd=buffer+sectorLen-SGN PI,side=NOT PI,track=NOT PI,sector=SGN PI,CRPos=NOT PI,lastTrack=CODE " CAT "
6 loadSector
7 DO
8 diskTo l$
9 EXIT IF endOfSource
10 PRINT AT 0,0;lineN
11 PRINT l$
PAUSE NOT PI
12 LOOP
13 END PROC
14 DEF PROC diskTo REF l$
15 LET l$=""
16 IF NOT PEEK sliceStart THEN LET endOfSource=SGN PI
GO TO 21
17 DO
18 LET crPos=INSTRING(1,MEMORY$()(sliceStart TO bufferEnd),c$)
19 IF crPos
LET l$=l$+MEMORY$()(sliceStart TO crPos-1)
IF crPos=bufferEnd THEN feedBuffer
ELSE LET sliceStart=crPos+1
ELSE LET l$=l$+MEMORY$()(sliceStart TO bufferEnd)
feedBuffer
20 LOOP UNTIL crPos
21 END PROC
22 DEF PROC feedBuffer
nextSector
loadSector
END PROC
23 DEF PROC loadsector d,t,s
24 DEFAULT d=drive,t=track,s=sector
25 PRINT t,s
REM LOAD @d,t,s,buffer,1
26 LET sliceStart=buffer
27 END PROC
28 DEF PROC nextSector
29 IF 10>sector THEN LET sector=sector+1
ELSE nextTrack
30 END PROC
31 DEF PROC nextTrack
32 IF track=lastTrack THEN wipeBuffer
LET endOfSource=SGN PI
GO TO 35
33 IF 80>track THEN doSide1 track
ELSE doSide0 track
LET track=track+1
34 LET sector=1
35 END PROC
36 DEF PROC doSide1 REF track
LET track=track+128
END PROC
37 DEF PROC doSide0 REF track
LET track=track-128
END PROC
38 DEF PROC r
RENUM LINE SGN PI STEP SGN PI
END PROC
39 DEF PROC s
ERASE d*"BBimport1!"
ERASE d*"BBimport1" TO "BBimport1!"
SAVE d*"BBimport1"
END PROC
BBimport 2
BBimport 2 emplea un método diferente de importación: lee el código fuente como un fichero secuencial desde un disquete MGT, fichero previamente creado con la extensión .bb por BBim2BB y que debe ser después introducido en el disquete con ayuda de una herramienta como SAM Diskimage Manager. Sin embargo, ciertos problemas (descritos en el historial de desarrollo) hicieron impracticable este método.
1 REM BBimport 2
(C) 2011 Marcos Cruz (programandala.net)
2 INPUT "Drive: ";d,"File:"; LINE f$
CLOSE #*
OPEN #VAL "4",dd;f$RND
FOR n=SGN PI TO VAL "9"
LET l$=INKEY$#VAL "4"
NEXT n
3 INPUT #VAL "4"; LINE l$
PRINT AT NOT PI,NOT PI;l$,,
KEYIN l$
GO TO 3
4 DEF PROC s
ERASE d*"BBimport2!"
ERASE d*"BBimport2" TO "BBimport2!"
RENUM LINE SGN PI STEP SGN PI
SAVE d*"BBimport2"
END PROC
BBimport 3
BBimport 3 es una versión de BBimport 1 en que el bucle principal está fuera de un procedimiento y en lugar de bucles se usan saltos de línea. Esto evita los problema que crean ciertos comandos de Beta DOS cuando se ejecutan en procedimientos, bucles o subrutinas de Beta BASIC.
9990 REM BBimport 3
(C) 2011 Marcos Cruz (programandala.net)
9991 LET buffer=VAL "16384",drive=VAL "2",bufferEnd=buffer+VAL "511",track=NOT PI,sector=SGN PI,l$=""
9992 LOAD @drive,track,sector,buffer
LET chunk=buffer
IF NOT PEEK chunk THEN STOP
9993 LET crPos=INSTRING(SGN PI,MEMORY$()(chunk TO bufferEnd),CHR$ VAL "13")
IF crPos THEN LET l$=l$+MEMORY$()(chunk TO chunk+crPos-VAL "2")
IF crPos=bufferEnd THEN nextSector
LOAD @drive,track,sector,buffer
LET chunk=buffer
ELSE LET chunk=chunk+crPos
ELSE LET l$=l$+MEMORY$()(chunk TO bufferEnd)
nextSector
GO TO 9992
9994 PRINT AT VAL "9",NOT PI;l$,,
KEYIN l$
LET l$=""
GO TO 9993
9995 DEF PROC nextSector
IF VAL "10">sector THEN LET sector=sector+SGN PI
ELSE LET sector=SGN PI
IF track=VAL "207" THEN STOP
ELSE IF VAL "80">track THEN LET track=track+VAL "128"
ELSE LET track=track-VAL "127"
9996 END PROC
9997 DEF PROC s
SAVE d*"BBimport3"
END PROC
BBimport 4
BBimport 4 es una versión más rápida de BBimport 3, pues no lee los sectores del disco de uno en uno sino en grupos de cinco. Esta fue la versión utilizada en el desarrollo de La legionela del pisto hasta que se produjo un oscuro error en la importación de uno de los módulos, para cuya investigación se creó la versión BBimport 5.
9990 REM BBimport 4
(C) 2011 Marcos Cruz (programandala.net)
9991 LET buffer=VAL "16384",drive=VAL "2",bufferEnd=buffer+VAL "2559",track=NOT PI,sector=SGN PI,l$=""
9992 LOAD @drive,track,sector,buffer,VAL "5"
LET chunk=buffer
IF NOT PEEK chunk THEN STOP
9993 LET crPos=INSTRING(SGN PI,MEMORY$()(chunk TO bufferEnd),CHR$ VAL "13")
IF crPos THEN LET l$=l$+MEMORY$()(chunk TO chunk+crPos-VAL "2")
IF crPos=bufferEnd THEN next5sectors
LOAD @drive,track,sector,buffer,VAL "5"
LET chunk=buffer
ELSE LET chunk=chunk+crPos
ELSE LET l$=l$+MEMORY$()(chunk TO bufferEnd)
next5sectors
GO TO 9992
9994 PRINT CSIZE VAL "4",VAL "8";AT VAL "16",NOT PI;l$,,
KEYIN l$
LET l$=""
GO TO 9993
9995 DEF PROC next5sectors
IF sector=SGN PI THEN LET sector=VAL "6"
ELSE LET sector=SGN PI
IF track=VAL "207" THEN STOP
ELSE IF VAL "80">track THEN LET track=track+VAL "128"
ELSE LET track=track-VAL "127"
9996 END PROC
9997 DEF PROC s
SAVE d*"BBimport4"
END PROC
BBimport 4a
BBimport 4a es una modificación de BBimport 4, que fue necesaria para poder importar BBimport 5: imprime las líneas en una ventana. Sin este cambio las líneas muy largas provocaban un desplazamiento de pantalla que corrompía la informacíon leída del disco.
9990 REM BBimport 4a
(C) 2011,2012 Marcos Cruz (programandala.net)
9991 WINDOW SGN PI,NOT PI,CODE "/",VAL "256",CODE "0"
WINDOW SGN PI
LET buffer=VAL "16384",drive=VAL "2",bufferEnd=buffer+VAL "2559",track=NOT PI,sector=SGN PI,l$=""
9992 LOAD @drive,track,sector,buffer,VAL "5"
LET chunk=buffer
IF NOT PEEK chunk THEN STOP
9993 LET crPos=INSTRING(SGN PI,MEMORY$()(chunk TO bufferEnd),CHR$ VAL "13")
IF crPos THEN LET l$=l$+MEMORY$()(chunk TO chunk+crPos-VAL "2")
IF crPos=bufferEnd THEN next5sectors
LOAD @drive,track,sector,buffer,VAL "5"
LET chunk=buffer
ELSE LET chunk=chunk+crPos
ELSE LET l$=l$+MEMORY$()(chunk TO bufferEnd)
next5sectors
GO TO 9992
9994 POKE VAL "23692",CODE " COPY "
PRINT l$
KEYIN l$
LET l$=""
GO TO 9993
9995 DEF PROC next5sectors
IF sector=SGN PI THEN LET sector=VAL "6"
ELSE LET sector=SGN PI
IF track=VAL "207" THEN STOP
ELSE IF VAL "80">track THEN LET track=track+VAL "128"
ELSE LET track=track-VAL "127"
9996 END PROC
9997 DEF PROC s
SAVE d1"BBimport4a"
END PROC
BBimport 5
BBimport 5 empezó como una traducción de BBimport 4 al formato BBim, con el objetivo de manejar mejor el código y encontrar la oscura causa de un error que se producía durante la importación de un módulo de La legionela del pisto. Sorprendentemente, usando esta versión el problema desapareció, sin hacer ningún cambio, al menos conscientemente.
Esta es pues la versión recomendada.
/*
BBimport 5
Copyright (C) 2012 Marcos Cruz (programandala.net)
Licence:
http://programandala.net/license
This file is part of BBim:
http://programandala.net/es.programa.bbim
2011-03-07 First version (BBimport 4 converted to BBim).
2012-03-09 Added WINDOW ERASE at the end.
*/
rem BBimport 5 (C) 2012 programandala.net
// *****************************
// Metacommands
// Convert long variable and procedure names to short ones.
// It saves memory and execution time.
#vim %substitute/\<bufferEnd\>/be/gI
#vim %substitute/\<bufferPointer\>/bp/gI
#vim %substitute/\<buffer\>/b/gI
#vim %substitute/\<commandLenght\>/l/gI
#vim %substitute/\<command\$/c$/gI
#vim %substitute/\<crPosition\>/p/gI
#vim %substitute/\<drive\>/d/gI
#vim %substitute/\<line\$/l$/gI
#vim %substitute/\<pointToNext5sectors\>/n5/gI
#vim %substitute/\<sector\>/s/gI
#vim %substitute/\<track\>/t/gI
// *****************************
// Init
let \
buffer=val "16384",\ // The screen is used as buffer.
bufferEnd=buffer+val "2559",\ // Space for 5 disk sectors.
drive=val "2",\ // The source must be in the second drive.
track=not pi,\ // Tracks are 0-79.
sector=sgn pi,\ // Sectors are 1-10.
line$="":\ // Source line to be interpreted.
// Output window
// (below the screen region used as buffer)
window erase:\
window sgn pi,\
not pi,code"/",\ // Top left corner: x=0 and y=47.
val"256",code"0":\ // Size: width=256 and height=48.
window sgn pi
// *****************************
// Main loop
label @load5sectors:\
load @drive,track,sector,buffer,val "5":\
let bufferPointer=buffer:\
if not peek bufferPointer then \
// The sectors are empty. There is no more source code.
window erase:stop
label @searchForEndOfLine:\
let crPosition=instring(sgn pi,memory$()(bufferPointer to bufferEnd),chr$ val "13"):\
if crPosition then \
// The end of the line was found.
let line$=line$+memory$()(bufferPointer to bufferPointer+crPosition-val "2"):\
if crPosition=bufferEnd then \
// The end of line is the last byte of the buffer.
pointToNext5sectors:\
load @drive,track,sector,buffer,val "5":\
let bufferPointer=buffer:\
else \
let bufferPointer=bufferPointer+crPosition:\
else \
// The end of the line was not found yet.
let line$=line$+memory$()(bufferPointer to bufferEnd):\
pointToNext5sectors:\
goto @load5sectors
// The source line is ready.
// Force endless scrolling,
// poking the ZX Spectrum variable SCR_CT with 255:
poke val "23692",code "\#255":\
//
print line$:\
keyin line$:\
let line$="":\
goto @searchForEndOfLine
// *****************************
// Disk sector position
defproc pointToNext5sectors:\
/*
Update the sector and track numbers
in order to load the next five sectors.
*/
if sector=sgn pi then \
// Point to the second half of the current track.
let sector=val "6":\
else \
// Point to the first half of the next track.
let sector=sgn pi:\
if track=code "\#207" then \ // track=207?
// No more tracks. The source code is too big.
stop:\
else \
// Next track (and change the disk side).
if track < code "\#80" then \ // track<80?
let track=track + code "\#128":\ // Add 128.
else \
let track=track - code "\#127" // Substract 127.
endproc
// *****************************
// Import-time commands:
// This version doesn't work fine:
#:\
# delete 9990 to:\ // Remove the import program used.
# renum line 9990 step 1:\ // Occupy its position.
# save over d1"BBimport5"
// Manual alternative:
:\
cls:print \
"Type in the following commands:"'\
"DELETE 9990 TO"'\
"RENUM LINE 9990 STEP 1"'\
"SAVE OVER D1""BBIMPORT5"""
Descargas
Imágenes de disquete de Plus D:
- bbimport.mgt.gz (95.08 KiB): Imagen de disquete comprimida con gzip.
- bbimport.mgt.zip (94.60 KiB): Imagen de disquete comprimida con zip.
- bbimport_5.bbim (3.52 KiB): Código fuente de BBimport 5 en el formato BBim original.
- Beta DOS 1.3 (1990), corregido con los programas Betafix publicados en las publicaciones Format (número 9/9, de 1996-05) y Outlet (número 132, de 1998).
- Beta BASIC 4.0+D (1987), para ZX Spectrum 128 con interfaz Plus D.
Todos los componentes de BBim pueden descargarse en la sección de descargas de BBim.