dBASE-II Lite para ORIC

dancresp
Mensajes: 5336
Registrado: 13 Nov 2010 02:08
Agradecido : 150 veces
Agradecimiento recibido: 287 veces

dBASE-II Lite para ORIC

Mensajepor dancresp » 29 Abr 2015 09:29

dBaseII-1.gif
dBaseII-1.gif (54.99 KiB) Visto 1604 veces


En los inicios de la informática doméstica apareció un programa que permitió que tanto usuarios particulares como profesionales pudieran crear de una forma sencilla bases de datos relacionales y aplicaciones que permitían el acceso a estos datos.

Este programa lo lanzó la empresa Ashton-Tate con el nombre de dBASE II, a pesar de que nunca existió una versión I, pensando que esto le daba una imagen de producto más consolidado.

Rápidamente el programa fue un éxito y se traslado a muchos equipos basados en sistemas operativos CP/M y MS-DOS.


COMANDOS DISPONIBLES
Disponemos de una línea de comandos, indicada con el carácter “.”, donde vamos introduciendo los distintos comandos que queremos ejecutar.

Esta versión admite 16 comandos del dBASE II original. Son los necesarios para definir y manipular bases de datos, pero se ha prescindido de los índices y la parte de programación.

CREATE
Este comando nos permite crear una base de datos. Al ejecutarlo, entramos en modo de diseño, y se han de introducir los campos, de uno en uno y separados por coma, con el siguiente formato: nombre, tipo, longitud, decimales.

Hay 2 tipos de datos:
N - Numérico.
C - Alfanumérico.

Esta versión nos permite definir hasta 20 campos por base de datos, y los campos pueden tener un nombre de hasta 10 caracteres.

Los campos alfanuméricos admiten hasta 25 caracteres, en lugar de los 254 del original, y los numéricos hasta 10 dígitos.
Solo hay que especificar los decimales en los campos que los precisen.
Si hay algún error nos avisa, y nos permite volver a introducir los valores del campo.

Forma de uso:
CREATE EJEMPLO

USE
Abre la base de datos indicada. Para ello es preciso poner en marcha el casete y esperar a que se cargue en memoria.
Si ya hay una base de datos activa se pedirá si se quiere volcar el contenido a una cinta de casete, antes de abrir la nueva.

Forma de uso:
USE EJEMPLO

APPEND
Permite introducir un nuevo registro al final de la base de datos activa.
En la pantalla aparecen los distintos campos y el espacio para introducir los valores.

Forma de uso:
APPEND

INSERT
Inserta un registro a continuación del registro activo.
En la pantalla aparecen los distintos campos y el espacio para introducir los valores.

Forma de uso:
INSERT

EDIT
Este comando permite editar el registro indicado.

Forma de uso:
EDIT 5

DELETE
Marca como borrados registros de la base de datos activa. Estos registros siguen visibles, pero aparece un “*” a continuación del número de registro al hacer un LIST.

Forma de uso:
DELETE : Marca el registro activo.
DELETE ALL : Marca todos los registros de la base de datos.
DELETE NEXT 5 : Marca 5 registros a partir del registro activo.
DELETE RECORD 5 : Marca el registro número 5.

RECALL
Este comando desmarca registros marcados como borrados.

Forma de uso:
RECALL : Desmarca el registro activo.
RECALL ALL : Desmarca todos los registros de la base de datos.
RECALL NEXT 5 : Desmarca 5 registros a partir del registro activo.
RECALL RECORD 5 : Desmarca el registro número 5.

SET DELETED
Activa o desactiva la visualización y acceso a los registros marcados como borrados.

Forma de uso:
SET DELETED ON : Los registros marcados no son visibles ni accesibles.
SET DELETED OFF : Los registros marcados están visibles y accesibles.

COUNT
Muestra el número total de registros de la base de datos activa, incluyendo los marcados como borrados.

Forma de uso:
COUNT

PACK
Este comando elimina todos los registros marcados como borrados, actualiza el contador de registros y reduce el tamaño que ocupa la base de datos.

Posteriormente no hay posibilidad de recuperar los registros borrados.

Forma de uso:
PACK

LIST
Lista los registros o estructura de la base de datos por pantalla, entre otras funciones especiales.

Forma de uso:
LIST : Muestra todos los registros de la base de datos.
LIST ALL : Igual que LIST.
LIST NEXT 5 : Muestra 5 registros a partir del registro activo.
LIST RECORD 5 : Muestra el registro número 5.
LIST STRUCT: Muestra la estructura de la base de datos.

DISPLAY
Este comando es "casi" idéntico a LIST y funciona con los mismos parámetros.

Forma de uso:
DISPLAY : Muestra el registro activo.
DISPLAY ALL : Igual que LIST.
DISPLAY NEXT 5 : Muestra 5 registros a partir del registro activo.
DISPLAY RECORD 5 : Muestra el registro número 5.

GO
Posiciona el puntero en el número de registro indicado. Permite los parámetros TOP y BOTTOM, para ir al primer o último registro de la base de datos.

Forma de uso:
GO 5 : Nos posicionamos en el registro 5.
GO TOP : Nos posicionamos en el primer registro.
GO BOTTOM : Nos posicionamos en el último registro.

SKIP
Mueve el puntero del registro activo en función del número indicado.

Forma de uso:
SKIP 2 : Avanzamos dos registros a partir del registro activo.
SKIP -2 : Retrocedemos dos registros a partir del registro activo.

SORT ON
Este comando genera un fichero de base de datos con los registros ordenados por el campo indicado. Los registros quedan renumerados en función del nuevo orden. La base de datos original queda inalterada.
A diferencia del original, solo permite ordenar por un único campo, ya sea numérico o alfanumérico.

Si se desea que el orden sea descendente, se debe usar DESCENDING a continuación del nombre del fichero.

Forma de uso:
SORT ON campo TO basedatos
SORT ON campo TO basedatos DESCENDING

QUIT
Sale de dBASE II y vuelve al sistema operativo. Este comando, previa confirmación, vuelca el contenido de la memoria en la cinta de casete. Abandonar el programa de otra forma provocará la perdida de los datos.

Imagen

Descargar dBASE II en formato TAP:
dBASE-II_ORIC.rar
(7.74 KiB) Descargado 69 veces


¿COMO FUNCIONA?
Este proyecto se ha organizado para que ocupe lo mínimo y funcione lo más rápido posible. El resultado es un programa de unos 8 KB, que deja unos 36 KB libres para datos.

Variables principales
Para ganar velocidad me he limitado a usar variables con nombres de una única letra, excepto con la "E".

C$() : Matriz donde se almacenan los comandos disponibles.
D$ : Nombre de la base de datos activa.
L$ : Línea de entrada de comandos.
P$() : Matriz de los parámetros introducidos.
R : Número de registros en la base de datos.
S$() : Matriz con todos los registros de la base de datos.
T : Número de campos de la base de datos.
U : Visualizar (1) o Ocultar (0) los registros marcados como borrados.
V : Número de registro activo.
W$() : Matriz de campos durante la edición de un registro.
X$ : Fecha de entrada a dBASE II.
Y$ : Fecha última actualización de la base de datos.
E1$() : Matriz de Nombres de los campos.
E2$() : Matriz de Tipos de los campos.
E3$() : Matriz de Tamaño de los campos.
E4$() : Matriz de Decimales de los campos numéricos.
El resto de las variables pueden tener distintos usos.


EL LISTADO

Código: Seleccionar todo

       Punteros de Memoria de Variables y Matrices
    1 GRAB:DOKE#9C,10000:DOKE#9E,10000:DOKE#A0,10000:DOKE#A2,99
       DATA con los Comandos y Saltos a rutinas de Comandos
    2 DATA"CREATE","USE","QUIT","APPEND","INSERT","EDIT","DELETE","SET"
    3 DATA "RECALL","COUNT","PACK","LIST","GO","SKIP","DISPLAY","SORT"
    4 DATA 4200,4600,5000,2100,2000,2200,3600,3500
    5 DATA 3700,3400,3900,2800,3200,3300,2800,4000
    6 X$="                         "
       Declaración de matrices
   10 DIMJ(16),C$(16),P$(6),E1$(20),E2$(20),E3$(20),E4$(20),N$(20),S$(512)
  100 GOSUB 9000
 
       Entrada de Comandos
  200 PRINT". ";:GOSUB1500:IFL$=""THEN200ELSEB$=" ":N=6:GOSUB1000:I=0
  230 FORF=1TO16:IFP$(1)=C$(F)THENI=F:F=16
  250 NEXT:IFI=0THEN1200
  270 IFD$<>""ORI<4THEN280
  275 PRINT"No database in use, enter filename:":GOSUB1500:IFL$=""THEN200
  276 N=2:GOSUB1000:P$(2)=P$(1):GOTO4605
  280 IFI>3ANDI<7THENPRINTCHR$(17)
  285 IFI>0ANDI<17THENGOTOJ(I)ELSE200
 
       Separar Valores
 1000 I=1:L$=L$+" ":FORF=1TON:P$(F)="":NEXT
 1010 FORF=1TOLEN(L$)
 1020 A$=MID$(L$,F,1):IFA$=B$ANDI<NTHENI=I+1ELSEP$(I)=P$(I)+A$
 1030 NEXT:RETURN
       Formatear Número
 1100 PRINTRIGHT$("00000"+MID$(STR$(N),2),J);:RETURN
       Imprimir Errores
 1200 PRINT"*** Unknown command":PRINTP$(1):GOTO200
       Rutina de INPUT alternativa
 1500 L$=""
 1505 GETB$:F=ASC(B$):IFF>31ANDF<127THEN1530
 1510 IFF=13THENPRINT:RETURN
 1515 REM IFF<32ORF>127THEN1505
 1516 IFF<32ANDF<>3THEN1505
 1520 IFL$=""THEN1505ELSEL$=LEFT$(L$,LEN(L$)-1):PRINTB$;:GOTO1505
 1530 IFLEN(L$)<35THENL$=L$+B$:PRINTB$;
 1540 GOTO1505

       Comando INSERT
 2000 FORF=R+1TOV+1STEP-1:S$(F)=S$(F-1):NEXT
       Comando APPEND
 2100 IFP$(1)="APPEND"THENV=R+1ELSEV=V+1
 2110 R=R+1:S$(V)=" "
 2120 FORF=1TOT:S$(V)=S$(V)+" "+MID$(X$,1,VAL(E3$(F))):NEXT:GOTO2240
       Comando EDIT
 2200 IFR=0THEN200
 2210 N=VAL(P$(2)):IFN=0THENPRINT"Enter record # : ";:GOSUB1500:N=VAL(L$)
 2220 IFN>RTHENPRINT"Record out of range":GOTO200
 2230 IFN=0THENV=RELSEV=N
 2240 CLS:PRINT"RECORD # ";:J=5:N=V:GOSUB1100:PRINT:J=3
 2250 FORF=1TOT:W$(F)=MID$(S$(V),J,VAL(E3$(F))):J=J+VAL(E3$(F))+1
 2260 PRINTE1$(F);TAB(12);"| ";LEFT$(W$(F),25);"|":NEXT:F=0:J=1
 2300 IFF=0THENA$="_"+W$(J)ELSEA$=LEFT$(W$(J),F)+"_"+MID$(W$(J),F+1)
 2310 A$=LEFT$(A$,VAL(E3$(J))+1):PLOT13,J,A$
 2320 GETA$:IFA$<>CHR$(27)THEN2360
 2330 IFP$(1)="APPEND"THENV=V-1:R=R-1
 2350 CLS:PRINTCHR$(17):GOTO200
 2360 K=ASC(A$):IFK<32ORK>126THEN2410
 2380 IFF=0THENW$(J)=A$+W$(J)ELSEW$(J)=LEFT$(W$(J),F)+A$+MID$(W$(J),F+1)
 2390 W$(J)=LEFT$(W$(J),VAL(E3$(J))):F=F+1:GOTO2300
 2410 IFK=11THENGOSUB2530:J=J-1:GOTO2460
 2420 IFK=10ORK=13THENGOSUB2530:J=J+1:GOTO2460
 2430 IFK=8ANDF>0THENF=F-1
 2440 IFK=9ANDF<VAL(E3$(J))THENF=F+1
 2450 IFK=127ANDF>0THENW$(J)=LEFT$(W$(J),F-1)+MID$(W$(J),F+1)+" ":F=F-1:GOTO2300
 2460 IFJ=0THENJ=1ELSE2470
 2465 IFV<2THEN2240ELSEGOSUB2500:V=V-1:GOTO2240
 2470 IFJ<=TTHEN2300
 2475 GOSUB2500:IFV<RTHENV=V+1:GOTO2240
 2480 IFP$(1)="APPEND"THEN2100ELSECLS:PRINTCHR$(17):GOTO200
 2500 S$(V)=LEFT$(S$(V),1):FORI=1TOT:S$(V)=S$(V)+" "+W$(I):NEXT:RETURN
 2530 IFE2$(J)<>"N"THEN2560
 2540 N=VAL(W$(J)):I=VAL(E4$(J)):IFI<>0THENF=10^I:N=INT(N*F)/F
 2550 W$(J)=RIGHT$("         "+STR$(N),VAL(E3$(J)))
 2560 F=0:PLOT13,J," "+W$(J):RETURN

       Comando LIST y DISPLAY
 2800 IFLEFT$(P$(2),4)="STRU"THEN2910
 2810 IFP$(2)="ALL"THENF=1:I=R:GOTO2850
 2820 IFP$(2)="NEXT"THENF=V:I=F+VAL(P$(3))-1:GOTO2850
 2830 IFP$(2)="RECORD"THENF=VAL(P$(3)):I=F:GOTO2850
 2840 IFP$(1)="LIST"THENF=1:I=R
 2850 IFI>RTHENI=R
 2860 FORF=FTOI:A$=LEFT$(S$(F),1):IFA$="*"ANDU=0THEN2890
 2880 J=5:N=F:GOSUB1100:PRINT" ";S$(F):PRINT:V=F
 2890 NEXT:GOTO200
       Comando LIST STRUCT
 2910 PRINT"Structure for file: ";D$
 2915 PRINT"Number of records:";:J=5:N=R:GOSUB1100:PRINT
 2920 PRINT"Date of last update: ";Y$:PRINT"Primary use database"
 2930 PRINT "Fld     Name         Type Width  Dec":I=0
 2940 FORF=1TOT:J=3:N=F:GOSUB1100
 2960 PRINTTAB(10);E1$(F);TAB(23);E2$(F);
 2970 PRINTTAB(28);:J=3:N=VAL(E3$(F)):GOSUB1100
 2980 IFVAL(E4$(F))<>0THENPRINTTAB(35);:J=3:N=VAL(E4$(F)):GOSUB1100
 2990 PRINT:I=I+VAL(E3$(F)):NEXT
 3010 PRINT"** Total **";TAB(26);:J=5:N=I:GOSUB1100:PRINT:GOTO200
 
       Comando GO
 3200 IFP$(2)="TOP"THENV=1:GOTO3220
 3210 IFP$(2)="BOTTOM"THENV=RELSEV=VAL(P$(2))
 3220 IFV>RTHENV=R:GOTO3230
 3225 IFV<1THENV=1
 3230 PRINT"Record: ";:J=5:N=V:GOSUB1100:PRINT:GOTO200
 
       Comando SKIP
 3300 N=VAL(P$(2)):IFN=0THENN=1
 3310 V=V+N:GOTO200
 
       Comando COUNT
 3400 PRINT"Count =  ";:J=5:N=R:GOSUB1100:PRINT:GOTO200
 3500 IFP$(2)="DELETED"ANDP$(3)="ON"THENU=1:GOTO200
 3510 IFP$(2)="DELETED"ANDP$(3)="OFF"THENU=0:GOTO200
 3520 GOTO1200
 
       Comando DELETE
 3600 A$=" ":B$="*":GOTO3710
       Comando RECALL
 3700 A$="*":B$=" "
 3710 IFP$(2)="ALL"THENF=1:I=R:GOTO3750
 3720 IFP$(2)="NEXT"THENF=V:I=F+VAL(P$(3))-1:GOTO3750
 3730 IFP$(2)="RECORD"THENF=VAL(P$(3)):I=F:GOTO3750
 3740 F=VAL(P$(2)):IFFTHEN1200ELSEF=V:I=F
 3750 K=0:IFI>RTHENI=R
 3760 FORF=FTOI
 3770 IFLEFT$(S$(F),1)=A$THENS$(F)=B$+MID$(S$(F),2):K=K+1
 3780 NEXT:J=5:N=K:GOSUB1100
 3800 IFA$="*"THENPRINT" recall(s)"ELSEPRINT" deletion(s)"
 3810 GOTO200
 
       Comando PACK
 3900 I=0:FORF=1TOR:IFLEFT$(S$(F),1)=" "THENI=I+1:S$(I)=S$(F)
 3930 NEXT:PRINT"Pack complete ";:J=5:N=I:GOSUB1100
 3950 PRINT" records copied":R=I:V=I:GOTO200

       Comando SORT ON
 4000 IFP$(2)<>"ON"ORP$(4)<>"TO"THEN1200
 4010 A$=P$(3):D$=P$(5):N=0:J=2
 4020 IFLEFT$(P$(6),4)="DESC"THENI=1ELSEI=0
 4030 FORF=1TOT:IFA$=E1$(F)THENN=F:F=T+1
 4040 J=J+VAL(E3$(F))+1:NEXT:IFN=0THEN1200ELSEN=VAL(E3$(N))
 4080 FORF=1TOR:FORK=1TOR
 4090 A$=MID$(S$(K),J,N):B$=MID$(S$(F),J,N):IFI=1THENL$=A$:A$=B$:B$=L$
 4120 IFA$>B$THENL$=S$(F):S$(F)=S$(K):S$(K)=L$
 4130 NEXTK,F:GOTO200
 
       Comando CREATE
 4200 IFLEN(P$(2))<1ORLEN(P$(2))>8THEN1200
 4210 IFD$<>""THENGOSUB5100ELSED$=P$(2)
 4220 PRINT"Enter record structure as follows:"
 4230 PRINT"Field   Name, Type, Width, Decimals"
 4240 PRINT" ";:J=3:N=T+1:GOSUB1100:PRINTTAB(11);:GOSUB1500
 4260 IFL$=""THEN200
 4270 B$=",":N=4:GOSUB1000:N=VAL(P$(3)):F=VAL(P$(4))
 4290 IFLEN(P$(1))>10THEN4360
 4300 IFP$(2)<>"C"ANDP$(2)<>"N"THEN4360
 4310 IFP$(2)="C"AND(N<1ORN>25)OR(P$(2)="N"AND(N<1ORN>10))THEN4360
 4320 IFP$(2)="N"ANDF>N-2ANDF<>0THEN4360
 4330 T=T+1:E1$(T)=P$(1):E2$(T)=P$(2):E3$(T)=P$(3)
 4340 IFP$(2)="C"THENE4$(T)="0"ELSEE4$(T)=P$(4)
 4350 IFT=20THEN200ELSE4240
 4360 PRINT"Bad type field":GOTO4240
 
       Comando USE
 4600 IFD$<>""THENGOSUB5100
 4605 D$=P$(2):CLOAD D$+".SYS":CLOAD D$+".DAT":GOTO200
 
       Comando QUIT (Grabar la base de datos)
 5000 IFD$<>""THENGOSUB5100
 5010 PRINT"*** End run   dBASE II   ***":PRINT:PRINT
 5020 PRINT"Remember to back-up your data.":PRINT:END
 5100 IFD$=""THENRETURN
 5105 PRINT"Save data to tape? ";:GETA$:PRINTA$:IFA$="N"ORA$="n"THEN5115
 5110 CSAVE D$+".SYS",A#9C,E#A3:CSAVE D$+".DAT",A10000,E46080
 5115 T=0:R=0:V=0:U=1:D$=P$(2):RETURN

       Inicio de la Aplicación
 9000 INK7:PAPER0:CLS:U=1:FORF=1TO16:READC$(F):NEXT:FORF=1TO16:READJ(F):NEXT
 9005 FORF=46840TO46847:POKEF,255:NEXT
 9010 PRINT"Enter todays date or return for none"
 9020 PRINT" (MM/DD/YY) :";:GOSUB1500:Y$=L$:IFLEN(Y$)>8THENY$=LEFT$(Y$,8)
 9030 PRINT:PRINT"*** dBASE II  Ver Lite*  20 April 2015":PRINT
 9040 PRINT"COPYRIGHT (c) SCAINET SOFT 2015"
 9050 PRINT"AS AN UNPUBLISHED LICENSED PROPIETARY."
 9060 PRINT"ALL RIGHTS RESERVED.":PRINT
 9070 PRINT"dBASE II is a registered trademark and"
 9080 PRINT"dBASE and ASHTON-TATE are trademarks":PRINT"of Ashton-Tate.":RETURN


EL PROYECTO
EL CP/M y sus aplicaciones no están disponibles en muchos de los equipos de 8 bits, y queda descartado en equipos que usan cintas de casete o no disponen del modo de 80 columnas o un microprocesador Z80, salvo excepciones o extrañas adaptaciones.

A partir de un hilo aparecido hace tiempo hablando sobre la posibilidad de hacer un CP/M botable de cinta de casete, y otro del Coleco ADAM de ron, me planteé la posibilidad de que si no se podía adaptar el CP/M, como mínimo hacerlo con sus aplicaciones.

Para ello, decidí hacer adaptaciones en Microsoft BASIC puro y duro, teniendo mucho cuidado que el código fuera muy reducido, con un buen rendimiento y sobretodo fácilmente adaptable a cualquier otro sistema.

Así nació el "dBASE II Lite", el primero de una serie de aplicaciones CP/M adaptadas.

Se puede decir que es un "pixel perfect" ya que tanto el aspecto como la funcionalidad disponible es idéntica al original en CP/M, pero se han reducido las funciones y se ha contemplado que tanto la cinta de casete o incluso el disquete pueda ser usado como medio de almacenamiento externo.

La primera versión fue desarrollada para PC y posteriormente se pasó al AMSTRAD CPC 464/464+ con soporte de cinta y modo 80 columnas. Esta tercera versión funciona en modo de 38 columnas y se ha reducido el código fuente a solo 152 líneas.

A partir de aquí, cualquiera lo puedo adaptar fácilmente a un DRAGON 32, SPECTRUM, BBC Micro, ALPHATRONIC o cualquier otro sistema.

Compare.gif


LA VERSIÓN ORIC
La versión ORIC se ha adaptado muy fácilmente a partir del código fuente de la versión de AMSTRAD CPC, con la salvedad de que he tenido que pasarlo de 80 columnas a 38 columnas, ya que el ORIC funciona a 40 columnas pero las 2 de la izquierda son “bastante” especiales, y con un PRINT normal, inaccesibles.

La principal diferencia, que me ha provocado muchos dolores de cabeza, ha sido el tema de la grabación y carga de los datos.

Empieza la pesadilla...
El ORIC-1 no dispone de ninguna instrucción para gestionar la grabación de ficheros secuenciales o el volcado de matrices, y el ORIC ATMOS dispone de los comandos STORE y RECALL que se supone que lo hacen, pero o los emuladores no lo emulan bien o la complejidad del programa hace que no funcione bien. No lo he probado en un equipo original.

Usar STORE y RECALL habría excluido a los ORIC-1, cosa que no me gustaba, pero me habría facilitado mucho las cosas.

... pero investigando un poquito ...
Analizando las variables del sistema he podido descubrir unas cuantas direcciones interesantes, usadas por el sistema como punteros a direcciones de memoria:

#9C - #9D : Puntero al inicio de la zona de variables.
#9E - #9F : Puntero al inicio de la zona de matrices tipo “string”.
#A0 - #A1 : Puntero al final de la zona de matrices tipo “string”.
#A2 - #A3 : Puntero al siguiente espacio libre para variables tipo “strings”.

Examinando estas zonas de memoria he podido comprobar ciertas cosas:
- Las variables numéricas se guardan en la memoria entre las direcciones indicadas por #9C-#9D y #9E-#9F.
- Cada variable numérica ocupa 6 bytes, más un carácter por cada letra del nombre.
- Las matrices tipo “string” se guardan en la memoria entre las direcciones indicadas por #9E-#9F y #A0-#A1.
- En esta zona se guardan punteros de 2 bytes que apuntan a una zona comprendida entre las direcciones indicadas por #A2-#A3 y el RAMTOP, dirección máxima que puede alcanzar un programa en BASIC y sus variables.
- El valor de estos punteros puede ser alterado, pero deben tener un valor igual o superior al puntero anterior.

Imagen

Como digo, el contenido de las variables tipo “string” se guardan en una posición de memoria entre #A2-#A3 y el RAMTOP, y la zona de la tabla de variables solo contiene los punteros a estas direcciones. Cada vez que una de estas variables cambia de contenido se copia entera en una nueva dirección a partir de la dirección indicada en #A2-#A3 y se decrementa el valor de este puntero en función de la longitud del string. Cuando este puntero apunta a una zona de memoria por debajo de la indicada por #A0-#A1, el sistema ejecuta una rutina que hace una especie de defragmentación de la zona de memoria donde se guarda el contenido de los strings. Esto hace que durante unos segundos el sistema se quede “parado”, y al terminar ajusta el contenido del puntero #A2-#A3.

Supongo que la zona donde se guarda el valor de los string se va decrementando porque si durante la ejecución del programa se van creando nuevas variables numéricas, se deberían ajustar todos los punteros y se podría sobrescribir información. De esta forma es más eficiente ya que solo debe desplazar hacia arriba la zona de los punteros, a la que no le afecta el cambio de situación en la memoria porque las direcciones de los contenidos no han cambiado.

... aparecen las posibles soluciones
Lo primero que hago es modificar los valores de los punteros, en la línea 1 del programa, para que exista una separación de unos 2 KB entre el final del programa en BASIC y la zona donde se guardan las variables. Las he puesto a partir de la dirección 10000, pero podría ser modificado. Con el GRAB de la línea 1, reduzco el espacio asignado a la memoria de vídeo, y esto nos deja unos 36 KB, que descontados la zona de punteros y demás, nos deja unos 32 KB para guardar la información de las bases de datos.

A continuación he definido las líneas DATA porque he visto que cuando haces una asignación de un string de un DATA a una variable, el puntero del string apunta al propio código BASIC y no a una zona de memoria entre #A2-#A3 y el RAMTOP. Más adelante explicaré que no hacerlo así daría problemas en el supuesto de realizar modificaciones en el programa BASIC.

Después de experimentar un buen rato encuentro varias posibles soluciones con un tema en común: se debe realizar un volcado de memoria en cinta.

He probado 3 métodos distintos y me he decidido por el que me ha funcionado mejor y me ha ofrecido más seguridad de que posteriormente se podrán recuperar los datos sin problemas. La diferencia es que en función del método, se graban más o menos bloques de distintos tamaños, que en el supuesto de usar un equipo real con cintas de casete tardará lo suyo…


1) Volcado simple
En el supuesto de que en el programa en BASIC no se realice ninguna modificación, se podría hacer un volcado mediante un CSAVE desde la dirección 10000 hasta la 46080, que es donde deja el RAMTOP el comando GRAB de la línea 1. Si las variables se definen antes y se guardan los valores de los punteros en las variables de sistema antes indicadas, al realizar un CLOAD del bloque de bytes guardado, el sistema quedará como estaba y el programa funcionará bien.

Metodo-1.gif
Metodo-1.gif (38.44 KiB) Visto 1604 veces


Este método graba un bloque de 36KB, y cualquier mínimo cambio en el programa BASIC provocará un cambio en los valores de los punteros del sistema, y al recuperar el bloque puede pasar que se sobrescriba el programa en BASIC, se pierda el valor de algunas variables, etc.

Visto esto, decidí descartarlo pero podría ser útil en otros casos.

2) Volcado seguro
Con este método se graban dos bloques de bytes: uno de 8 bytes con extensión “.SYS” que contiene los punteros a las zonas de variables.

A continuación guardo desde la dirección 10000 hasta la 46080 en un bloque con extensión “.DAT”. Decir que las extensiones no tienen ninguna importancia, excepto para diferenciar los ficheros generados.

El hacerlo de esta forma me permite poder realizar modificaciones en el programa BASIC, de forma que el bloque de bytes grabado tenga un buen margen de seguridad para poder seguir siendo cargado correctamente. Si las modificaciones son muy grandes y el programa BASIC supera la dirección 10000 puede pasar como con el método anterior.

Metodo-2.gif
Metodo-2.gif (38.24 KiB) Visto 1604 veces


Inicialmente las líneas con los DATA estaban al final del programa, como me gusta hacer siempre, pero me encontraba que al realizar cambios en el programa BASIC y cargar un bloque de bytes grabado previamente, los punteros apuntaban a posiciones incorrectas porque las direcciones de los textos del DATA habían cambiado. Al ponerlo al principio del programa he evitado este problema, pero si se modifica el contenido de las primeras líneas volvería a fallar al cargar un bloque grabado anteriormente, pero no uno grabado con la nueva versión del BASIC.

El problema de este método es que graba un pequeño bloque de 8 bytes, pero a continuación graba otro gran bloque de 36 KB, que en el emulador no se nota pero que en un equipo real nos llevará su tiempo.

Podemos reducir el tamaño de este bloque modificando el valor de los DOKE de la línea 1, ya que cuanto más grande, menos espacio para datos y menos tamaño del bloque a grabar. Para gustos...

Este es el método que he seleccionado porque me ha funcionado sin ningún problema.

3) Volcado óptimo
Este volcado es el mejor ya que el bloque de datos se reduce a la cantidad de datos reales a grabar. Pero por desgracia, a veces se pierde algún valor. Ignoro el motivo, pero seguro que no he tenido en cuenta algo...

Su funcionamiento consiste en forzar una compactación de la zona del contenido de las variables string, reduciendo el valor del puntero #A2-#A3 por debajo del contenido del puntero #A0-#1, y realizando un cambio en una variable tipo string. Después de la compactación, el puntero #A2-#A3 apunta a una zona libre más cercana a RAMTOP, y grabando el contenido desde ésta posición hasta la RAMTOP tenemos los datos guardados en un bloque de bytes con un tamaño más reducido.

A continuación se guarda otro bloque de unos 3 KB que contiene el bloque comprendido entre los punteros #9C-#9D y #A0-#A1, para poder posteriormente recuperar los punteros a la zona de strings.

Y para terminar se guarda un pequeño bloque de 8 bytes con la zona de las variables de sistemas, como en el caso anterior.

Metodo-3.gif
Metodo-3.gif (36.12 KiB) Visto 1604 veces


Es el tema más eficiente ya que el tamaño de los datos a grabar se reduce significativamente, pero como digo, “algo” no acaba de funcionar bien y lo descarté por inseguro hasta que encuentre el fallo.

Apuntes finales
He utilizado el método 2 porque funciona correctamente, pero hay un “pequeño” problema: restaurar la zona de variables completa y “a saco” provoca que perdamos el contenido de variables definidas antes de cargar el bloque con CLOAD. Por eso, y como podréis comprobar, en esta versión el tema de la fecha no funciona al cargar un fichero grabado previamente, porque se destruye su contenido y recupera el que tenía al realizarse la grabación. Con todo, lo he dejado porque respeta el original.

El tamaño de los bloques que comento es en función de esta aplicación, pero aplicado en otros programas variará en función de la cantidad de variables usadas y sus tamaños.

Y seguro que hay mejores soluciones, pero esta es la que he encontrado y excepto por el tema de la fecha, esta versión de dBASE II funciona perfectamente. Y con el emulador cargar y grabar datos es muy rápido !!!


PARA TERMINAR
Este programa ha sido un ejercicio estupendo para aprender un poco sobre como el sistema gestiona todo el tema de las variables. El tema es muy amplio y da para mucho más. Pero lo dejo para otra ocasión.

Si lo queréis usar:
1) Cargar el programa y haz RUN.
2) Puedes poner la fecha de entrada, si quieres.
3) Escribe: USE COMPUTER
4) Carga la base de datos “COMPUTER”, de ejemplo, que viene junto al programa.
5) Escribe: LIST para ver los registros.
6) Escribe: LIST STRUCT para ver la estructura de la base de datos.
7) Escribe: EDIT 5 para editar el registro número 5.
8) Escribe QUIT para terminar.
9) Da la opción de grabar los datos en cinta de casete. Pulsa “N” o “n” para no hacerlo.


Espero que os guste

dBaseII-2.gif
dBaseII-2.gif (33.91 KiB) Visto 1604 veces

dBaseII-3.gif
dBaseII-3.gif (13.42 KiB) Visto 1604 veces

dBaseII-4.gif
dBaseII-4.gif (30.03 KiB) Visto 1604 veces

dBaseII-5.gif
dBaseII-5.gif (35.3 KiB) Visto 1604 veces
Adjuntos
dBaseII-Double.gif
dBaseII-Double.gif (26.46 KiB) Visto 139 veces
Memoria-ORIC.gif
Memoria-ORIC.gif (43.88 KiB) Visto 139 veces

FloppySoftware

Re: dBASE-II para ORIC

Mensajepor FloppySoftware » 29 Abr 2015 09:38

Hola Dancresp.

Tengo 2 comentarios buenos y otro malo:

1º. Me quito el sombrero ante ud. -thumbup Siempre he tenido gran interés por las bases de datos, y lo que has hecho, con tan poco código, es espectacular. -drinks

2º. Creo que no tendrías que darle el mismo nombre que el producto original, al programa. Puede causar confusión, aun cuando en el post lo aclaras. Espero que no te molestes, pero, entiéndeme, creo que sería mejor.

dancresp
Mensajes: 5336
Registrado: 13 Nov 2010 02:08
Agradecido : 150 veces
Agradecimiento recibido: 287 veces

Re: dBASE-II para ORIC

Mensajepor dancresp » 29 Abr 2015 09:48

FloppySoftware escribió:Creo que no tendrías que darle el mismo nombre que el producto original, al programa. Puede causar confusión, aun cuando en el post lo aclaras. Espero que no te molestes, pero, entiéndeme, creo que sería mejor.

Pues la verdad es que me he olvidado porque en el Word donde lo he redactado lleva el "Lite".

Así que no solo no me molesto, sino que te agradezco me hayas avisado.

Y de paso me libro de una demanda de los de Asthon-Tate... -rofl

FloppySoftware

Re: dBASE-II para ORIC

Mensajepor FloppySoftware » 29 Abr 2015 10:30

dancresp escribió:Y de paso me libro de una demanda de los de Asthon-Tate... -rofl


Tienen buenos abogados, y dBase sigue en la cresta de la ola: http://www.dbase.com/ -rofl -rofl -rofl -rofl

Avatar de Usuario
Chema
Mensajes: 2214
Registrado: 21 Jun 2012 20:13
Ubicación: Gijón
Agradecido : 1748 veces
Agradecimiento recibido: 573 veces
Contactar:

Re: dBASE-II Lite para ORIC

Mensajepor Chema » 29 Abr 2015 11:35

Uau! Qué pasada dancresp. Te has peleado con el tema de las matrices a base de bien, por lo que veo, ¿eh?. No miré más por qué no te funcionaba el STORE y el RECALL y en mi pequeño ejemplo sí. Me gustaría profundizar más y ver si es un problema del emulador, para avisar al autor a ver si saca un parche.

Si me pudieses mandar un ejemplo que NO funcione para probar (lo más simple posible) sería genial.

Enhorabuena otra vez por tu trabajo. La verdad es que no dejas de sorprendernos con las cosas que haces con el BASIC...

Avatar de Usuario
ron
Mensajes: 18396
Registrado: 28 Oct 2010 14:20
Ubicación: retrocrypta
Agradecido : 1569 veces
Agradecimiento recibido: 1315 veces

Re: dBASE-II Lite para ORIC

Mensajepor ron » 29 Abr 2015 12:49

naaa, lo dejan solo y mirad lo que hace, LO HA VUELTO A HACER, no tiene remedio.

Tiene que ser muy interesante pero para que funcione con disco. Que seguramente y con muy pocos cambios sea factible del todo.

dancresp
Mensajes: 5336
Registrado: 13 Nov 2010 02:08
Agradecido : 150 veces
Agradecimiento recibido: 287 veces

Re: dBASE-II Lite para ORIC

Mensajepor dancresp » 29 Abr 2015 13:10

Chema escribió:Si me pudieses mandar un ejemplo que NO funcione para probar (lo más simple posible) sería genial.

Las versiones previas las he borrado, pero es tan simple como intentar grabar la matriz S$ en la línea 5510, quitando los CSAVE que hay, y después tratar de recuperarlo desde la línea 4605 en lugar del CLOAD.

Con esto la recuperación no sería funcional porque hay que meter la definición en una parte de S$, pero para comprobar si el STORE y RECALL funcionan sería suficiente, haciendo un PRINT S$(1) (por ejemplo) después del RECALL. A mi me salía basura en el contenido de la matriz.

Chema escribió:Enhorabuena otra vez por tu trabajo. La verdad es que no dejas de sorprendernos con las cosas que haces con el BASIC...

Bueno, viniendo de alguien que ha dejado escrito: -shock

chema dixit:
... me propuse aprender a programar en el ensamblador de 6502 y, de paso, aprender cómo se hacían las maravillas que veíamos en los 80 correr en esas pequeñas máquinas. Y comencé con algo de lo más duro: los juegos en perspectiva isométrica. Y así nació el juego Space:1999, una aventura basada en la popular serie de TV.

Imagen

... hace que me intente superar y aprender, porque de mayor me gustaría hacer programas como los que haces tú... -grin

ron escribió:Tiene que ser muy interesante pero para que funcione con disco. Que seguramente y con muy pocos cambios sea factible del todo.

Por descontado que cuando tenga la controladora, y si hay alguna extensión en el BASIC que lo permita, mi intención sería hacer una versión que permita elegir el soporte de almacenamiento.

Y como le he dicho a chema, los cambios serían mínimos.

Avatar de Usuario
Chema
Mensajes: 2214
Registrado: 21 Jun 2012 20:13
Ubicación: Gijón
Agradecido : 1748 veces
Agradecimiento recibido: 573 veces
Contactar:

Re: dBASE-II Lite para ORIC

Mensajepor Chema » 29 Abr 2015 13:42

LOL En realidad no me parece más complicado que las cosas que tú haces (encima en diferentes cacharros y sin tools sobre PC!). Eso sí, hay que tirar de ensamblador, paciencia y tesón. Vamos, estar un poco loco para dedicar un añito o así a un proyecto de este tipo.

Otra cosa distinta es lo que hace la peña en las demos o con los gráficos o el sonido... Eso ya es creatividad a tope, y ahí patino. Los gráficos y el sonido de ese juego son casi todos hechos por Twilighte, por ejemplo.

Pero volviendo al tema. Creo recordar que SEDORIC tiene extensiones para grabar matrices en ficheros de disco desde BASIC. Me parece que redefine STORE/RECALL para ello, así que la conversión debería ser casi inmediata. No tengo aquí el manual para mirar, pero deberías encontrar la info por la red fácilmente y puedes probar desde un emulador. Eso sí, se beneficiaría un montón de las rutinas de BASIC para leer/escribir archivos (que no he probado ni usado nunca, por cierto).

Usa tap2dsk para meter tu programa en un archivo dsk con sedoric y arrancable y puedes probar ya mismo.

Este programa merece chutar en disco y, quizás, unos toques de color para diferenciar comandos y respuestas, un menú... porque tiene una pinta estupenda!

Si me hago un hueco pruebo lo que dices. De todas formas ya he posteado en Defence-Force sobre el bug que te comenté del archivo que se genera con STORE. A ver si encuentran algo...


Volver a “Lenguajes de Programación y herramientas Dev”

¿Quién está conectado?

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