!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)
--
!$
