Classic Computer Magazine Archive A.N.A.L.O.G. ISSUE 72 / MAY 1989 / PAGE 48

THE
ULTIMATE
GRAPHICS
FILE
CONVERTER

by Lee S. Brilliant, M.D.


    It seems to me that there are two types of computer enthusiasts in this world: programmers and users; and each group has its own philosophy and language. You can usually tell the difference by the way they act: programmers program and users use.
    I guess I fall in the former category. I can tell because of what happened to me when Newsroom was released. Of course I bought the whole set of five disks and decided to learn how to use it and in the process make a family newsletter. I started out making the banner at the top of the page and immediately ran into trouble. You see, I wanted to use my family symbol on the header, and in spite of the 2,000+ graphics in the Newsroom set, none of them is a compass star. In fact, there are no stars at all. So I figured I could use the one from my Print Shop disk, but Newsroom does not have a routine to incorporate outside graphics or to save graphics you create onto a Newsroom format disk. (You can save them on DOS disks as photos or banners but not as Newsroom clip art disks).
    The only recourse I had was to use the built-in graphics editor which is both clumsy and slow. Too bad I couldn't use MicroPainter and transfer my creation over. Immediately wheels started turning, and before I ever got started on the newsletter, I was pounding the keyboard. That's how I know I am a programmer, not a user! Here is what I humbly call the Ultimate Graphics File Convertor (UGFC)!

Typing It In
    To create your copy of UGFC, first type in Listing 1 (checking your work with BASIC Editor II, found elsewhere in this issue) and save it to disk. Then type in Listing 2, save it and run it. A file named TEMRLST will be written to your disk. Now load the program you typed from Listing 1 into your computer's memory and type ENTER "D:TEMP.LST" to merge the lines created by Listing 2 with the main program. Finally, save the completed program to disk.

For Users
    With UGFC you have four formats to work from: Graphics 8, MicroPainter, Print Shop and Newsroom. Operation is quite simple. First you will select a Load Format then a Save Format (not the same type). After inserting the proper type of disk, the menu for that disk will appear. You then select the file you want and the desired picture will load. Next a set of four lines will appear which you move around the screen to define the area you wish to save. Print Shop saves are a fixed size while the others can be any size.
    Finally, you give the Save filename and your screen is saved. The disk you save to must be an unneeded disk, because it will be formatted and dedicated to the single file. From this disk, you can save Graphics 8 and MicroPainter files to any DOS disk, while Print Shop saves can be loaded into the Print Shop editor then re-saved to your Print Shop file disk. Newsroom clip art files cannot easily be added to another disk, but you can convert then to a photo or banner and save them to a DOS disk.

Tutorial
    Newsroom and Print Shop both display their graphics as monochrome, high resolution (i.e. Graphics 8) pictures. These can readily be converted to standard 62-sector DOS files, as well as the other way around, within size constraints. The problem arises when you try to convert between Graphics 8 screens and MicroPainter's Graphics 15 (or 7½ or "E"). While both types occupy 7,680 bytes, the graphics mode 15 has only one half the horizontal resolution of Graphics 8. By assigning two bits to each pixel, you lose resolution but gain four colors.
    You can load a Graphics 15 picture into a Graphics 8 screen, but you will still have only 160 columns of resolution, and you will lose your color information (although there is artifacted color which can look quite good). Conversely if you load a Graphics 8 picture into a Graphics 15 screen, you can display only 160 pixels per line, but the additional information creates strange color artifacts. (See Figure 1.)

figure 1

    With careful attention paid to selection of color values and fill patterns you can reasonably exchange Graphics 8 and Graphics 15 screens.

Storage Techniques
    Nothing really needs to be said about Graphics 8 storage. Each file is simply a 7,680-byte screen transferred to disk in a block. MicroPainter is the same except that after the screen bytes, the values of the four color registers are added. The real difficult storage forms are Print Shop and Newsroom.
    Print Shop graphics disks (not including the original Print Shop disk) have a directory in Sectors 362 to 393 with each entry occupying 32 bytes instead of 16 like DOS. Sector 361 has the essential disk ID info and a VTOC or sector map. Each entry contains the starting sector of the graphic and an ID byte. Each graphic is 88*52 pixels or 572 bytes long. Each sector contains 126 bytes of data and two bytes containing the number of the next sector much the way DOS does. (See Figure 2.)

      SECTOR 361                         SECTOR 362
--------------------                --------------------

    0 1 2 3 4 5 6 7                     0 1 2 3 4 5 6 7
--------------------               --------------------

0 | P R I N T   S H                 0 | F I L E N A M E
8 | 0 P : C L K ! <--DISK ID BYTE   8 | 1 6 - B Y T E S
16|                   0=PRINT SHOP  16| - - - - ? ? - -
24|      VTOC         2=GRAPHICS    24| \ /    |
32|       |           3=USER MADE   32|  |     |
          |             GRAPHICS         |     |
          |           4=COMPANION     START    TYPE ID
          |                           SECTOR    x=COMPANION
          |                                     X=PRINT SHOP
         \ /
                                 BIT
VTOC BYTE                  7 6 5 4 3 2 1 0
EACH BIT=1 SECTOR           FIRST    LAST
   ie. FF=8 SECTORS -->
       F8=5 SECTORS


FIGURE 2

    Each Newsroom clip art disk is in enhanced density mode and contains around 1,000 sectors. Fortunately, the disk drive and resident disk handler in the OS readily handle such problems. The process of loading a file begins with Sector 1. Here you find an ID header followed by the name of each file stored as ASCII text. Each name is separated by a character 0. The directory space extends to Sector 12 but doesn't seem to be used beyond Sector 4. Beginning at Sector 13 and extending up to about Sector 24 is a table of sector/byte locations for each graphic on the disk. Graphics are segregated into files, each one making up one screen and having one filename. Files are separated by headers consisting of two consecutive character 255s. (See Figure 3.)

                    CLIP ART DISK VOLUME ONE

       SECTOR 1                                  SECTOR 13
-----------------------------          ---------------------------------
    0  1  2  3  4  5  6  7                 0   1   2   3   4   5   6   7
-----------------------------          ---------------------------------
0 | S  S  I     C  L  I  P             0 | 224 3   122 227 3   21  231 3
8 |    N  E  W  S  R  O  O             8 | 61  235 3   72  240 3   78  225
16| M                                  16| 225 202 3   101 210 3   52  214
24| 0  1  1  57 116 3    A             24| 3   96  218 3   15  255 255 181
32| E  R  I  A  L  1     A             32| 3   82  182 3   121 184 3   3
40| E  R  I  A  L  2     A             40|        ETC
48| U  T  O  1     A  U  T
56|
64|      ETC                                    REARRANGED IT LOOKS LIKE:
                                                 224  3  122
                                                 117  3  21
                                                 231  3  61       AERIAL 1
24   1  1  57 ?  ?     A                         235  3  72
     |  |  |                                     240  3  78
     |  |  # OF FILES ON THIS SIDE               255  255
     |  |                                        202  3  101
     |  SIDE 1 OR 2                              210  3  52       AERIAL 2
     |                                           214  3  96
     DISK ID#                                    218  3  15
     0=MAIN DISK                                 255  255
     1=CLIP ART VOL. 1                           181  3  82
     2=  "   "   "   2                           182  3  121      AUTO 1
     3=  "   "   "   3                           184  3  3
                                                     ETC.

                                                 SECTOR  BYTE
                                                 LO  HI  OFFSET


FIGURE 3

    First, you read the directory while counting the number of filenames you pass in order to find the one you want. Then you must search the sector table looking for and counting the file separators until you reach the one you want. For example, in Clip Art Volume 1, AUTO1 is the third name in the directory so you search until you find the second header in the sector table. The next three-byte entry will be the first graphic in the AUTOI file. Now by our example this would be 181,3,82. The sector number is 181+3*256 or 949 and the offset into sector 949 is byte 82. The data for this file is illustrated in Figure 4.
    The first four bytes give the screen boundaries of the graphic. Following are two types of data, single and repeat. Single data is a single byte whose value is placed directly on screen. To save disk space, when a byte is used more than once in a row, a special code is used to "compress" the data (most pictures contain large amounts of repetitive data). Each repetition is three bytes long: a 0 indicates a repetition followed by the number of repeats then the value to be repeated. Of course that means that any blank space, or 0, must be represented as a repetition: A single blank would then be 0, l, 0. Since blanks are the most common repeat, it works out well.
    Finally, bytes are scanned vertically, not in the usual horizontal fashion, proceeding column by column from the upper left to the lower right. Each sector uses all 128 bytes so there is no forward chaining or jumping sectors. Each sector must be contiguous with the last as are all graphics within a file. The left-hand margin of the screen area is actually 8, so any graphic saved past that margin will overwrite the Icon area and will be "inverted." Try not to save graphics past the left margin, but don't worry about Print Shop graphics; they are automatically marginated.

SECTOR 949
BYTE        DATA
     PICTURE

82           1     TOP ROW
83           21    BOTTOM ROW
84           8     LEFT COLUMN
85           84    RIGHT COLUMN
86           0

87 10 SPACES 10    REPEAT DATA
88           0

89         1
90        3
91       7
92       14
93        28     SINGLE DATA
94       56

95       112
96  225
97           0

98 5 SPACES  5     REPEAT DATA
99           0


FIGURE 4

Final Notes
    With UGFC you now have a way of changing one format to another among the best and most commonly used graphics programs. While UGFC should run on any type of Atari computer, I doubt it would work on an 810 disk drive because of the number of sectors on the disk; but if your drive will run Newsroom, it will run UGFC.
    To round out UGFC, you will need a Graphics 8 paint program. The only one I am aware of is Graphics Master by Courtney Goodin which is not in current distribution. I happen to be lucky enough to be in the same users' group as Courtney but for the rest of you, hound ANALOG to get one in print! [Okay, software authors: Anyone want to submit a Graphics 8 paint program?-ed.] One exciting possibility is the ability to incorporate digitized photos or illustrations into your Newsroom creations.
    So here you find the sum of all I have learned in the last two months. Now you know why I never finished making my newsletter! Maybe I can be a user for a while instead of a programmer-that is until the next idea hits me!

Addendum
    As an afterthought I have included a short no-frills program to convert Newsroom Photos and Banners to Graphics 8 files. You need only a load-and-save filename. Newsroom stores photos and banners as DOS binary files with the first two characters of the filename "PH" for a photo and "BN" for a banner then a 6-byte filename without extenders. The graphics file consists of an 8-byte header, then the graphic margins.
    The next group of bytes is variable and contains the word "Newsroom" at least once. Following are some blank spaces and assorted data which includes the disk and graphic number of the original Newsroom clip art graphic. All this ends in a header that is a 255 followed by a 0. The banner or photo is then stored as a single file with no compression, horizonal scan, but in inverted (black-on-white background) form.
    To type in this program, first type Listing 3 and save it to disk. Next type Listing 4, save it and run it. A file named TEMP.LST will be created on your disk. Merge this file with the program from Listing 3 in the manner described in "Typing it in" above.


LISTING 1: BASIC
Blue indicates inverse video

EI 1 REM *******************************
CV 2 REM *      ULTIMATE GRAPHICS      *
PA 3 REM *       FILE CONVERTOR        *
OD 4 REM *    by Lee Brilliant, M.D.   *
TC 5 REM *                             *
FS 6 REM *       Copyright 1989        *
TC 7 REM *     by ANALOG COMPUTING     *
EP 8 REM *******************************
QQ 9 GOTO 900
GE 10 REM *** 10-500 BASIC SUBROUTINES FO
   R SPEED
PQ 20 IF BUF$(N,N)="" THEN 60
SG 30 FN$(S)=BUF$(N,N):S=S+1
AD 35 N=N+1
JY 40 IF N=129 THEN N=1:SECT=SECT+1:GOSUB
    10000
RV 50 GOTO 20
SR 60 DIR$(COUNT*32+1,000NT*32+LEN(FN$))=
   FN$:COUNT=COUNT+1:POKE 755,( NOT (PEEK
   (755)))*2
IW 70 IF N=128 THEN N=0:SECT=SECT+1:GOSUB
    10000
ZG 80 S=1:IF COUNT=SIZE THEN RETURN
UG 90 GOTO 35
TY 100 DIR$="":S=0:FOR SECT=13 TO 24:GOSU
   B 10040:DIR$(LEN(DIR$)+1)=BUF$(1,128):
   NEXT SECT
CJ 110 FOR N=1 TO LEN(DIR$):IF S=COUNT TH
   EN POP :GOTO 150
MZ 120 IF DIR$(N,N+1)="" THEN S=S+1:N=N
   +1:POKE 755,( NOT (PEEK(755)))*2:REM E
   SC-CNTL>
HV 130 NEXT N
NQ 150 SECT=INT(N/128):BYTE=N-SECT*128:SE
   CT=SECT+13:RETURN :REM S$B OF 1ST GRAP
   HIC
BM 180 X=ASC(BUF$(BYTE)):BYTE=BYTE+1:IF B
   YTE>128 THEN BYTE=1:SECT=SECT+1:GOSUB
   10000
ZP 190 RETURN
ZD 300 A=USR(ADR(MOVE$),ADR(UNCOMP$),1536
   ,LEN(UNCOMP$)):A=USR(1536,START,R,SIZE
   ,BYTE-1,ADR(BUF$)):RETURN
GZ 400 A=USR(ADR(MOVE$),ADR(C0MP$),1536,L
   EN(C0MP$)):A=USR(1536,START,R,SIZE,ADR
   (DIR$)):RETURN
VK 499 REM *** 500-900 CURSOR CONTROL SUB
   ROUTINES
GT 500 GET #2,K:IF K=155 THEN RETURN
GH 510 IF K=27 THEN POP :POP :GOTO 1005
WH 520 IF K=32 THEN FLAG= NOT (FLAG):GOTO
    700
GS 525 IF K>27 AND K<32 THEN ON K-27+D GO
   SUB 600,602,604,606,610,620,630,640,65
   0,660,670,680:GOTO 550
PV 526 IF D>0 THEN IF K>48 AND K<51 THEN
   D=(K-48)*4
NE 530 GOTO 500
RB 550 IF D=0 THEN A=USR(1560,ROWT,COLL,R
   OWT+52,COLL+88):GOTO 500
GH 551 A=USR(1560,ROWT,COLL,ROWB,COLR):GO
   TO 500
QG 600 IF ROWT>0 THEN ROWT=ROWT-1
ZF 601 RETURN
JG 602 IF ROWT<139 THEN ROWT=ROWT+1
ZL 603 RETURN
UC 604 IF COLL>0 THEN COLL=COLL-1
ZR 605 RETURN
DT 606 IF COLL<231 THEN COLL=COLL+1
ZX 607 RETURN
QI 610 IF ROWT>0 THEN ROWT=ROWT-1
ZH 611 RETURN
WK 620 IF ROWT+1<ROWB THEN ROWT=ROWT+1
ZJ 621 RETURN
TW 630 IF COLL>0 THEN COLL=COLL-1
ZO 632 RETURN
IC 640 IF COLL+1<COLR THEN COLL=COLL+1
ZN 641 RETURN
PW 650 IF ROWB-1>ROWT THEN ROWB=ROWB-1
ZP 651 RETURN
OK 660 IF ROWB<191 THEN ROWB=ROWB+1
ZR 661 RETURN
ZK 670 IF COLR-1>COLL THEN COLR=COLR-1
ZT 671 RETURN
WY 680 IF COLR<319 THEN COLR=COLR+1
ZV 681 RETURN
DW 700 IF FLAG=0 THEN GOSUB 13020:GOTO 50
   0
AR 710 GOSUB 13030:? "USE TO MO
   VE FRAME. USE ESC":? "TO GO BACK, RETU
   RN TO SAVE GRAPHIC,"
NE 720 ? "AND SPACE BAR TO TOGGLE WINDOW.
   ":IF T0=4 THEN ? "1 & 2 SELECT CURSOR
   LINES.";
NG 730 GOTO 500
YC 800 POSITION 0,OLDY:? #6;" ":POSITION
   0,NWY:? #6;"→":OLDY=NWY
HA 810 GET #2,K
PM 820 IF K=28 OR K=45 THEN NWY=NWY-2:GOT
   O 860
LX 830 IF K=29 OR K=61 THEN NWY=NWY+2:GOT
   O 860
NH 840 IF K=155 THEN 890
PA 850 GOTO 810
SV 860 IF NWY<YMIN THEN NWY=YMAX
SR 870 IF NWY>YMAX THEN NWY=YMIN
OV 880 GOTO 800
JW 890 SELECT=(NWY-YMIN+2)/2:RETURN
PU 900 REM DIMENSION VARIABLES
PW 901 OPEN #2,4,0,"K:"
QL 910 DIM CALL$(5),BUF$(129),FN$(16),DIR
   $(7680),MOVE$(49),ORA$(51),CURSOR$(243
   ),ROR$(43),ROL$(44)
ZM 920 DIM CBMP$(239),UNCOMP$(194)
BM 963 CURSOR$(74,74)=CHR$(157):CURSOR$(2
   27,227)=CHR$(255)
MA 1000 OPEN #6,12,0,"S:":DL=PEEK(560)+25
   6*PEEK(561):POKE DL+2,70:POKE DL+3,PEE
   K(DL+4):POKE DL+4,PEEK(DL+5)
DP 1001 POKE DL+5,6:POKE 710,0:POKE 709,1
   4:POKE 82,0
TM 1005 POKE 752,1:? CHR$(125);"  ULTIMAT
   E GRAPHICS    file converter"
WD 1010 ? " FORMAT TO LOAD FROM ":? :? "
    1)MICROPAINTER(62 SECTOR)"
VV 1020 ? :? " 2)GRAPHICS 8 SCREEN":? :?
    "  3)PRINT SHOP ICON"
KZ 1030 ? :? " 4)NEWSROOM":? :? " FORMAT
    TO SAVE TO "
JU 1040 ? :? " 1)MICROPAINTER(62 SECTOR)
   ":? :? " 2)GRAPHICS 8 SCREEN"
LZ 1050 ? :? " 3)PRINT SHOP ICON":? :? "
     4)NEWSROOM"
VQ 1060 POKE 703,4:GOSUB 13010
RJ 1070 OLDY=3:NWY=3:YMIN=3:YMAX=9:GOSUB
   800:FROM=SELECT
VA 1080 OLDY=13:NWY=13:YMIN=13:YMAX=19:GO
   SUB 800
NK 1090 IF SELECT<>FROM THEN 1100
RA 1095 ? "":? "YOU CAN'T USE THE SAME F
   ORMAT AS FROM":GOSUB 13000:GOSUB 13010
   :GOSUB 800:GOTO 1890
NV 1100 T0=SELECT
AX 1200 POKE 703,24:POKE 752,1:? "":? "I
   NSERT SOURCE DISK. PRE55 ANY KEY."
HG 1210 GET #2,K
WY 1300 ON FROM GOSUB 13100,13100,13300,1
   3500:REM GET DIRECTORY
ZL 1350 POKE 752,0:TRAP 48000:? "":? "EN
   TER FILE NAME:";:INPUT FN$
US 1400 IF FN$="" THEN 1200
GA 1500 REM GET FILE NAME
LF 1501 ON FROM GOSUB 2000,2000,4000,5000
QK 1515 GOSUB 13030:TRAP 40000
UQ 1520 ? "ENTER SAVE FILE NAME:";:INPUT
    FN$
AC 1525 IF FN$="" THEN 1520
IY 1530 ? "INSERT  BLANK  DISK & PRESS A
   NY KEY.":GOSUB 13000
HV 1540 GET #2,K:? "PRESS  RETURN  TO FOR
   MAT & SAVE FILE,":? " ESC  TO QUIT.":G
   ET #2,K:IF K=27 THEN RUN
UO 1550 IF K<>155 THEN 1530
YR 1560 TRAP 11300:? "FORMATTING DISK":X
   IO 254,#1,0,0,"D:":GOSUB 13020
BV 1600 ON T0 GOSUB 6000,7000,8000,9000
KR 1700 GRAPHICS 1:POKE 710,0:? #6;" YOU
   HAVE FINISHED":? #6;"       USING":? #
   6:? #6;"        the":? #6
TW 1710 ? #6;" ultimate graphics":? #6;"
     file converter":POKE 752,1
PJ 1720 ? "PRESS RETURN FOR ANOTHER CONVE
   RSION."
VJ 1750 GET t#2,K:IF K=155 THEN RUN
TN 1760 GOTO 1750
QW 2000 REM MICROPAINTER GET
QD 2010 BUF$="D:":BUFS(3)=FN$:FN$=BUF$
AP 2020 TRAP 11100:OPEN #3,4,0,FN$:GOSUB
   13020:? #6; CHR$(125)
VE 2100 POKE 882,7:POKE 884,PEEK(88):POKE
    885,PEEK(89):POKE 888,0:POKE 889,30
GX 2110 A=USR(ADR("")):CLOSE #:TR
   AP 40000:RETURN
FF 3000 REM GR.8 GET SAME AS MICROPAINTER
MV 4000 REM PS GET
EV 4010 FN$(LEN(FN$)+1)="
       ":? "":? "LOADING ":FN$
SH 4020 FOR N=1 TO COUNT*32 STEP 32:IF DI
   R$(N,N+15)=FN$ THEN POP :GOTO 4050
PY 4030 NEXT N:POKE 195,170:POP :GOTO 111
   00
YD 4050 SECT=ASC(DIR$(N+16))+256*ASC(DIR$
   (N+17))
FG 4060 FOR N=1 TO 379 STEP 126:GOSUB 100
   40:DIR$(N)=BUF$(1,126):SECT=ASC(BUF$(1
   27))+256*ASC(BUF$(128)):NEXT N
XZ 4070 GOSUB 10040:DIR$(N)=BUF$(1,68):PO
   KE 755,2:GOSUB 13020:? #6;CHR$(125)
QQ 4080 START=PEEK(88)+256*PEEK(89)
QR 4100 FOR N=1 TO 572 STEP 11:A=USR(ADR(
   ORA$),ADR(DIR$)+N-1,START,11):START=ST
   ART+40:NEXT N
AH 4110 RETURN
XP 5000 REM NEWSROOM GET
BM 5010 FN$(LEN(FN$)+1)="
   ":? "":POKE 752,1:? "LOADING "; FN$
UZ 5020 FOR N=1 TO COUNT*32 STEP 32:IF DI
   R$(N,N+15)=FN$ THEN POP :GOTO 5050
PZ 5030 NEXT N:POKE 195,170:POP :GOTO 111
   00
RV 5050 COUNT=(N-1)/32:GOSUB 100:GOSUB 13
   020:? #6;CHR$(125):GOSUB 10000
MU 5070 GOSUB 180:LO=X:GOSUB 180:HI=X:GOS
   UB 180:OFF=X
GY 5080 SECT=LO+256*HI:BYTE=OFF+1:IF BYTE
   >128 THEN BYTE=1:SECT=SECT+1:GOSUB 100
   00
JD 5090 FOR TIMES=1 TO 16:DIR$(1)="":DIR
   $(7600)="":DIR$(2)=DIR$
KF 5100 GOSUB 10000:GOSUB 180:ROWT=X:GOSU
   B 180:ROWB=X:GOSUB 180:COLL=X:GOSUB 18
   0:COLR=X
PU 5110 C=INT((COLR-COLL)/8)+1:R=ROWB-ROW
   T+1:SIZE=C*R:START=ADR(DIR$)+40*(ROWT-
   1)+INT(COLL/8)
VZ 5120 GOSUB 300:SECT=PEEK(778)+256*PEEK
   (779):BYTE=PEEK(1726):SHIFT=COLL-INT(C
   OLL/8)*8:IF SHIFT=0 THEN 5125
OG 5122 FOR N=1 TO SHIFT:A=USR(ADR(ROR$),
   ADR(DIR$),7680):NEXT N
YP 5125 A=USR(ADR(ORA$),ADR(DIR$),PEEK(88
   )+256*PEEK(89),7680)
LB 5130 NEXT TIMES
AJ 5300 RETURN
NT 6000 REM MICROPAINTER PUT
OA 6601 TRAP 40000:GOTO 6500
LY 6010 GOSUB 9002:DIR$(1)="":DIR$(7680)
   ="":DIR$(2)=DIR$:START=PEEK(88)+256*P
   EEK(89):OFF=ROWT*40+LBYTE
PJ 6015 LPRINT ROWT,ROWB,COLL,COLR,LBYTE,
   WIDE,C,OFF
GZ 6020 FOR N=ROWT TO ROWB:A=USR(ADR(MOVE
   $),START+OFF,ADR(DIR$)+OFF,WIDE):OFF=0
   FF+40:NEXT N
CZ 6030 BUF$="D:":BUF$(3)=FN$:TRAP 11200:
   OPEN #3,8,0,BUF$:AD=ADR(DIR$):HI=INT(A
   D/256):LO=AD-256*HI
FJ 6040 POKE 882,11:POKE 884,LO:POKE 885,
   HI:POKE 888,0:POKE 889,30:A=USR(ADR("h
   "))
AT 6050 RETURN
RA 6500 GOSUB 6010:PUT #3,0:PUT #3,14:PUT
    #3,14:PUT #3,14:CLOSE #3:RETURN
PA 7000 REM GR.8 PUT
   ="SSI CLIP NEWSROOM" THEN 13600
WU 13510 ? "":? "NOT A NEWSROOM DISK!":?
    "INSERT A NEWSROOM CLIP ART DISK AND"
   :? "PRESS RETURN OR ESC TO GO BACK."
NE 13515 GOSUB 13000
DN 13520 GET #2,K:IF K=155 THEN 13500
WR 13530 IF K=27 THEN POP :GOTO 1005
CA 13540 GOTO 13520
PE 13600 DIR$(1)=" ":DIR$(7680)=" ":DIR$(
   2)=DIR$:? "":POSITION 8,10:? " Readin
   G DIRECTORY";
CM 13610 SIZE=ASC(BUF$(28)):COUNT=0:S=1:N
   =32:GOSUB 20:POKE 755,2:POKE 752,1:A=0
   :GOTO 13410
   K(195);". CORRECT AND PRESS ANY KEY.":
   GET #2,K
ZW 11210 ON T0 GOTO 6000,7000
XP 11300 GRAPHICS 0:? "FORMATTING ERROR.
   USE NEW DISK.":END
QF 13000 SOUND 0,200,10,10:A=1^1:SOUND 0,
   250,10,10:A=1^1:SOUND 0,0,0,0:FOR DELA
   Y=1 TO 100:NEXT DELAY:RETURN
JN 13010 ? "":? "USE THEN PRESS
   RETURN":RETURN
GM 13020 GRAPHICS 8+16+32:POKE 710,0:POKE
    709,14:RETURN
KK 13030 GRAPHICS 8+32:POKE 710,0:POKE 70
   9,14:RETURN
YT 13100 REM DOS DIRECTORY
BQ 13101 TRAP 11000:OPEN #l,6,0,"D:*.*":P
   OKE 201,14:POKE 675,0:POKE 676,2:POKE
   677,0:POKE 678,8:POKE 679,0:? ""
SS 13110 INPUT #1,FN$:IF FN$(6,9)="FREE"
   THEN 13130
RK 13120 ? FN$(3,13);"";:GOTO 13110
DP 13130 CLOSE #1:TRAP 40000:POKE 703,4:R
   ETURN
JE 13300 REM PRINT SHOP DIRECTORY
NZ 13301 ? "":? :SECT=361:GOSUB 10000:IF
    BUF$(1,15)="PRINT SHOP:CLK!" THEN 133
   50
AS 13310 ? "":? "NOT A PRINT SHOP DISK":
   ? "INSERT PRINT SHOP GRAPHICS DISK AND
   ":? "PRESS RETURN OR ESC TO GO BACK."
MY 13315 GOSUB 13000
AV 13320 GET #2,K:IF K=155 THEN 13300
WL 13330 IF K=27 THEN POP :GOTO 1005
AS 13340 GOTO 13320
GO 13350 DIR$(1)=" ":DIR$(7680)=" ":DIR$(
   2)=DIR$:POSITION 8,10:? " READING DIRE
   CTORY ";:COUNT=0:TRAP 40000
XT 13360 FOR SECT=362 TO 393:GOSUB 10040
RY 13370 FOR N=0 TO 96 STEP 32:FN$=BUF$(N
   +20,N+20):IF FN$="X" OR FN$="x" THEN 1
   3380
BN 13375 GOTO 13400
LU 13380 DIR$(COUNT*32+1,000NT*32+32)=BUF
   $(N+1,N+32):COUNT=COUNT+1
YP 13400 NEXT N:NEXT SECT:POKE 755,2:POKE
    755,2:POKE 752,1:A=0
HR 13410 ? "":FOR N=0 TO 11:POSITION 6,1
   +N:? DIR$(32*(N+A)+1,32*(N+A)+16);"  "
   ;DIR$(32*(N+12+A)+1,32*(N+12+A)+16)
IR 13420 NEXT N
IV 13430 POKE 703,4:? "PRESS FOR
    MORE TITLES,  ESC ":? "TO GO BACK, &
    RETURN  TO CHOOSE TITLE."
KL 13440 GET #2,K
YW 13450 IF K=27 THEN POKE 703,24:POP :GO
   TO 1005
SE 13460 IF K=155 THEN RETURN
EM 13465 IF K=61 OR K=45 THEN 13480
CO 13470 IF K<28 OR K>29 THEN 13440
JD 13480 IF K=28 OR K=45 THEN IF COUNT>A+
   24 THEN A=A+24:POKE 703,24:GOTO 13410
AM 13490 IF K=29 OR K=61 THEN IF A>0 THEN
    A=A-24:POKE 703,24:GOTO 13410
EG 13495 GOTO 13440
MA 13500 REM DIRECTORY FOR NEWSROOM
QB 13501 SECT=1:GOSUB 10000:IF BUF$(1,17)
XY 10020 POKE 779,INT(SECT/256):POKE 778,
   SECT-INT(SECT/256)*256:POKE 769,1:A=US
   R(ADR(CALL$))
XH 10030 IF PEEK(771)=1 THEN RETURN
ZC 10035 GRAPHICS 0:? "DISK ERROR NUMBER
   ";PEEK(771):END
UB 10040 POKE 755,( NOT (PEEK(755)))*2:GO
   TO 10000
WC 10050 POKE 770,87:GOTO 10010
TK 11000 CLOSE #l:IF PEEK(195)=136 THEN 1
   3130
JS 11010 ? "ERROR ";PEEK(195):STOP
LA 11100 CLOSE #3:IF PEEK(195)=170 THEN ?
    "":? "FILE NOT FOUND! PRESS ANY KEY"
   :GOSUB 13000:GET #2,K:GOTO 1350
FK 11110 ? "":? "ERROR ";PEEK(195);".  P
   RESS ANY KEY.":GOSUB 13000:GET #2,K:GO
   TO 1350
CG 11200 POP :GOSUB 13030:? "ERROR ";PEE
   START+7688,7680):NEXT N
WE 8240 FOR N=0 TO 571 STEP 11:A=USR(ADR(
   MOVE$),START+OFF,ADR(DIR$)+N,11)
GD 8250 OFF=OFF+40:NEXT N
BL 8260 SECT=1:FOR N=1 TO 572 STEP 126:BU
   F$=DIR$(N,N+126):BUF$(127)=CHR$(SECT+1
   ):BUF$(128)=""
CN 8270 GOSUB 10050:SECT=SECT+1:NEXT N
BI 8280 RETURN
QQ 9000 REM NEWSROOM PUT
UK 9001 GOTO 9080
IX 9002 IF FROM=3 THEN COLL=0:ROWT=0:COLR
   =88:ROWB=52:GOTO 9030
BL 9005 A=USR(ADR(MOVE$),ADR(CURSOR$),153
   6,LEN(CURSOR$)):A=USR(1560,0,0,191,319
   )
US 9010 D=4:FLAG=0:COLL=0:ROWT=0:COLR=319
   :ROWB=191:POKE 764,33:GOSUB 500
IA 9020 A=USR(1560,0,0,0,0)
FB 9030 LBYTE=INT(COLL/8):RBYTE=INT(COLR/
   8):SHIFT=COLL-LBYTE*8:C=COLR-COLL:SHIF
   T2=7-(C-INT(C/8)*8):WIDE=INT(C/8)+1
NT 9040 IF SHIFT2=0 THEN 9060
SW 9050 COLOR 0:FOR N=1 TO SHIFT2:PLOT CO
   LR+N,ROWT:DRAWTO COLR+N,ROWB:NEXT N
UX 9060 START=PEEK(88)+256*PEEK(89):IF SH
   IFT=0 THEN 9075
ZX 9070 FOR N=1 TO 5HIFT:A=USR(ADR(ROL$),
   START+7680,7680):NEXT N
BW 9075 RETURN
AY 9080 GOSUB 9002:5TART=START+INT(COLL/8
   )+ROWT*40:R=ROWB-ROWT+1:SIZE=R*(INT(C/
   8)+1)
TR 9090 DIR$(1)="":DIR$(7680)="":DIR$(2
   )=DIR$
LJ 9100 G05UB 400:SIZE=PEEK(205)+256*PEEK
   (206)-ADR(DIR$)
EM 9110 BUF$(1)="":BUF$(129)="":BUF$(2)
   =BUF$:BUF$(1,17)="SSI CLIP NEWSROOM":B
   UF$(26,28)=""
EP 9120 BUF$(32,LEN(FNS)+32)=FN$:SECT=1:G
   OSUB 10050
HU 9130 BUF$(1)="":BUF$(129)="":BUF$(2)
   =BUF$:BUF$(1)=CHR$(60):BUF$(2)=CHR$(0)
   :BUF$(3)=CHR$(0):BUF$(4,6)=""
XJ 9140 SECT=13:GOSUB 10050:SECT=60:BUF$(
   1)="":BUF$(129)="":BUF$(2)=BUF$
QD 9145 BUF$(1)=CHR$(ROWT+1):BUF$(2)=CHR$
   (ROWS+1):IF FROM=3 THEN COLL=8:COLR=96
WR 9150 BUF$(3)=CHR$(COLL):BUF$(4)=CHRS(C
   OLR):BUF$(5)=DIR$:GOSUB 10050:IF SIZE<
   125 THEN 9200
QD 9160 FOR N=125 TO SIZE STEP 128:BUF$(1
   )="":BUF$(129)="":BUF$(2)=BUF$:BUF$=
   DIR$(N):SECT=SECT+1:GOSUB 10050
HX 9170 NEXT N
AL 9200 RETURN
NK 10000 BUF$(1)="":BUF$(129)="":BUFS(2)=
   BUF$:POKE 770,82
EL 10010 A=ADR(BUF$):POKE 773,INT(A/256):
   POKE 772,A-INT(A/256)*256
IL 7001 GOSUB 6010:CLOSE #3:RETURN
CM 8000 REM PRINTSHOP PUT
YN 8001 A=USR(ADR(MOVE$),ADR(CURSOR$),153
   6,LEN(CURSOR$)):A=USR(1560,70,116,122,
   204)
ZQ 8010 D=0:FLAG=0:COLL=116:ROWT=70:POKE
   764,33:GOSUB 500
HZ 8020 A=USR(1560,0,0,0,0)
MK 8201 BUF$="PRINT SHOP:CLK!":BUF$(18)
   ="":BUF$(129)="":BUF$(19)=BUF$(18):B
   UF$(33,33)=""
VP 8202 BUF$ (78,82)=""
DP 8210 SECT=361:GO5UB 10050
KB 8220 BUF$=FN$:BUF$(LEN(BUF$)+1)="
              "
SZ 8230 BUF$(17,22)="":BUF$(23)=""
   :BUF$(129)="":BUF$(24)=BUF$(23):SECT=
   362:GOSUB 10050
TK 8232 DIR$(1)="":DIR$(7680)="":DIR$(2
   )=DIR$
DX 8235 START=PEEK(88)+256*PEEK(89):I=INT
   (COLL/8):OFF=ROWT*40+I:SHIFT=COLL-8*I:
   IF SHIFT=0 THEN 8240
AM 8236 FOR N=1 TO SHIFT:A=USR(ADR(ROL$),


LISTING 2: BASIC

SA 5 LINE=100
GZ 10 FOR N=1 TO 1092 STEP 26:ST=0:FOR S=
   1 TO 26:READ D:ST=ST+D:T=T+D:NEXT 5
LR 20 READ X:IF X<>ST THEN ? "ERROR IN LI
   NE #";LINE:STOP
SO 30 ? "LINE ";LINE;" OK!"
QN 40 LINE=LINE+l0:NEXT N
PE 50 IF T<>112481 THEN ? "CHECKSUM ERROR
   ":END
DL 60 ? "INSERT FORMATTED DISK & PRESS
    ANY KEY":POKE 764,255
YH 65 IF PEEK(764)=255 THEN 65
TN 70 ? : ? "WRITING FILE "D:TEMP.LST"";:o
   PEN #l,8,0,"D:TEMP.LST":RESTORE :POKE
   764,255
AS 80 FOR N=1 TO 1092 STEP 26:FOR X=l TO
   26:READ D:PUT #1,D:NEXT X:READ D:POKE
   755,( NOT (PEEK(755)))*2:NEXT N
IH 90 CLOSE #1:? :? :? "DONE":END
OL 100 DATA 57,50,49,32,67,48,77,80,36,61
   ,34,104,104,133,204,141,230,6,104,133,
   203,141,229,6,104,104,2537
AB 110 DATA 141,233,6,141,235,6,104,141,2
   32,6,104,141,231,6,104,133,206,104,133
   ,205,160,0,140,237,6,140,3295
AE 120 DATA 236,6,177,203,141,234,6,24,16
   5,203,105,40,133,203,165,204,105,0,133
   ,204,206,235,6,208,24,173,3539
GL 130 DATA 233,6,141,235,6,238,229,6,208
   ,3,238,230,6,34,155,57,50,50,32,67,48,
   77,80,36,40,56,2561
FR 140 DATA 49,41,61,34,173,229,6,133,203
   ,173,230,6,133,204,173,231,6,208,17,17
   3,232,6,208,9,173,237,3348
SC 150 DATA 6,208,3,32,199,6,96,206,232,6
   ,206,231,6,177,203,170,173,237,6,208,3
   8,173,234,6,208,6,3276
SG 160 DATA 238,237,6,76,161,6,236,234,6,
   240,11,173,234,6,145,205,32,192,6,76,4
   3,6,169,1,141,236,3116
HK 170 DATA 6,141,237,6,76,43,34,155,57,5
   0,51,32,67,48,77,80,36,40,49,54,49,41,
   61,34,6,238,1768
MM 180 DATA 236,6,208,15,206,236,6,32,199
   ,6,238,236,6,140,237,6,76,115,6,236,23
   4,6,240,3,32,199,3160
JP 190 DATA 6,76,43,6,230,205,208,2,230,2
   06,96,169,0,145,205,32,192,6,173,236,6
   ,145,205,32,192,6,3052
XY 200 DATA 173,234,6,145,205,32,192,6,14
   0,237,6,140,236,6,96,0,0,0,0,0,0,0,0,0
   ,0,34,1888
VL 210 DATA 155,57,50,52,32,85,78,67,79,7
   7,80,36,61,34,104,104,133,206,141,186,
   6,104,133,205,141,185,2591
DA 220 DATA 6,104,104,141,189,6,141,191,6
   ,104,141,188,6,104,141,187,6,104,104,1
   41.190.6.104,133,204.104,2855
Ah 230 DATA 133,203,160,0,140,184,6,173,1
   84,6,240,1,96,32,83,6,138,240,6,32,113
   ,6,34,155,57,50,2478
HR 240 DATA 53,32,85,78,67,79,77,80,36,40
   ,54,49,41,61,34,76,45,6,32,83,6,142,19
   2,6,32,83,1569
MR 250 DATA 6,32,113,6,206,192,6,208,248,
   76,45,6,172,190,6,177,203,72,238,190,6
   ,16,16,169,0,141,2740
VR 260 DATA 190,6,238,10,3,208,3,238,11,3
   ,32,83,228,104,170,96,173,187,6,208,12
   ,173,188,34,155,57,2816
DN 270 DATA 50,54,32,85,78,67,79,77,80,36
   ,40,49,50,49,41,61,34,6,208,4,238,184,
   6,96,206,188,2098
IB 280 DATA 6,206,187,6,160,0,138,145,205
   ,206,191,6,208,27,238,185,6,208,3,238,
   186,6,173,185,6,133,3258
OP 290 DATA 205,173,186,6,133,206,173,189
   ,6,141,191,6,76,183,6,24,165,205,105,4
   0,133,205,165,206,105,0,3233
PS 300 DATA 133,206,96,0,0,0,0,0,0,0,0,0,
   0,34,155,57,51,48,32,67,65,76,76,36,61
   ,34,1227
NO 310 DATA 104,32,83,228,96,34,155,57,52
   ,48,32,77,79,86,69,36,61,34,104,104,13
   3,204,104,133,203,104,2452
KL 320 DATA 133,206,104,133,205,104,133,2
   08,104,133,207,160,0,165,207,208,7,165
   ,208,208,1,96,198,208,198,207,3906
PH 330 DATA 177,203,145,205,200,208,4,230
   ,204,230,206,144,230,176,228,34,155,57
   ,53,48,32,79,82,65,36,61,3492
RJ 340 DATA 34,104,104,133,204,104,133,20
   3,104,133,206,104,133,205,104,133,208,
   104,133,207,160,0,165,207,208,7,3540
DU 350 DATA 165,208,208,1,96,198,208,198,
   207,177,205,17,203,145,205,200,208,4,2
   30,204,230,206,144,228,176,226,4497
NY 360 DATA 34,155,57,54,48,32,67,85,82,8
   3,79,82,36,61,34,0,0,0,0,0,0,0,0,0,0,0
   ,989
IV 370 DATA 0,0,0,0,0,128,64,32,16,8,4,2,
   1,104,104,104,141,6,6,104,141,8,6,104,
   141,7,1231
WA 380 DATA 6,104,104,141,9,6,104,141,11,
   6,104,141,10,6,169,0,141,12,6,32,80,6,
   32,80,6,32,1489
SY 390 DATA 80,6,32,80,6,162,5,189,6,6,32
   ,0,6,202,16,247,96,174,12,6,189,0,6,32
   ,179,6,1775
WS 400 DATA 174,34,155,57,54,49,32,67,85,
   82,83,79,82,36,40,57,49,41,61,34,12,6,
   232,189,0,6,1796
SR 410 DATA 141,14,6,232,189,0,6,141,15,6
   ,232,142,12,6,32,114,6,96,173,14,6,41,
   7,170,189,16,2006
TQ 420 DATA 6,141,13,6,162,3,78,15,6,110,
   14,6,202,208,247,24,173,14,6,101,88,13
   3,205,165,89,105,2320
TW 430 DATA 0,133,206,160,0,162,192,177,2
   05,77,13,6,145,205,24,165,205,105,40,1
   33,205,165,206,105,0,133,3167
BI 440 DATA 206,202,208,233,96,141,34,155
   ,57,54,50,32,67,85,82,83,79,82,36,40,4
   9,56,49,41,61,34,2312
ZZ 450 DATA 14,6,169,40,141,15,6,162,8,16
   9,0,133,203,133,204,10,38,203,14,15,6,
   144,8,24,109,14,1988
IG 460 DATA 6,144,2,230,203,202,208,237,2
   4,101,88,133,205,165,203,101,89,133,20
   6,169,32,141,13,6,160,39,3240
WW 470 DATA 173,13,6,81,205,145,205,136,1
   6,246,96,34,155,57,55,48,32,82,79,82,3
   6,61,34,104,104,133,2418
ET 480 DATA 204,104,133,203,104,133,206,1
   04,133,205,160,0,24,165,205,208,7,165,
   206,208,1,96,198,206,198,205,3781
QH 490 DATA 177,203,106,145,203,200,208,2
   ,230,204,144,231,176,229,34,58,82,79,7
   6,36,61,34,104,104,133,204,3463
FM 500 DATA 104,133,203,104,133,206,104,1
   33,205,160,0,24,165,205,208,7,165,206,
   208,1,96,198,206,198,205,177,3754
MT 510 DATA 203,42,145,203,152,208,2,198,
   204,136,144,230,176,228,34,155,0,0,0,0
   ,0,0,0,0,0,0,2460


LISTING 3: BASIC

MD 10 GOSUB 1000
AW 20 FOR R=ROWT TO ROWB:FOR S=LC TO S+WI
   DE:GET #3,X:POKE S,X:NEXT S:LC=LC+40:N
   EXT R
TD 30 IF COLR=RBYTE*8+7 THEN 50
BB 40 FOR N=COLR TO RBYTE*8+7:PLOT N,ROWT
   :DRAWTO N,ROWB:NEXT N
WC 50 IF FLAG THEN PLOT 0,ROWT:DRAWTO 0,R
   OWB
KV 53 LC=START:FOR N=ROWT TO ROWB:A=USR(A
   DR(EOR$),LC,WIDE+1):LC=LC+40:NEXT N
JE 55 GRAPHICS 8+32:POKE 710,0:POKE 709,1
   4:? "SAVING"
ZH 60 CLOSE #3: OPEN #3,8,0,FN2$
JP 70 POKE 882,11:POKE 884,PEEK(88):POKE
   885,PEEK(89):POKE 888,0:POKE 889,30:A=
   USR(ADR(""))
MK 80 CLOSE #3
WS 90 GRAPHICS 2+16:POSITION 8,6:? #6;"DO
   NE"
LG 100 GOTO 100
VI 999 STOP
DY 1010 DIM FN1$(15),FN2$(15),CALL$(5)
FJ 1020 ? CHR$(125):POSITION 2,10:? "USE
   DEVICE ID AND EXTENTERS.":POSITION 2,1
   :? "ENTER LOAD FILENAME:";:INPUT FN1$
AX 1030 ? :? "ENTER SAVE FILENAME:";:INPU
   T FN2$
IH 1040 D=47:IF FN1$(3,4)="BN" OR FN1$(4,
   5)="BN" THEN FLAG=1:D=31
BV 1050 OPEN #3,4,0,FN1$
YH 1060 FOR N=1 TO 8:GET #3,X:NEXT N
RX 1070 GET #3,ROWT:GET #3,ROWB:GET #3,CO
   LL:GET #3,COLR:IF FLAG THEN COLL=1:COL
   R=239
GJ 1080 FOR N=1 TO D:GET #3,X:NEXT N
MI 1090 LBYTE=INT(COLL/8):RBYTE=INT(COLR/
   8):WIDE=RBYTE-LBYTE
FC 1100 GRAPHICS 8+16:POKE 710,0:POKE 709
   ,14:COLOR 1:START=PEEK(88)+256*PEEK(89
   )+40*ROWT+LBYTE:LC=START
AE 1110 RETURN


LISTING 4: BASIC

DL 60 ? "INSERT FORMATTED DISK & PRE55
    ANY KEY":POKE 764,255
YH 65 IF PEEK(764)=255 THEN 65
TN 70 ? :? "WRITING FILE :D:TEMP.LST"";:0
   PEN #1,8,0,"D:TEMP.L5T":RESTORE :POKE
   764,255
HN 80 FOR N=1 TO 92:READ D:PUT #1,D:NEXT
   N
IH 90 CLOSE #1:? :? :? "DONE":END
QP 100 DATA 49,48,48,48,32,68,73,77,32,69
   ,79,82,36,40,52,52,41,58,69,79,82,36,6
   1,34,104,104
YZ 110 DATA 133,204,104,133,203,104,133,2
   06,104,133,205,160,0,24,165,205,208,7,
   165,206,208,1,96,198,206,198
GL 120 DATA 205,177,203,73,32,145,203,200
   ,208,2,230,204,144,230,176,228,34,58,6
   9,79,82,36,40,51,51,44
ET 130 DATA 51,51,41,61,67,72,82,36,40,50
   ,53,53,41,155