Area: Quik_Bas Msg: #285 Date: 01-10-93 21:14 (Public) From: Matt Hart To: Keith Watkins Subject: GSAVE.BAS
KW> I like the idea of saving 64k of BSAVE to 8k and really need to be able
GSAVES.BAS is the wrong program. It saves multiple screens
to a single file, but doesn't compress them - and it has a
bug too. I'm going to work on it and add RLL compression
to it. For now, though, here's BSAVECP.BAS - the
saver/restorer with compression.
' BSAVECP.BAS by Matt Hart
' Compress a BSAVE/BLOAD file. Requires enough far memory
' to temporarily store the compressed file.
'
' The example draws a picture in CGA, saves it, then restores it.
' With this example, the CGA screen saved very quickly AND only
' took 1700 bytes of disk space. This was a much better result
' than I expected! At 7.9 times the processor speed of an XT and
' 1.8 times the speed of an AT, the FindKey PLUS BSave took 1.2
' seconds. At 35.2 times an XT, it took .55 seconds.
' The AsciiKey finder is included so you can use the best key - but
' it slows down the save routine some.
'
' Make sure NumBytes& is an even number. Some modifications would
' be necessary for NumBytes& > 32K. If one of the PEEK address'
' is > 32K, then add 2K to the segment and subtract 32K from the
' address. Alternately add 1 to the segment and subtract 16 from the
' address after every 16 increments in the address.
'
DEFINT A-Z
SCREEN 1 : CLS
LINE (0,0)-(319,199),1,B
LINE (1,1)-(318,198),1,B
CIRCLE (160,100),50,3
PAINT (160,100),2,3
BEEP : WHILE INKEY$="" : WEND ' Ready to Save
File$="EXAMPLE.BNC"
StartSeg=&HB800 : StartAddr=0
NumBytes&=16384&
'AsciiKey = 1
CALL FindKey(StartSeg,StartAddr,NumBytes&,AsciiKey)
CALL BSaveCompress(File$,StartSeg,StartAddr,NumBytes&,AsciiKey)
CLS
BEEP : WHILE INKEY$="" : WEND ' Saved - Ready to Re-load
CALL BLoadCompress(File$,StartSeg,StartAddr)
BEEP : WHILE INKEY$="" : WEND ' Re-loaded - ready to end
SCREEN 0 : WIDTH 80
END
'
SUB BSaveCompress(File$,StartSeg,StartAddr,NumBytes&,AsciiKey)
DimSize = NumBytes& \ 2
REDIM Temp(1 to DimSize)
ToSeg = VARSEG(Temp(1)) : ToAddr = VARPTR(Temp(1))
CALL MemCopyCP(StartSeg,StartAddr,ToSeg,ToAddr,NumBytes&,_
NewNumBytes&,AsciiKey)
DEF SEG = ToSeg
BSAVE File$,ToAddr,NewNumBytes&
DEF SEG
END SUB
'
SUB BLoadCompress(File$,ToSeg,ToAddr)
F=FreeFile
OPEN "B",1,File$ : NumBytes& = LOF(F)-12
AsciiK$=" " : GET 1,LOF(F),AsciiK$ : AsciiKey=ASC(Asciik$)
CLOSE 1
DimSize = NumBytes& \ 2
REDIM Temp(1 to DimSize)
StartSeg = VARSEG(Temp(1)) : StartAddr = VARPTR(Temp(1))
DEF SEG = StartSeg
BLOAD File$,StartAddr
DEF SEG
CALL MemCopyUNCP(StartSeg,StartAddr,ToSeg,ToAddr,_
NumBytes&,AsciiKey)
END SUB
'
SUB MemCopyCP(FromSeg,FromAddr,ToSeg,ToAddr,NumBytes&,_
NewNumBytes&,AsciiKey)
FS=FromSeg : TS=ToSeg
FA&=FromAddr : TA&=ToAddr : CB&=1 : N=0
DEF SEG = FS ' Get rid of an IF/THEN/ELSE and make it
Y=PEEK(FA&) ' faster - get's rid of the "First=-1" flag
DEF SEG
NewNumBytes&=0
DO
DEF SEG = FS ' Read the byte from memory
Z=PEEK(FA&)
FA&=FA&+1 ' If the From Address is over
IF FA&>32767& THEN ' 32K, then increase the segment
FS=FS+2048 ' by 32K ( increase is actually
FA&=FA&-32768& ' 32K \ 16).
ENDIF '
DEF SEG
IF Z <> Y THEN ' A sequence of characters has ended
DO UNTIL N < 256 ' Put in multiple codes for greater than
DEF SEG = TS ' 255 sequential bytes
POKE TA&,AsciiKey : TA&=TA&+1
POKE TA&,255 : TA&=TA&+1
POKE TA&,Y : TA&=TA&+1
IF TA&>30719& THEN
TS=TS+1920
TA&=TA&-30720&
ENDIF
DEF SEG
N=N-255
LOOP
IF N > 4 OR Y = AsciiKey THEN ' so Put the Code
DEF SEG = TS
POKE TA&,AsciiKey : TA&=TA&+1
POKE TA&,N : TA&=TA&+1
POKE TA&,Y : TA&=TA&+1
DEF SEG
NewNumBytes&=NewNumBytes&+4
ELSE
FOR i=1 TO N ' Otherwise, put the characters
DEF SEG = TS
POKE TA&,Y : TA&=TA&+1
DEF SEG
NewNumBytes&=NewNumBytes&+1
NEXT i
ENDIF
IF TA&>30719& THEN ' Increment the ToAddress
TS=TS+1920 ' and check it's size.
TA&=TA&-30720&
ENDIF
N=0 ' Reset number of sequential
ENDIF ' characters to zero
Y=Z ' Current character
N=N+1 ' Current count
CB&=CB&+1 ' Counting the number of
LOOP UNTIL CB&>NumBytes& ' bytes read so far
IF N > 4 OR Y = AsciiKey THEN ' Catch the last character or
DEF SEG = TS ' character sequence
POKE TA&,AsciiKey : TA&=TA&+1
POKE TA&,N : TA&=TA&+1
POKE TA&,Y : TA&=TA&+1
DEF SEG
NewNumBytes&=NewNumBytes&+4
ELSE
FOR i=1 TO N
DEF SEG = TS
POKE TA&,Y : TA&=TA&+1
DEF SEG
NewNumBytes&=NewNumBytes&+1
NEXT i
ENDIF
DEF SEG = TS ' Here, the ASCIIKEY is
POKE TA&,AsciiKey : TA&=TA&+1 ' stored at the end of
DEF SEG ' the file
NewNumBytes& = NewNumBytes& + NewNumBytes& MOD 2
NewNumBytes& = NewNumBytes& + 1 ' This is done so that
END SUB ' NewNumBytes& will make an
' ' even DimSize in UNCP
'
'
SUB MemCopyUNCP(FromSeg,FromAddr,ToSeg,ToAddr,NumBytes&,_
AsciiKey)
FA=FromAddr : TA=ToAddr : CB=0
DO
DEF SEG = FromSeg
Z=PEEK(FA)
FA=FA+1
DEF SEG
IF Z=AsciiKey THEN
DEF SEG = FromSeg
N=PEEK(FA)
FA=FA+1
DEF SEG
DEF SEG = FromSeg
Y=PEEK(FA)
FA=FA+1
DEF SEG
FOR I=1 to N
DEF SEG = ToSeg
POKE TA,Y
TA=TA+1
DEF SEG
NEXT I
ELSE
DEF SEG = ToSeg
POKE TA,Z
TA=TA+1
DEF SEG
ENDIF
CB=CB+1
LOOP UNTIL CB>NumBytes&
END SUB
'
SUB FindKey(FromSeg,FromAddr,NumBytes&,AsciiKey)
DIM Temp(0 to 255)
FA=FromAddr
FOR i&=1 TO NumBytes&
DEF SEG = FromSeg
Z = PEEK(FA) : FA=FA+1
DEF SEG
Temp(Z) = Temp(Z) + 1
NEXT i&
AsciiKey=256
FOR i=0 to 255
IF Temp(i)<AsciiKey THEN AsciiKey=Temp(i)
NEXT i
END SUB
-end-

Books at Amazon:
Back to BASIC: The History, Corruption, and Future of the Language
Hackers: Heroes of the Computer Revolution (including Tiny BASIC)
Go to: The Story of the Math Majors, Bridge Players, Engineers, Chess Wizards, Scientists and Iconoclasts who were the Hero Programmers of the Software Revolution
The Advent of the Algorithm: The Idea that Rules the World
Moths in the Machine: The Power and Perils of Programming
Mastering Visual Basic .NET