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