!0.......^.........^.........^.. !B \H11\H07\H10\H00 SCREEN SCRUNGER !2.......^.........^.........^.........^.........^.........^.... Calling all those of you who are contemplating adding graphics to your adventure programs. Chris Wood has devised a couple of screen compressor programs that'll "scrunge" those screens and save those precious bytes. !1.......^.........^.........^.........^........ What we're talking about here is a two-in-one "screen scrunger" - or screen compressor, if you prefer - that's fast, relocatable and short (less than 50 bytes each!). Using either of these routines, or a combination of both, you can "scrunge" most screens down to at least half their original size and, with a built-in relo- catable screen scrunger saved as a standard with each picture, you can have between 10 and 15 screens stored in memory at any one time! Adventure writers only require the top third or so of each screen saved, which is why the program included does this ... and even lets you move bits of the screen around. The only restriction on saving parts of the screen is that attributes have to be compressed separ- ately; this is because the program can only handle continuous chunks of memory. !0.......^.........^.........^.. !B ON-SCREEN STORAGE !1.......^.........^.........^.........^........ At this stage, there's no need to go into too much detail about how the Spectrum's screen is laid out - but if you've got a couple of days spare sometime ... Suffice to say that what you see on-screen is no more than an area of memory that we can see and, as far as the Spectrum's concerned, it's nothing but a jumble of binary figures. In the meantime, here's some information on how the scrunger routines work ... and why you need two of them! Take a look at a few SCREEN$ pictures and you'll see there are quite a few large areas of the same colour - from which you'd surmise that the same value is popping up in memory quite often. You'd be right! Thus, our first routine dives through the screen memory counting the number of times a particular value pops up until a different value is found. Once another value has been found, the Spectrum resets its internal counter, stores the data !0.......^.........^.........^.. !B 10 POKE 23658,8 !2.......^.........^.........^.........^.........^.........^.... Line 10 Turns the Caps Lock feature on !0.......^.........^.........^.. 20 PAPER 7: INK 0: CLS 30 PRINT " HOW MUCH DO YOU WA NT SAVED?" 40 PRINT ''" 1. PART OF SCREEN $ "''" 2. ALL OF SCREEN$ " 50 IF INKEY$="2" THEN POKE 30 009,64: POKE 30048,91: POKE 3005 6,64: POKE 30065,91: POKE 40010, 64: POKE 40046,91: POKE 40054,64 : POKE 40063,91: GO TO 500 60 IF INKEY$<>"1" THEN GO TO 50 70 CLS : PRINT ''" INPUT LIMI TS" 80 PRINT ''"64.TOP OF INK"''"7 2.MIDDLE OF INK"''"80.BOTTOM OF INK"''"88.TOP OF ATTRIBUTES"''"8 9.MIDDLE OF ATTRIBUTES"''"90.BOT TOM OF ATTRIBUTES"''"91.END OF S CREEN" 90 INPUT "FROM? ";start: INPUT "END? ";end 95 POKE 30009,start: POKE 4001 0,start: POKE 30048,end: POKE 40 046,end 100 INPUT "PARTS TO GO TO SAME PLACE?";a$: IF CODE a$=CODE "Y" THEN GO TO 110 105 INPUT "TO GO TO? ";dest 106 LET diff=dest-start: LET en d=end+diff: LET start=start+diff 110 POKE 30056,start: POKE 4005 4,start: POKE 30065,end: POKE 40 063,end !2.......^.........^.........^.........^.........^.........^.... Lines 20-110 Provide menu options for the screen scrunger !0.......^.........^.........^.. 500 GO SUB 990: LET l=USR 30000 : LET m=USR 40000: LET l=l-30054 : LET m=m-40052 510 CLS : PRINT "EXTRACTING 0 A ND 255 TAKES "; PAPER 6;l''; PAP ER 7;"SQUASHING ALL DATA TAKES " ; PAPER 6;m !2.......^.........^.........^.........^.........^.........^.... Lines 500-510 Find out how much space is saved by each routine, and then print up each option. !0.......^.........^.........^.. 520 PRINT ''"SAVE FIRST OR SECO ND?" 530 INPUT "SAVE? (1 OR 2)?";a 540 IF a=1 THEN CLS : RANDOMIZ E USR 30054: SAVE "SQUASHED SCRE EN$ "CODE 30054,l: RUN 550 IF a=2 THEN CLS : RANDOMIZ E USR 40052: SAVE "SQUASHED SCRE EN$ "CODE 40052,m: RUN 560 GO TO 530 !2.......^.........^.........^.........^.........^.........^.... Lines 520-560 Save the "scrunged" screen !0.......^.........^.........^.. 990 POKE 65370,64: POKE 65373,1 96: RANDOMIZE USR 65368: RETURN 995 POKE 65370,196: POKE 65373, 64: RANDOMIZE USR 65368: RETURN 999 STOP !2.......^.........^.........^.........^.........^.........^.... Lines 990-999 Contain the screen handling subroutines !0.......^.........^.........^.. 1000 RESTORE 1010: LET ch=0: FOR n=0 TO 81: READ a: LET ch=ch+a: POKE 40000+n,a: POKE 49000+n,a: NEXT n 1001 IF ch<>8217 THEN PRINT "ER ROR IN DATA IN LINE 1010": STOP 1005 LET ch=0: FOR n=0 TO 97: RE AD a: LET ch=ch+a: POKE 30000+n, a: POKE 39000+n,a: NEXT n 1006 IF ch<>9171 THEN PRINT "ER ROR IN DATA IN LINE 1020": STOP 1008 FOR n=65368 TO 65379: READ a: POKE n,a: NEXT n: CLEAR 29999 : PRINT "LOADING": LOAD ""SCREEN $ : GO SUB 995: GO TO 1 !2.......^.........^.........^.........^.........^.........^.... Lines 1000-1008 Provide the initialisation routines !0.......^.........^.........^.. 1009 REM SQUASH ALL CODE 1010 DATA 197,209,33,85,0,25,235 ,221,33,0,64,14,1,221,126,0,221, 190,1,32,8,121,60,167,40,3,79,24 ,10,221,126,0,18,19,121,18,19,14 ,1,221,35,221,229,225,124,254,91 ,32,220,213,193,201,17,0,64,221, 33,33,0,221,9,122,254,91,200,221 ,70,1,221,126,0,18,19,16,252,221 ,35,221,35,24,236,0 !2.......^.........^.........^.........^.........^.........^.... Lines 1009-1010 Contain the data for the first screen scrunger routine !0.......^.........^.........^.. 1019 REM EXTRACT 0 AND 255 CODE 1020 DATA 197,209,33,100,0,25,23 5,33,0,64,14,1,126,167,40,9,254, 255,40,5,237,160,3,24,21,71,121, 60,35,40,7,126,184,32,3,12,24,24 3,120,18,19,121,18,19,14,1,124,2 54,91,32,217,213,193,201,17,0,64 ,221,33,46,0,221,9,122,254,91,20 0,221,126,0,167,40,10,254,255,40 ,6,18,19,221,35,24,236,221,70,1, 18,19,16,252,221,35,221,35,24,22 3,0,0 !2.......^.........^.........^.........^.........^.........^.... Lines 1019-1020 Contain the data for the second screen scrunger routine !0.......^.........^.........^.. 1030 DATA 17,0,176,33,0,64,1,0,2 7,237,176,201 !2.......^.........^.........^.........^.........^.........^.... Line 1030 Provides the save routine for the SCREEN$ The "screen scrunger" program should be initialised with "RUN 1000" to set up the data lines 1009-1030. Once the data has been initialised, the program flow is directed to the menu of options offered by the scrunger. !1.......^.........^.........^.........^........ !B and carries on looking through the rest of the screen memory. For example, the following data "1,1,1,1,1,1,2,2,2,2,3,3,3,3" in screen memory would be scrunged and stored as "1*6,2*4,3*4". As the routine allocates a single byte to store the internal counter, if there's more than 256 occurrences of the same value the counter resets itself and the next value is treated anew. For example, a row of 400 twos becomes "2*0,2*144" (where a zero value denotes '256'). !0.......^.........^.........^.. FOR MY NEXT TRICK ... !1.......^.........^.........^.........^........ The first routine will suit most screen- scrunging requirements, but very complex screens with a few repeated values can trip up the routine. For example, a block of memory that originally looks like "1,2,3,4" becomes "1*1,2*1,3*1,4*1", and four bytes is transformed into eight - not a good method if complex illus- trations, such as the start-up screen in Lunar Jetman, can grow to around 7.5K instead of the usual 6.5K! And this is where the second routine comes in. Complex visual screens, such as Ultimate's, require a routine that just takes all the free bytes (that is, all the zeros in the background) and just squashes up all the rest of the data. Using this method, you can't help but make a saving. However, to make the second routine even more clever, it's also programmed to take out 255s that occur in solidly-filled blocks of the screen. You'll be glad to know that the Lunar Jetman screen mentioned earlier is scrunged happily down to around 4.5K! But don't start worrying which routines you're going to have to use with each screen, as the Basic program (the two routines are provided in the data statements) tells you which "scrunger" is the most efficient for each case. To make use of the "scrunged" screens saved by the program, call the machine code from the same address at which you load the code; each picture saved is accompanied by a screen decompressor routine at its start. For example, if you want to put your "scrunged" screen at address 40000, you'd get it back on-screen by executing "RANDOMIZE USR 40000". Happy scrunging, my dearios! !0.......^.........^.........^.. !B \H11\H07\H10\H00SQUEEZE ME! !2.......^.........^.........^.........^.........^.........^.... First of all, load up the "Screen Scrunger" and type RUN 1000. Now, load the SCREEN$ - in this case, a view from Quicksilva's Zombie Zombie - and it'll be stored in a high location in memory. The program will then move on to the options screen ... !Szombi1 !2.......^.........^.........^.........^.........^.........^.... The options screen allows you to choose whether you want to scrunge the whole SCREEN$ or just a portion of it. In this case, the middle section was scrunged - by typing in '72' and '80' as the parameters for the compression. !Szombi2 !2.......^.........^.........^.........^.........^.........^.... The program offers you the option of saving the compressed SCREEN$ code - displaying the relevant section on-screen whilst saving takes place. The "Screen Scrunger" itself will advise you as to which routine is the most efficient for the SCREEN$ you're scrunging. !Szombi3 !0.......^.........^.........^.. CARTOON !Scartoon !1.......^.........^.........^.........^........ !B -- from Your Spectrum #13 (Apr.1985) -- !$