$ create nl: Okay... About twenty people have e-mailed me already to say that my first attempted posting of the modular GIF-reader did NOT make it onto either comp.os.vms (INFO-VAX, to some) or vmsnet.sources. Who the h--- knows what evil lurks in the heart of Portal's news-posting module? ANYWAY... here I go again, trying once more to post this thing. There are six parts, VMS_SHAREd, and I am NOT posting it to vmsnet.sources this time around, so if you miss it this time, post to the Net and get it from someone who's picking it up from me at THIS time... BTW, it may have been something of a misnomer to call this a "_VMS_" GIF reader, per se; it ought to work on any machine on which C programs can be compiled. I've used it absolutely without change on VMS and on a Sun SPARCstation, and plan to try it on the IBM-PC sometime... Without further ado... $! ------------------ CUT HERE ----------------------- $ v='f$verify(f$trnlnm("SHARE_VERIFY"))' $! $! This archive created by VMS_SHARE Version 7.1-004 3-AUG-1989 $! On 1-SEP-1991 23:43:36.84 By user CHIESA $! $! This VMS_SHARE Written by: $! Andy Harper, Kings College London UK $! $! Acknowledgements to: $! James Gray - Original VMS_SHARE $! Michael Bednarek - Original Concept and implementation $! $!+ THIS PACKAGE DISTRIBUTED IN 6 PARTS, TO KEEP EACH PART $! BELOW 30 BLOCKS $! $! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER $! AND EXECUTE AS A COMMAND PROCEDURE ( @name ) $! $! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING: $! 1. AAAREADME.TXT;2 $! 2. CFC.C;1 $! 3. CFC_DISP.MAR;1 $! 4. CFC_LV3.MAR;1 $! 5. CFC_LV3_WSYM.MAR;1 $! 6. GIF.H;1 $! 7. GIFCOMPR.C;1 $! 8. GIFDECOD.C;1 $! 9. GIFENCOD.C;1 $! 10. MAIN.C;1 $! 11. MYMAIN.C;1 $! $set="set" $set symbol/scope=(nolocal,noglobal) $f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID")) $e="write sys$error ""%UNPACK"", " $w="write sys$output ""%UNPACK"", " $ if f$trnlnm("SHARE_LOG") then $ w = "!" $ if f$getsyi("version") .ges. "V4.4" then $ goto START $ e "-E-OLDVER, Must run at least VMS 4.4" $ v=f$verify(v) $ exit 44 $UNPACK: SUBROUTINE ! P1=filename, P2=checksum $ if f$search(P1) .eqs. "" then $ goto file_absent $ e "-W-EXISTS, File ''P1' exists. Skipped." $ delete/nolog 'f'* $ exit $file_absent: $ if f$parse(P1) .nes. "" then $ goto dirok $ dn=f$parse(P1,,,"DIRECTORY") $ w "-I-CREDIR, Creating directory ''dn'." $ create/dir 'dn' $ if $status then $ goto dirok $ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped." $ delete/nolog 'f'* $ exit $dirok: $ w "-I-PROCESS, Processing file ''P1'." $ define/user sys$output nl: $ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1' PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET( SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name"); buff:=CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(buff)) ;LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION( BEGINNING_OF(buff));g:=0;LOOP EXITIF MARK(NONE)=END_OF(buff);x:= ERASE_CHARACTER(1);IF g = 0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x= "V" THEN APPEND_LINE;MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF; IF x="+" THEN g:=1;ERASE_LINE;ENDIF;ELSE IF x="-" THEN g:=0;ENDIF;ERASE_LINE; ENDIF;ENDLOOP;p:="`";POSITION(BEGINNING_OF(buff));LOOP r:=SEARCH(p,FORWARD); EXITIF r=0;POSITION(r);ERASE(r);COPY_TEXT(ASCII(INT(ERASE_CHARACTER(3)))); ENDLOOP;o:=GET_INFO(COMMAND_LINE,"output_file");WRITE_FILE(buff,o); ENDPROCEDURE;Unpacker;EXIT; $ delete/nolog 'f'* $ CHECKSUM 'P1' $ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT $ e "-E-CHKSMFAIL, Checksum of ''P1' failed." $ ENDSUBROUTINE $START: $ create/nolog 'f' XGIF Encoder/Decoder Package docfile`032 X X- Chris Chiesa, Chris_F_Chiesa@cup.portal.com X X This is a brief doc file I've whipped up for the sake of sparing other Xfolks the mystification I underwent while figuring out "what was what" Xwhen I originally obtained this package. Otherwise, YOU would have an even` V032 XWORSE time than I did, because I've added/changed a few things (doesn't EVER VY- Xbody? :-) ). X X Before discussing the use of this package, I'd like to give what credit XI can to the original authors. That's more difficult than I would like, Xbecause I DON'T REALLY KNOW who "originally" wrote it! I obtained fewer Xfiles than you are receiving here -- no docs, no author credits. I don't Xeven clearly remember how it fell into MY hands, although I VAGUELY recall Xgetting it off this Net a couple of years ago. (I've been thinking TWO Xyears, but the more I think back, I believe it may be closer to THREE.)`032 XComments in the source code range from "sparse" to "nonexistent," but Xthat's the ONLY source of information, and two people's names (and ONE of Xtheir e-mail addresses!) do appear: in gifcompr.c appears the comment, "... Xmodifications by David Rowley, mgardi@watdcsu.waterloo.edu," and in Xgifdecod.c the remarks ".. based on Pascal (code) by Jim Griebal," and the Xbeloved words:`032 X X`009"... IN THE PUBLIC DOMAIN!" X X So, as far as I can tell, it's okay for me to send this to you, and for`0 V32 Xyou to use it. I've done my best to check this out on THIS end, but "no Xdice." If the original author(s) ever read(s) this, I hereby publically and Xheartily THANK YOU for a very useful and cleverly modularized package.`032 X X Having said that, I now feel free to explain what you now have in your Xhot little hands.`032 X XFirst, here's a list of what came with the ORIGINAL package, as it first Xcame to ME: X X`009gif.h`009`009- defines two error status values for compile-time use X`009gifcompr.c`009- compression routine used by gifencod.c X`009gifdecod.c`009- GIF decoder routine. Reads GIF file, does all the X`009`009`009 dirty work of decoding, and feeds clean pixel data X`009`009`009 to routines YOU supply X`009gifencod.c`009- GIF _output_ (i.e. creation) routine? I've never`032 X`009`009`009 used it. X`009main.c`009`009- Main program which calls gifdecod, giving it the X`009`009`009 addresses of three routines YOU supply X X Since then, I've added a couple more pieces to this package, although`032 Xnothing you couldn't get along without. I'll come to that shortly, but in Xorder for the explanation to make sense, you should know how the GIF`032 Xdecoder is meant to operate. (I cannot and will not discuss the GIF`032 XENcoder, since I have never worked with it nor even LOOKED AT it.) X X The intent of this package as originally received here appears to have`03 V2 Xbeen that main.c is a "skeleton" containing a main() function which calls Xthe GIF decoder routine GIFDisplay() (gifdecod.c), passing it the addresses Xof three routines whose DECLARATIONS ONLY appear in main.c: TestInit, TestPl Vot, Xand TestTerm. (Internally, GIFDisplay calls these GIFInit, GIFPlot, and`032 XGIFTerm, so those are the names I am most familiar with and will use here.) XExamination of GIFDisplay() shows that it calls these routines to perform`03 V2 Xinitialization of pixel-plotting, to plot each individual pixel extracted Xfrom the GIF data, and to terminate the plotting process. YOU supply these Xroutines, performing whatever SPECIFIC operations are appropriate for the`03 V2 Xparticular type of output you care to create. (I create, fill, and close Xa data file, or clear, draw on, and disconnect from a display screen; you Xmight send a VT240 "sixel introduction" escape sequence, buffer up pixels Xuntil you had enough for a Sixel output band, then send the VT240 end-of- Xsixel-mode sequence...) `032 X X In the original package, when I first studied main.c, it appeared that`032 Xthe user was supposed to flesh out the skeleton by writing his implementatio Vn`032 Xof TestInit(), TestPlot(), and TestTerm(), in C, right there in main.c. Sin Vce`032 Xat that time I didn't know C, but did know VAX Macro assembly, I had to`032 Xfigure out how to interface the two. Thus came my first "addition" to the`0 V32 Xpackage: mymain.c , in which the routines' names have been changed to`032 XCFC_GIFInit, CFC_GIFPlot, and CFC_GIFTerm. I believe the name changes`032 Xarose from a need to clearly identify them when running this whole shebang`0 V32 Xunder the Debugger, although I also vaguely remember some conflicts of`032 Xcase-sensitivity... X X One particularly delicate issue was that GIFInit and GIFTerm take no Xarguments! One of my file-output requirements is/was that I needed to know Xthe size of the file in advance in order to pre-allocate contiguous disk Xspace, for which I needed at least the image's HEIGHT and WIDTH values. XAlso, GIFPlot receives arguments (XC,YC,colour), where "colour" is just Xan INDEX into a set of Red, Green, Blue arrays declared in gifdecod.c;`032 XGIFPlot needs to be able to reference those arrays. Since I didn't know`032 XC, I didn't know (as now I do) that such referencing was easy in C, but XI DID know that I had NO CLUE how to get at those entities from a MACRO Xprogram! X X Through judicious use of CC/DEBUG/LIST and LINK/DEBUG/MAP, I found that Xgifdecod.c's "Width" and "Height" ints, and its "Red`091`093," "Green`091`09 V3," and`032 X"Blue`091`093" arrays, when compiled and linked, led to a separate "Psect"`0 V32 X(program section) for each variable. The .MAP file showed me the`032 Xparticular attributes of each Psect, along with its name, so I tried`032 Xcreating Psects in my MACRO program having the same names and attributes Xas those created by C compilation/linkage, but also having labels visible`03 V2 XWITHIN my macro program. That worked, and to this very day you'll see Xa number of weird-looking .PSECT directives early on in the .MAR files I'm Xsending you: X X`009CFC_LV3.MAR`009`009- creates LVT 3-channel (24-bit-per-pixel) X`009`009`009`009 output image file X`009CFC_LV3_WSYM.MAR`009- same as CFC_LV3.MAR, but also puts HEIGHT X`009`009`009`009 and WIDTH values into DCL symbols GIF_HEIGHT X`009`009`009`009 and GIF_WIDTH X`009CFC_DISP.MAR`009`009- plots pixels directly onto a color screen`032 X`009`009`009`009 for immediate display X X (The LVT 3-channel (.LV3) files created by the first two modules are`032 Xlikely to be rather too large for the typical disk-quota-bound, nonprivilege Vd`032 XUniversity system user; for example, a 320x200 GIF becomes a 400-block data Xfile, and THAT's a SMALL one...) X X To use any of these routines on VAX/VMS, here's the plan: X X`009- Compile (CC) MYMAIN.C and GIFDECOD.C X`009- Assemble (MACRO) any of the .MAR files above, let'sa CFC_LV3.MAR X`009- Link them all together:`032 X`009`009LINK MYMAIN,GIFDECOD,CFC_LV3 X`009- Define a foreign command ("GIF" works well) to invoke the`032 X`009 resulting executable: X X`009`009GIF :== $MYDEVICE:`091MYDIR`093MYMAIN.EXE X X`009- Invoke it with the name of a GIF file: X X`009`009GIF PORSCHE.GIF X X`009 If you have enough disk space, you'll end up with a .LV3 data X`009 file. I suggest, instead, that you write your OWN front end X`009 to do something that's useful to YOU. X X I also eventually got around to working in C now and then, and wrote`032 Xanother LV3-file output routine IN C, which demonstrates the use of these Xroutines as they were meant to be used. It is called CFC.C, and if you`032 Xwant to try it, here's THAT plan: X X`009- Compile (CC) CFC.C and GIFDECOD.C X`009- Link them together (CFC.C is really MAIN.C fleshed out by me) X`009- Invoke as above. X X That's about all I can say on this subject; I hope it's enough. Good`032 Xluck to all who read this. I've had a lot of fun with this decoder in the`0 V32 Xpast couple of years, so I hope you do too. Contact information follows; Xuse it if you have questions/comments/claims of authorhood... X X Chris Chiesa X Chris_F_Chiesa@cup.portal.com X (716) 482-9573 `032 $ CALL UNPACK AAAREADME.TXT;2 1297296712 $ create/nolog 'f' X/* X * cfc.c - Christopher F. Chiesa (Chris_F_Chiesa@cup.portal.com) X * X * This is a sample "front end" for the modular GIF decoder. This code X * compiles under SunOS 4.03 and helps turn a GIF into a .LV3 (LVT 3- X * channel) 24-bit-per-pixel image file. X * X * KNOWN BUGS: X * X * - output LV3 image is one line shorter than input GIF image X * - does not handle "interleaved" GIFs properly (I don't know enough X * C/*nix to move around within a file as needed) X * X */ X X#include X Xextern int Height,Width; /* As declared in gifdecod.c */ Xextern int Red`091`093,Green`091`093,Blue`091`093; X Xstatic FILE *lv3file;`009`009 /* Internal global stuff */ Xstatic int bytes_per_line, X`009 bytes_per_record, X`009 bytes_in_line,fill_bytes; Xstatic unsigned int old_Y; Xstatic char *buffer; X X/* X * CFC_GIFInit() (formerly just plain GIFInit(), renamed for case compati- X * bility while doing development under VAX/VMS) - initialize output`032 X * device/file/environment. In this case we initialize parameters which X * will control the structure of the output LV3 file. Note that GIFInit() X * (sic) takes NO ARGUMENTS; image width, height, etc. is grabbed directly X * from global storage declared in gifdecod.c . X */ X Xint CFC_GIFInit() X`123 X printf("Image is %d pixels by %d lines!\n",Width,Height); X lv3file = fopen("cfc.lv3","w"); X bytes_per_line = (Width*3); X bytes_per_record = 512 * ((bytes_per_line + 511) >> 9); X fill_bytes = 512 - (bytes_per_line & 511);`032 X buffer = (char *) malloc((unsigned) bytes_per_record); X if (!buffer) `123 X printf("Unable to allocate buffer memory!\n"); X exit(0); X `125; X memset(buffer,'\0',bytes_per_record); X bytes_in_line = 0; X old_Y = 0; X`125; X X/* X * CFC_GIFTerm() (formerly GIFTerm()) - release/deallocate/close output`03 V2 X * device/file/environment. In this case, close the output file and re- X * linquish memory we were using as a buffer. X */ X Xint CFC_GIFTerm() X`123 X fclose(lv3file); X free(buffer); X`125; X X/*`032 X * CFC_GIFPlot(XC, YC, colour) (formerly GIFPlot() ...) - perform output`0 V32 X * a single pixel extracted from the GIF image. The pixel is intended to`0 V32 X * appear at location (XC,YC) in the image plane, and have the color indexe Vd X * by "colour" in the Red`091`093. Green`091`093, and Blue`091`093 look-up V tables declared X * in gifdecod.c . X * X * In this instance, since I'm writing a sequential output file, I am in- X * terested only in making sure XC increases monotonically, and in padding X * the output record to the nearest 512-byte boundary when YC _changes_. X * X */ Xint CFC_GIFPlot(XC, YC, colour) X unsigned int XC,YC; X int colour; X`123 X int k; X X if (XC == 0) printf("DEBUG: YC = %d, old_Y = %d\n",YC,old_Y); X if (YC != old_Y) `123 X fwrite(buffer,bytes_per_record,1,lv3file); X memset(buffer,'\0',bytes_per_record); X old_Y = YC; X `125; X if (YC >= old_Y) `123 X if ((YC <= Height) && (XC <= Width)) `123 X k = XC*3; X buffer`091k++`093 = Red`091colour`093; X buffer`091k++`093 = Green`091colour`093; X buffer`091k++`093 = Blue`091colour`093; X `125; X `125; X`125; X X/* X * It's been a while since I wrote this, but from the code below it looks X * like cfc.c is meant to be the MAIN PROGRAM. Compile this and`032 +-+-+-+-+-+-+-+- END OF PART 1 +-+-+-+-+-+-+-+- -+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+ X * gifdecod.c, link 'em together (this module first) and you should be X * able to RUN the beast. (I don't guarantee you'll have disk space for X * the output file, though -- they're BIG.) X */ Xmain( argc, argv ) Xint argc; Xchar *argv`091`093; X`123 X`009GIFDisplay( argv`0911`093, CFC_GIFInit, CFC_GIFPlot, CFC_GIFTerm ); X`125 $ CALL UNPACK CFC.C;1 1378296336 $ create/nolog 'f' X;+ X; CFC_DISP - GIF-output routine(s) that send output to display screen, X; rather than to intermediate LV3 file! X; X; Includes code to define GIF_HEIGHT and GIF_WIDTH local DCL symbols. X; X;- X`009.psect`009data`009wrt,noexe,long X; X`009`009cr = 13 X`009`009lf = 10 Xiosb: X; Xfile_access:`009$fab`009fac=,- X`009`009`009fop=,- X`009`009`009mrs=512,- X`009`009`009org=seq,- X`009`009`009rfm=fix X; X`009`009.macro`009colormap X`009`009x = 0 X`009`009.repeat`009256`009`009; Linear LUT for image`032 X`009`009.LONG`009X`009; TRY A LONG HERE X;`009 `009.byte`0090 X;`009`009.byte x X`009`009x = x + 1 X`009`009.endr X`009`009.repeat 16`009`009; Clear overlay planes X`009`009.LONG`0090`009; TRY A LONG HERE TOO X;`009`009.word`0090 X`009`009.endr X`009`009.endm X; X`009`009.psect`009data`009wrt,noexe,long Xscrn_buf:`009.blkb`0091024 X; Xred_lut:`009colormap Xgreen_lut:`009colormap Xblue_lut:`009colormap X; XVB_per_line:`009.blkl X; Xline_buffer_size: X`009`009.blkl Xline_buffer_ptr: X`009`009.blkl X; Xlast_pixel:`009.blkl`0092`009; Spare space for Longword overrun! Xlast_color:`009.blkw Xlast_y:`009`009.blkw X; Xsymbol_value:`009.long`0097 X`009`009.address value_buffer Xvalue_buffer:`009.blkb`0097 X; Xwidth_symbol:`009.ascid`009\GIF_WIDTH\ Xheight_symbol:`009.ascid`009\GIF_HEIGHT\ Xsymbol_format:`009.ascid`009\!UW\ X; Xoutfile:`009.asciz`009\CFC.LV3\ Xsize_msg:`009.asciz`009\The image is %d pixels by %d lines.\ X; X;+ X; Judging from the .MAP file, C treats every declared variable as a`032 X; separate PSECT unto itself! I will try to get around this problem. X;- X`009.psect`009red`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_red:`009.blkb X`009.psect`009green`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_green:`009.blkb X`009.psect`009blue`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_blue:`009.blkb X`009.psect`009height`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_height: X; X; This USED to be a .BLKB X; X`009.blkw X`009.psect`009width`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X; X; This also used to be a .BLKB X; X_width:`009.blkw X; X`009.psect`009code`009nowrt,exe X`009.entry`009CFC_GIFInit,`094m X;+ X; Initialize the GIF "plotting" environment - in this case, create and open X; an LV3 output file, and initialize the values for writing therein. X;- X`009pushl`009_height`009`009`009; Height value, word? X`009pushl`009_width`009`009`009; Width value, word? X`009pushab`009size_msg`009`009; Display width and height info X`009calls`009#1,g`094printf X;+ X; NEW: DEFINE DCL SYMBOLS FOR HEIGHT AND WIDTH VALUES X;- X`009movl`009#7,symbol_value X`009$FAO_S`009ctrstr=symbol_format,- X`009`009outbuf=symbol_value,- X`009`009outlen=symbol_value,- X`009`009p1=_height X`009blbs`009r0,10$ X`009jmp`009anyway X10$: X`009pushal`009#1 X`009pushaq`009symbol_value X`009pushaq`009height_symbol X`009calls`009#3,g`094LIB$SET_SYMBOL X`009blbs`009r0,20$ X`009jmp`009anyway X20$: X`009movl`009#7,symbol_value X`009$FAO_S`009ctrstr=symbol_format,- X`009`009outbuf=symbol_value,- X`009`009outlen=symbol_value,- X`009`009p1=_width X`009blbs`009r0,30$ X`009jmp`009anyway X30$: X`009pushal`009#1 X`009pushaq`009symbol_value X`009pushaq`009width_symbol X`009calls`009#3,g`094LIB$SET_SYMBOL X;+ X; Failure of the preceding steps doesn't matter at all to the real pur- X; pose of this program -- decoding a GIF image! So come here regardless X; of success/failure mode. X;- Xanyway: X;+ X; Data size of "int" in VAX C is not known to me at the time of this`032 X; writing. I'll assume an "int" is a WORD, for the time being. X;- X;+ X; "Initialize host-based CTP data structures for one or more boards" -- X;- X`009`009pushl`009#1`009`009; Number of boards, int by ref X`009`009pushal`009scrn_buf`009; Buffer address... X`009`009calls`009#2,sysint`009; pg. 191; (no return value) X;+ X; "Initialize internal data structures for a board's worth of information` V032 X; and possibly initialize the TMS34020 on the board."`032 X;- X`009`009pushl`009#-1`009`009; Initialization flags. Use this X`009`009`009`009`009; only if VCTINT was previously run X`009`009pushl`009#1 ; 0`009`009; "Synchronization group" - unused X`009`009pushl`009#`094X0; 20000c00`009; (Is supposed to be the physical`032 X`009`009`009`009`009; address of the 1KB data buffer in X`009`009`009`009`009; the I/O page. How the hell am I X`009`009`009`009`009; supposed to get THAT?) X`009`009pushl`009#`094X0; 200019e0`009; (Is supposed to be physical CSR X`009`009`009`009`009; address! How the hell do I get X`009`009`009`009`009; THAT?) X`009`009pushl`009#0`009`009; Board number X`009`009calls`009#5,devint`009; pg. 61; (no return value) X; X`009`009movl`009#SS$_NORMAL,r0`009; (For the sake of VMS) X;+ X; Enable the selected board... X;- X`009`009pushl`009#1`009`009; "Enable" X`009`009pushl`009#0`009`009; "Board #0" X`009`009calls`009#2,gcntl X;+ X; Initialize video...? X;- X`009`009pushl`009#1 X`009`009calls`009#1,init_video X;+ X; Initialize graphics ... ? X;- X`009`009calls`009#0,init_grafix X;+ X; Initialize text ... X;- X`009`009calls`009#0,init_text X;+ X; Set text color (try for a medium gold): X;- X`009`009pushl`009#`094X0060EEFF X`009`009calls`009#1,set_color1 X;+ X; CLEAR SCREEN X;- X`009`009pushl`009#0 X`009`009calls`009#1,clear_screen X;+ X; Load values into color maps... :-? X;- X`009`009pushab`009blue_lut`009; Blue array address (?) X`009`009pushab`009green_lut`009; Green array address (?) X`009`009pushab`009red_lut`009`009; Red array address (?) X`009`009pushl`009#<256+16>`009; Length (number of LUT entries) X`009`009pushl`009#0`009`009; First LUT entry to write X`009`009pushl`009#0`009`009; Board #`032 X`009`009CALLS`009#6,CMMWBLK`009; WE'RE SUPPOSED TO _WRITE_ THIS! X;`009`009calls`009#6,cmmrblk`009; Try READING the suckers! X X;+ X; Get Virtual Memory for LV3 line buffer X;- X`009clrl`009r5`009`009`009; Zero all bits X`009mulw3`009_width,#4,line_buffer_size `009; Peritek-output line buffer siz Ve X; X`009pushal`009line_buffer_ptr X`009pushal`009line_buffer_size X`009calls`009#2,g`094LIB$GET_VM X`009blbs`009r0,10$ X`009jmp`009init_err X10$: X;+ X; Initialize non-QIO values X;- X`009clrw`009last_y X`009movw`009#-1,last_color X;+ X; Darned if I know what to return for C to think this was SUCCESSFUL... X;- Xinit_err: X`009ret X;--------------------------------------------------------------------------- V`009 X`009.entry`009CFC_GIFPlot,`094m X; X`009pushr`009#`094m X;+ X; Insert a supplied "color" value into the LV3 file at the supplied X, Y`032 X; coordinates. X; X; Input: X;`009 (AP) = # of arguments, by value, assumed 3 X;`009 4(AP) = X coordinate, "int" by value (assumed "WORD" by value) X;`009 8(AP) = Y coordinate, "int" by value (assumed "WORD" by value) X;`00912(AP) = COLOUR, i.e. index into color table for current pixel X;- X; X`009cmpw`00912(ap),last_color`009; Is this pixel same as last one? X`009beql`009100$`009`009`009; Yes: no need to recompute! X; X`009movzwl`00912(ap),r5`009`009; R5 => pixel color (index into tables) X; X`009movl`009_red`091r5`093,last_pixel`009; Insert Red value X`009movl`009_green`091r5`093,last_pixel+1`009; Insert Green value X`009movl`009_blue`091r5`093,last_pixel+2`009; Insert Blue value X; X`009movw`009r5,last_color`009`009; Save new "old" values! X100$: X;+ X; Determine whether or not we must move to a different LV3 line: X;- X`009cmpw`0098(ap),last_y`009`009; Is Y-coordinate same as last time? X`009beql`009200$`009`009`009; Yes: no need to flush buffer X; X;+ X; Display line on Peritek screen! X;- X`009`009pushal`009@line_buffer_ptr`009; Output buffer address X`009`009ashl`009#-2,line_buffer_size,- X`009`009`009-(sp)`009`009`009; Number of pixels being sent X`009`009movzwl`009last_y,-(sp)`009`009; Vertical display coord (Y) X`009`009pushl`009#0`009`009`009; Horizontal display coord (X) X`009`009pushl`009#0 X`009`009calls`009#5,wrtmem`009`009; Display! (No return value) X`009`009movl`009#SS$_NORMAL,r0`009`009; Fake "success" return! X200$: X`009movw`0098(ap),last_y`009`009; No: set new "last Y-coordinate" X;+ X; Determine buffer offset that corresponds to X coordinate... X;- X`009mull3`009#4,4(ap),r3`009`009; R3 => offset into line X`009moval`009@line_buffer_ptr,r4`009; R4 => line buffer base address X; X`009movab`009(r4)`091r3`093,r0 X`009movb`009last_pixel,(r0) X`009movb`009,1(r0) X`009movb`009,2(r0) X`009movb`009#0,3(r0) X;+ X; That should take care of plotting! X;- Xplot_err: X`009popr`009#`094m X`009ret X;--------------------------------------------------------------------------- X`009.entry`009CFC_GIFTerm,`094m X;+ X; Terminate GIF "plotting" -- that is, flush the LV3 line buffer, close the X; I/O channel, and relinquish VM.... X;- X`009pushal`009line_buffer_ptr X`009pushal`009line_buffer_size X`009calls`009#2,g`094LIB$FREE_VM`009; Relinquish buffer VM X`009blbs`009r0,30$ X`009jmp`009term_err X30$: Xterm_err: X`009ret X;`009 X`009.end $ CALL UNPACK CFC_DISP.MAR;1 1193349660 $ create/nolog 'f' X;+ X; CFC - Custom (LV3) GIF-output routine(s) for use by GIFENCOD.C, generic X; GIF-file reader obtained from Usenet! This module writes a .LV3 X; (LVT 3-channel) 24-bit-per-pixel image file. X;- X`009.psect`009data`009wrt,noexe,long X; X`009`009cr = 13 X`009`009lf = 10 Xiosb: X; Xfile_access:`009$fab`009fac=,- X`009`009`009fop=,- X`009`009`009mrs=512,- X`009`009`009org=seq,- X`009`009`009rfm=fix X; XIO_access:`009$QIO`009func=IO$_WRITEVBLK,- X`009`009`009iosb=iosb X; XVB_per_line:`009.blkl X; Xlast_pixel:`009.blkl`0092`009; Spare space for Longword overrun! Xlast_color:`009.blkw Xlast_y:`009`009.blkw X; Xoutfile:`009.asciz`009\CFC.LV3\ Xsize_msg:`009.asciz`009\The image is %d pixels by %d lines.\ X; X;+ X; Judging from the .MAP file, C treats every declared variable as a`032 X; separate PSECT unto itself! I will try to get around this problem. X;- X`009.psect`009red`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_red:`009.blkb X`009.psect`009green`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_green:`009.blkb X`009.psect`009blue`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_blue:`009.blkb X`009.psect`009height`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_height: X`009.blkb X`009.psect`009width`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_width:`009.blkb X; X`009.psect`009code`009nowrt,exe X`009.entry`009CFC_GIFInit,`094m X;+ X; Initialize the GIF "plotting" environment - in this case, create and open X; an LV3 output file, and initialize the values for writing therein. X;- X`009pushl`009_height X`009pushl`009_width X`009pushab`009size_msg X`009calls`009#1,g`094printf X; X`009moval`009file_access,r2`009`009; R2 => FAB address X`009moval`009outfile,r3`009`009; R3 => .ASCIZ filename address X`009moval`009IO_access,r4`009`009; R4 => $QIO data structure address X; X`009moval`009(r3),fab$l_fna(r2)`009; String address X`009locc`009#0,#`094XFF,(r3)`009`009; Find end-of-string (NULL byte) X`009subb3`009r0,#`094XFF,fab$b_fns(r2)`009; String length X;+ X; Data size of "int" in VAX C is not known to me at the time of this`032 X; writing. I'll assume an "int" is a WORD, for the time being. X;- X`009clrl`009r5`009`009`009; Zero all bits X`009mulw3`009_width,#3,r5`009`009; LV3-line buffer size X`009addl3`009#1,r5,QIO$_P2(r4) X`009bicl2`009#1,QIO$_P2(r4)`009`009; Insert into I/O structure X`009addl2`009#511,r5 X`009ashl`009#-9,r5,vb_per_line`009; Virtual Blocks per LV3 Line X`009mulw3`009vb_per_line,_height,-`009; Disk blocks necessary for file X`009`009fab$l_alq(r2) X;+ X; Get Virtual Memory for LV3 line buffer X;- X`009pushal`009QIO$_P1(r4) X`009pushal`009QIO$_P2(r4) X`009calls`009#2,g`094LIB$GET_VM X`009blbs`009r0,10$ X`009jmp`009init_err X10$: X;+ X; Create output file and obtain channel number X;- X`009$CREATE`009fab=(r2) X`009blbs`009r0,20$ X`009jmp`009init_err X20$: X`009movzwl`009fab$l_stv(r2),QIO$_CHAN(r4) X;+ X; Insert remaining initialization values in QIO structure: X;- X`009movl`009#1,QIO$_P3(r4)`009`009`009; First write is at VBN 1. X;+ X; Initialize non-QIO values X;- X`009clrw`009last_y X`009movw`009#-1,last_color X;+ X; Darned if I know what to return for C to think this was SUCCESSFUL... X;- Xinit_err: X`009ret X;--------------------------------------------------------------------------- V`009 X`009.entry`009CFC_GIFPlot,`094m X; X`009pushr`009#`094m X;+ X; Insert a supplied "color" value into the LV3 file at the supplied X, Y`032 X; coordinates. X; X; Input: X;`009 (AP) = # of arguments, by value, assumed 3 X;`009 4(AP) = X coordinate, "int" by value (assumed "WORD" by value) X;`009 8(AP) = Y coordinate, "int" by value (assumed "WORD" by value) X;`00912(AP) = COLOUR, i.e. index into color table for current pixel X;- X; X`009cmpw`00912(ap),last_color`009; Is this pixel same as last one? X`009beql`009100$`009`009`009; Yes: no need to recompute! X; X`009movzwl`00912(ap),r5`009`009; R5 => pixel color (index into tables) X; X`009movl`009_red`091r5`093,last_pixel`009; Insert Red value X`009movl`009_green`091r5`093,last_pixel+1`009; Insert Green value X`009movl`009_blue`091r5`093,last_pixel+2`009; Insert Blue value X; X`009movw`009r5,last_color`009`009; Save new "old" values! X100$: X`009moval`009IO_access,r2`009`009; R2 => QIO structure base address X;+ X; Determine whether or not we must move to a different LV3 line: X;- X`009cmpw`0098(ap),last_y`009`009; Is Y-coordinate same as last time? X`009beql`009200$`009`009`009; Yes: no need to flush buffer X; X;+ X; Compute VBN to write line just completed: X;- X`009movzwl`009last_y,r3`009`009; R3 => Y X`009mull2`009VB_per_line,r3`009`009; R3 => Y*VBI X`009movab`0091(r3),QIO$_P3(r2)`009; New VBN = (Y*VBI)+1 X; +-+-+-+-+-+-+-+- END OF PART 2 +-+-+-+-+-+-+-+- -+-+-+-+-+-+-+-+ START OF PART 3 -+-+-+-+-+-+-+-+ X`009$QIOW_G`009IO_access`009`009; Write current buffer... X`009blbc`009r0,105$ X`009movzwl`009iosb,r0 X`009blbs`009r0,110$ X105$: X`009jmp`009plot_err X110$: X200$: X`009movw`0098(ap),last_y`009`009; Associate it with supplied Y value X;+ X; Determine buffer offset that corresponds to X coordinate... X;- X`009mull3`009#3,4(ap),r3`009`009; R3 => offset into line X`009moval`009@QIO$_P1(r2),r4`009`009; R4 => line buffer base address X; X`009movab`009(r4)`091r3`093,r0 X`009movb`009last_pixel,(r0) X`009movb`009,1(r0) X`009movb`009,2(r0) X;+ X; That should take care of plotting! X;- Xplot_err: X`009popr`009#`094m X`009ret X;--------------------------------------------------------------------------- X`009.entry`009CFC_GIFTerm,`094m X;+ X; Terminate GIF "plotting" -- that is, flush the LV3 line buffer, close the X; I/O channel, and relinquish VM.... X;- X`009moval`009IO_access,r2`009`009; R2 => QIO data structure address X`009$QIOW_G`009IO_access`009`009; Flush buffer out to file X`009blbc`009r0,15$ X`009movzwl`009iosb,r0 X`009blbs`009r0,20$ X15$: X`009jmp`009term_err X20$: X`009pushal`009QIO$_P1(r2) X`009pushal`009QIO$_P2(r2) X`009calls`009#2,g`094LIB$FREE_VM`009; Relinquish buffer VM X`009blbs`009r0,30$ X`009jmp`009term_err X30$: X`009$DASSGN_S - X`009`009chan=QIO$_CHAN(r2)`009; Close I/O channel Xterm_err: X`009ret X;`009 X`009.end $ CALL UNPACK CFC_LV3.MAR;1 1298338398 $ create/nolog 'f' X;+ X; CFC - Custom (LV3) GIF-output routine(s) for use by GIFENCOD.C, generic X; GIF-file reader obtained from Usenet! This module writes a .LV3 X; (LVT 3-channel) 24-bit-per-pixel image file, and places GIF image X; size information in the DCL symbols "GIF_HEIGHT" and "GIF_WIDTH." X; X;- X`009.psect`009data`009wrt,noexe,long X; X`009`009cr = 13 X`009`009lf = 10 Xiosb: X; Xfile_access:`009$fab`009fac=,- X`009`009`009fop=,- X`009`009`009mrs=512,- X`009`009`009org=seq,- X`009`009`009rfm=fix X; XIO_access:`009$QIO`009func=IO$_WRITEVBLK,- X`009`009`009iosb=iosb X; XVB_per_line:`009.blkl X; Xlast_pixel:`009.blkl`0092`009; Spare space for Longword overrun! Xlast_color:`009.blkw Xlast_y:`009`009.blkw X; Xsymbol_value:`009.long`0097 X`009`009.address value_buffer Xvalue_buffer:`009.blkb`0097 X; Xwidth_symbol:`009.ascid`009\GIF_WIDTH\ Xheight_symbol:`009.ascid`009\GIF_HEIGHT\ Xsymbol_format:`009.ascid`009\!UW\ X; Xoutfile:`009.asciz`009\CFC.LV3\ Xsize_msg:`009.asciz`009\The image is %d pixels by %d lines.\ X; X;+ X; Judging from the .MAP file, C treats every declared variable as a`032 X; separate PSECT unto itself! I will try to get around this problem. X;- X`009.psect`009red`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_red:`009.blkb X`009.psect`009green`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_green:`009.blkb X`009.psect`009blue`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_blue:`009.blkb X`009.psect`009height`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X_height: X; X; This USED to be a .BLKB X; X`009.blkw X`009.psect`009width`009long,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec X; X; This also used to be a .BLKB X; X_width:`009.blkw X; X`009.psect`009code`009nowrt,exe X`009.entry`009CFC_GIFInit,`094m X;+ X; Initialize the GIF "plotting" environment - in this case, create and open X; an LV3 output file, and initialize the values for writing therein. X;- X`009pushl`009_height`009`009`009; Height value, word? X`009pushl`009_width`009`009`009; Width value, word? X`009pushab`009size_msg`009`009; Display width and height info X`009calls`009#1,g`094printf X;+ X; NEW: DEFINE DCL SYMBOLS FOR HEIGHT AND WIDTH VALUES X;- X`009movl`009#7,symbol_value X`009$FAO_S`009ctrstr=symbol_format,- X`009`009outbuf=symbol_value,- X`009`009outlen=symbol_value,- X`009`009p1=_height X`009blbs`009r0,10$ X`009jmp`009anyway X10$: X`009pushal`009#1 X`009pushaq`009symbol_value X`009pushaq`009height_symbol X`009calls`009#3,g`094LIB$SET_SYMBOL X`009blbs`009r0,20$ X`009jmp`009anyway X20$: X`009movl`009#7,symbol_value X`009$FAO_S`009ctrstr=symbol_format,- X`009`009outbuf=symbol_value,- X`009`009outlen=symbol_value,- X`009`009p1=_width X`009blbs`009r0,30$ X`009jmp`009anyway X30$: X`009pushal`009#1 X`009pushaq`009symbol_value X`009pushaq`009width_symbol X`009calls`009#3,g`094LIB$SET_SYMBOL X;+ X; Failure of the preceding steps doesn't matter at all to the real pur- X; pose of this program -- decoding a GIF image! So come here regardless X; of success/failure mode. X;- Xanyway: X`009moval`009file_access,r2`009`009; R2 => FAB address X`009moval`009outfile,r3`009`009; R3 => .ASCIZ filename address X`009moval`009IO_access,r4`009`009; R4 => $QIO data structure address X; X`009moval`009(r3),fab$l_fna(r2)`009; String address X`009locc`009#0,#`094XFF,(r3)`009`009; Find end-of-string (NULL byte) X`009subb3`009r0,#`094XFF,fab$b_fns(r2)`009; String length X;+ X; Data size of "int" in VAX C is not known to me at the time of this`032 X; writing. I'll assume an "int" is a WORD, for the time being. X;- X`009clrl`009r5`009`009`009; Zero all bits X`009mulw3`009_width,#3,r5`009`009; LV3-line buffer size X`009addl3`009#1,r5,QIO$_P2(r4) X`009bicl2`009#1,QIO$_P2(r4)`009`009; Insert into I/O structure X`009addl2`009#511,r5 X`009ashl`009#-9,r5,vb_per_line`009; Virtual Blocks per LV3 Line X`009mulw3`009vb_per_line,_height,-`009; Disk blocks necessary for file X`009`009fab$l_alq(r2) X;+ X; Get Virtual Memory for LV3 line buffer X;- X`009pushal`009QIO$_P1(r4) X`009pushal`009QIO$_P2(r4) X`009calls`009#2,g`094LIB$GET_VM X`009blbs`009r0,10$ X`009jmp`009init_err X10$: X;+ X; Create output file and obtain channel number X;- X`009$CREATE`009fab=(r2) X`009blbs`009r0,20$ X`009jmp`009init_err X20$: X`009movzwl`009fab$l_stv(r2),QIO$_CHAN(r4) X;+ X; Insert remaining initialization values in QIO structure: X;- X`009movl`009#1,QIO$_P3(r4)`009`009`009; First write is at VBN 1. X;+ X; Initialize non-QIO values X;- X`009clrw`009last_y X`009movw`009#-1,last_color X;+ X; Darned if I know what to return for C to think this was SUCCESSFUL... X;- Xinit_err: X`009ret X;--------------------------------------------------------------------------- V`009 X`009.entry`009CFC_GIFPlot,`094m X; X`009pushr`009#`094m X;+ X; Insert a supplied "color" value into the LV3 file at the supplied X, Y`032 X; coordinates. X; X; Input: X;`009 (AP) = # of arguments, by value, assumed 3 X;`009 4(AP) = X coordinate, "int" by value (assumed "WORD" by value) X;`009 8(AP) = Y coordinate, "int" by value (assumed "WORD" by value) X;`00912(AP) = COLOUR, i.e. index into color table for current pixel X;- X; X`009cmpw`00912(ap),last_color`009; Is this pixel same as last one? X`009beql`009100$`009`009`009; Yes: no need to recompute! X; X`009movzwl`00912(ap),r5`009`009; R5 => pixel color (index into tables) X; X`009movl`009_red`091r5`093,last_pixel`009; Insert Red value X`009movl`009_green`091r5`093,last_pixel+1`009; Insert Green value X`009movl`009_blue`091r5`093,last_pixel+2`009; Insert Blue value X; X`009movw`009r5,last_color`009`009; Save new "old" values! X100$: X`009moval`009IO_access,r2`009`009; R2 => QIO structure base address X;+ X; Determine whether or not we must move to a different LV3 line: X;- X`009cmpw`0098(ap),last_y`009`009; Is Y-coordinate same as last time? X`009beql`009200$`009`009`009; Yes: no need to flush buffer X; X;+ X; Compute VBN to write line just completed: X;- X`009movzwl`009last_y,r3`009`009; R3 => Y X`009mull2`009VB_per_line,r3`009`009; R3 => Y*VBI X`009movab`0091(r3),QIO$_P3(r2)`009; New VBN = (Y*VBI)+1 X; X`009$QIOW_G`009IO_access`009`009; Write current buffer... X`009blbc`009r0,105$ X`009movzwl`009iosb,r0 X`009blbs`009r0,110$ X105$: X`009jmp`009plot_err X110$: X200$: X`009movw`0098(ap),last_y`009`009; Associate it with supplied Y value X;+ X; Determine buffer offset that corresponds to X coordinate... X;- X`009mull3`009#3,4(ap),r3`009`009; R3 => offset into line X`009moval`009@QIO$_P1(r2),r4`009`009; R4 => line buffer base address X; X`009movab`009(r4)`091r3`093,r0 X`009movb`009last_pixel,(r0) X`009movb`009,1(r0) X`009movb`009,2(r0) X;+ X; That should take care of plotting! X;- Xplot_err: X`009popr`009#`094m X`009ret X;--------------------------------------------------------------------------- X`009.entry`009CFC_GIFTerm,`094m X;+ X; Terminate GIF "plotting" -- that is, flush the LV3 line buffer, close the X; I/O channel, and relinquish VM.... X;- X`009moval`009IO_access,r2`009`009; R2 => QIO data structure address X`009$QIOW_G`009IO_access`009`009; Flush buffer out to file X`009blbc`009r0,15$ X`009movzwl`009iosb,r0 X`009blbs`009r0,20$ X15$: X`009jmp`009term_err X20$: X`009pushal`009QIO$_P1(r2) X`009pushal`009QIO$_P2(r2) X`009calls`009#2,g`094LIB$FREE_VM`009; Relinquish buffer VM X`009blbs`009r0,30$ X`009jmp`009term_err X30$: X`009$DASSGN_S - X`009`009chan=QIO$_CHAN(r2)`009; Close I/O channel Xterm_err: X`009ret X;`009 X`009.end $ CALL UNPACK CFC_LV3_WSYM.MAR;1 1711606992 $ create/nolog 'f' X#define GIF_OPEN_ERROR`0091 X#define GIF_NOT_GIF`0092 X $ CALL UNPACK GIF.H;1 2064400776 $ create/nolog 'f' X/*************************************************************************** X * X * GIFENCOD.C - GIF Image compression routines X * X * Lempel-Ziv compression based on 'compress'. GIF modifications by X * David Rowley (mgardi@watdcsu.waterloo.edu) X * X *************************************************************************** V/ X X/* X * General DEFINEs X */ X#define min(a,b) ((a>b) ? b : a) X X#define BITS`00912 X#define MSDOS`0091 X X#define HSIZE 5003 /* 80% occupancy */ X X/* X * Pointer to function returning an int X */ Xtypedef int (* ifunptr)(); X X/* X * a code_int must be able to hold 2**BITS values of type int, and also -1 X */ Xtypedef int code_int; X X#ifdef SIGNED_COMPARE_SLOW Xtypedef unsigned long int count_int; Xtypedef unsigned short int count_short; X#else Xtypedef long int count_int; X#endif X X#ifdef NO_UCHAR X typedef char char_type; X#else X typedef unsigned char char_type; X#endif /* UCHAR */ X X/* X * X * GIF Image compression - modified 'compress' X * X * Based on: compress.c - File compression ala IEEE Computer, June 1984. X * X * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas V) X * Jim McKie (decvax!mcvax!jim) X * Steve Davies (decvax!vax135!petsd!peora!srd) X * Ken Turkowski (decvax!decwrl!turtlevax!ken) X * James A. Woods (decvax!ihnp4!ames!jaw) X * Joe Orost (decvax!vax135!petsd!joe) X * X */ X#include X#include X#include X X#define ARGVAL() (*++(*argv) `124`124 (--argc && *++argv)) X Xstatic int n_bits; /* number of bits/code */ Xstatic int maxbits = BITS; /* user settable max # bits/code * V/ Xstatic code_int maxcode; /* maximum code, given n_bits */ Xstatic code_int maxmaxcode = (code_int)1 << BITS; /* should NEVER generate t Vhis code */ X#ifdef COMPATIBLE /* But wrong! */ X# define MAXCODE(n_bits) ((code_int) 1 << (n_bits) - 1) X#else X# define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) X#endif /* COMPATIBLE */ X Xstatic count_int htab `091HSIZE`093; Xstatic unsigned short codetab `091HSIZE`093; X#define HashTabOf(i) htab`091i`093 X#define CodeTabOf(i) codetab`091i`093 X Xstatic code_int hsize = HSIZE; /* for dynamic table sizing * V/ Xstatic count_int fsize; X X/* X * To save much memory, we overlay the table used by compress() with those X * used by decompress(). The tab_prefix table is the same size and type X * as the codetab. The tab_suffix table needs 2**BITS characters. We X * get this from the beginning of htab. The output stack uses the rest X * of htab, and contains characters. There is plenty of room for any X * possible stack (stack used to be 8000 characters). X */ X X#define tab_prefixof(i) CodeTabOf(i) X#define tab_suffixof(i) ((char_type *)(htab))`091i`093 X#define de_stack ((char_type *)&tab_suffixof((code_int)1< 0 )`032 X goto probe; Xnomatch: X output ( (code_int) ent ); X out_count++; X ent = c; X#ifdef SIGNED_COMPARE_SLOW X if ( (unsigned) free_ent < (unsigned) maxmaxcode) `123 X#else X if ( free_ent < maxmaxcode ) `123 X#endif X CodeTabOf (i) = free_ent++; /* code -> hashtable */ X HashTabOf (i) = fcode; X `125 else X`009`009cl_block(); X `125 X /* X * Put out the final code. X */ X output( (code_int)ent ); X out_count++; X output( (code_int) EOFCode ); X X return; X`125 X X/***************************************************************** X * TAG( output ) X * X * Output the given code. X * Inputs: X * code: A n_bits-bit integer. If == -1, then EOF. This assumes X * that n_bits =< (long)wordsize - 1. X * Outputs: X * Outputs code to the file. X * Assumptions: X * Chars are 8 bits long. X * Algorithm: X * Maintain a BITS character long buffer (so that 8 codes will X * fit in it exactly). Use the VAX insv instruction to insert each X * code in turn. When the buffer fills up empty it and start over. X */ X Xstatic unsigned long cur_accum = 0; Xstatic int cur_bits = 0; X Xstatic Xunsigned long masks`091`093 = `123 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, X 0x001F, 0x003F, 0x007F, 0x00FF, X 0x01FF, 0x03FF, 0x07FF, 0x0FFF, X 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF `125; X Xstatic Xoutput( code ) Xcode_int code; X`123 X cur_accum &= masks`091 cur_bits `093; X X if( cur_bits > 0 ) X `009cur_accum `124= ((long)code << cur_bits); X else X cur_accum = code; X`009 X cur_bits += n_bits; X X while( cur_bits >= 8 ) `123 X `009char_out( (unsigned int)(cur_accum & 0xff) ); X`009cur_accum >>= 8; X`009cur_bits -= 8; X `125 X X /* X * If the next entry is going to be too big for the code size, X * then increase it, if possible. X */ X if ( free_ent > maxcode `124`124 clear_flg ) `123 X X if( clear_flg ) `123 X`009 `032 X maxcode = MAXCODE (n_bits = g_init_bits); X clear_flg = 0; X`009`009 X `125 else `123 X`009 `032 X n_bits++; X if ( n_bits == maxbits ) X maxcode = maxmaxcode; X else X maxcode = MAXCODE(n_bits); X `125 X `125 X`009 X if( code == EOFCode ) `123 X /* X * At EOF, write the rest of the buffer. X */ X while( cur_bits > 0 ) `123 X `009 char_out( (unsigned int)(cur_accum & 0xff) ); X`009 cur_accum >>= 8; X`009 cur_bits -= 8; X `125 X X`009flush_char(); X`009 X fflush( g_outfile ); X X`009if( ferror( g_outfile ) ) X writeerr(); X `125 X`125 X X/* X * Clear out the hash table X */ Xstatic Xcl_block () /* table clear for block compress */ X`123 X X cl_hash ( (count_int) hsize ); X free_ent = ClearCode + 2; X clear_flg = 1; X X output( (code_int)ClearCode ); X`125 X Xstatic Xcl_hash(hsize) /* reset code table */ Xregister count_int hsize; X`123 X X register count_int *htab_p = htab+hsize; X X register long i; X register long m1 = -1; X X i = hsize - 16; X do `123 /* might use Sys V memset(3) here V */ X *(htab_p-16) = m1; X *(htab_p-15) = m1; X *(htab_p-14) = m1; X *(htab_p-13) = m1; X *(htab_p-12) = m1; X *(htab_p-11) = m1; X *(htab_p-10) = m1; X *(htab_p-9) = m1; X *(htab_p-8) = m1; X *(htab_p-7) = m1; X *(htab_p-6) = m1; X *(htab_p-5) = m1; X *(htab_p-4) = m1; X *(htab_p-3) = m1; X *(htab_p-2) = m1; X *(htab_p-1) = m1; X htab_p -= 16; X `125 while ((i -= 16) >= 0); X X`009for ( i += 16; i > 0; i-- ) X *--htab_p = m1; X`125 X Xstatic Xwriteerr() X`123 X`009printf( "error writing output file\n" ); X`009exit(1); X`125 X X/*************************************************************************** V*** X * X * GIF Specific routines X * X *************************************************************************** V***/ X X/* X * Number of characters so far in this 'packet' X */ Xstatic int a_count; X X/* X * Set up the 'byte output' routine X */ Xstatic Xchar_init() X`123 X`009a_count = 0; X`125 X X/* X * Define the storage for the packet accumulator X */ Xstatic char accum`091 256 `093; X X/* X * Add a character to the end of the current packet, and if it is 254 X * characters, flush the packet to disk. X */ Xstatic Xchar_out( c ) Xint c; X`123 X`009accum`091 a_count++ `093 = c; X`009if( a_count >= 254 )`032 X`009`009flush_char(); X`125 X X/* X * Flush the packet to disk, and reset the accumulator X */ Xstatic Xflush_char() X`123 X`009if( a_count > 0 ) `123 X`009`009fputc( a_count, g_outfile ); X`009`009fwrite( accum, 1, a_count, g_outfile ); X`009`009a_count = 0; X`009`125 X`125`009 X X/* The End */ $ CALL UNPACK GIFCOMPR.C;1 2020241572 $ create/nolog 'f' X/* X * GIF DECODER - Based on a Pascal implementation by Jim Griebal X * In the public domain. 'GIF' and 'Graphics Interchange X * Format' are trademarks of Compuserve, Inc., an H&R Block Company. X */ X X#include X#include "gif.h" X X#define TRUE`0091 X#define FALSE`0090 X Xtypedef unsigned char byte; Xtypedef unsigned int word; X X#define static X Xtypedef int (* funptr)(); X Xfunptr _GIFInit, _GIFPlot, _GIFTerm; X X/* X * Variable declarations X */ Xstatic FILE *giffile; /* The input file */ X Xstatic word X Width, /* Read from GIF header, image width */ X Height, /* ditto, image height */ X RWidth, /* ditto, raster width */ X RHeight, /* ditto, raster height */ X ClearCode, /* GIF clear code */ X EOFCode, /* GIF end-of-information code */ X MaxCode, /* Decompressor limiting value for current code size */ X OldCode, /* Decompressor variable */ X InCode, /* Decompressor variable */ X FirstFree, /* First free code, generated per GIF spec */ X FreeCode, /* Decompressor, next free slot in hash table */ X XC,YC, /* Screen X and Y coords of current pixel */ X Pindex, /* Index into screen save array */ X ReadMask; /* Code AND mask for current code size */ X Xstatic int X Interlace, /* True if interlaced image */ X Colormap; /* True if colormap present */ X Xstatic int X Resolution, /* Resolution, read from GIF header */ X BitsPerPixel, /* Bits per pixel, read from GIF header */ X Background, /* Background color, read from GIF header */ X ColorMapSize, /* Length of color map, from GIF header */ X CodeSize, /* Code size, read from GIF header */ X InitCodeSize, /* Starting code size, used during Clear */ X Pass, /* Used by video output if interlaced pic */ X BitMask; /* AND mask for data size */ X X /* The hash table used by the decompressor */ X static int Prefix`0914096`093; X static int Suffix`0914096`093; X X /* An output array used by the decompressor */ X static int OutCode`0911025`093; X X /* The color map, read from the GIF header */ X static int Red`091256`093, Green`091256`093, Blue`091256`093; X X/* Const */ X X static int MaxCodes`091`093 = `123 X `0094,8,16,0x20,0x40,0x80,0x100,0x200,0x400,0x800 X`009`125; X X static int CodeMask`091`093 = `123 X `0091, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095 X`009`125; X X static int PowersOf2`091`093 = `123 X `0091, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 X`009`125; X X static int Masks`091`093 = `123 X `0097,15,0x1f,0x3f,0x7f,0xff,0x1ff,0x3ff,0x7ff,0xfff X`009`125; X Xstatic byte XGetbyte() X`123 X`009int c; X X`009c = fgetc( giffile ); X X`009if( c == EOF ) `123 X`009`009exit(1); X`009`125 X`009 X`009return (byte) c; X`125 X Xstatic int PacketSize = 0; Xstatic int CurrentCount = 0; X Xstatic byte DataBuf`091256`093; X Xstatic byte XGetdata() X`123 X`009if( CurrentCount == PacketSize ) `123 X`009`009PacketSize = Getbyte(); X`009 if( fread( DataBuf, sizeof( char ), PacketSize, giffile ) != X`009`009`009`009PacketSize ) `123 X`009`009`009`009 X`009`009`009`009exit(1); X`009`009`125 X`009`009CurrentCount = 0; X`009`125 X`009return DataBuf`091 CurrentCount++ `093; X`125 X X/* Reads two bytes, to get a word value */ X Xstatic Xword XGetword() X`123 X`009int a, b; X X`009a = Getbyte(); X`009b = Getbyte(); X X`009return (word)(a + (256 * b)); X`125 X X/* Fetch the next code from the raster data stream. The codes can be any Xlength from 3 to 12 bits, packed into 8-bit bytes, so we have to maintain Xour location in the Raster array as a BIT offset. We compute the byte offset Xinto the raster array by dividing this by 8, pick up three bytes, compute Xthe bit offset into our 24-bit chunk, shift to bring the desired code to Xthe bottom, then mask it off and return it. If the unblocked raster data Xoverflows the original RASTER array, we switch to the second one */ X Xstatic int BitsLeft = 0; Xstatic int ByteLeft = 0; X Xstatic int Msk`091`093 = `123 X 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383 X `125; X Xstatic word XReadCode() X`123 X register long code; X register int BitsNeeded; X register int BitsHave; X `032 X code = 0; X BitsNeeded = CodeSize; X BitsHave = 0; X X for( ;; ) `123 X `032 X`009/* X`009 * If there are no more bits, get another eight X`009 */ X if( BitsLeft == 0 ) `123 X`009`009ByteLeft = Getdata(); X`009`009BitsLeft = 8; X`009`125 X`009 X`009/* Take as many bits from what is available */ X`009if( BitsNeeded < BitsLeft ) `123 X`009`009if( BitsHave > 0 ) X`009`009`009code `124= (ByteLeft & Msk`091BitsNeeded`093) << BitsHave; X`009 `009else X`009`009`009code = ByteLeft & Msk`091BitsNeeded`093; X`009`009ByteLeft >>= BitsNeeded; X`009`009BitsLeft -= BitsNeeded; X`009`009break; X`009`009 X`009`125 else if( BitsNeeded > BitsLeft ) `123 X`009`009if( BitsHave > 0 ) X`009`009`009code `124= (ByteLeft & Msk`091BitsLeft`093) << BitsHave; X`009`009else X`009`009`009code = ByteLeft & Msk`091BitsLeft`093; X`009`009BitsHave += BitsLeft; X`009`009BitsNeeded -= BitsLeft; X`009`009BitsLeft = 0; X`009`009 X`009`125 else `123 /* BitsNeeded == BitsLeft */ X`009`009if( BitsHave > 0 ) X`009`009`009code `124= (ByteLeft & Msk`091BitsLeft`093) << BitsHave; X`009`009else X`009`009`009code = ByteLeft & Msk`091BitsLeft`093; X`009`009BitsLeft = 0; X`009`009break; X`009`125 X `125 X return (word)code; X`125 `032 X Xstatic XGIFNext( colour ) Xint colour; X`123 X`009(* _GIFPlot)( XC, YC, colour ); X`009 X/* Update the X-coordinate, and if it overflows, update the Y-coordinate */ X X XC++; X if( XC == Width ) `123 X X/* If a non-interlaced picture, just increment YC to the next scan line. If Xit's interlaced, deal with the interlace as described in the GIF spec. Put Xthe decoded scan line out to the screen if we haven't gone past the bottom Xof it */ X X XC = 0; X if( !Interlace )`032 X`009`009YC++; X`009else `123 X`009 switch( Pass ) `123 X`009 `032 X case 0: X YC += 8; X if( YC >= Height ) `123 X`009`009 `009Pass++; X`009`009`009YC = 4; X`009`009 `125 X break; X`009`009 `032 X case 1: X YC += 8; X if( YC >= Height ) `123 X`009`009 `009Pass++; X`009`009`009YC = 2; X`009`009 `125 X`009`009 break; X`009`009 `032 X case 2: X YC += 4; X if( YC >= Height ) `123 X Pass++; X YC = 1; X `125 X break; X`009`009 `032 X case 3: X YC += 2; X break; X `125 X `125 X `125 X`125 X X/* Set the key variables to their necessary initial values. */ X Xstatic XReInitialize() X`123 X X XC=0; /* X and Y screen coords back to home */ X YC=0; X Pass=0; /* Interlace pass counter back to 0 */ X PacketSize = 0; /* Number of bytes in this packet */ X CurrentCount = 0; /* ber of bytes left in this packet */ X BitsLeft = 0; /* There are no bits left */ X ByteLeft = 0; /* No Byte data left */ X`125 X +-+-+-+-+-+-+-+- END OF PART 4 +-+-+-+-+-+-+-+- -+-+-+-+-+-+-+-+ START OF PART 5 -+-+-+-+-+-+-+-+ X/* React to GIF clear code, or reset GIF decompression values back to their Xinitial state when restarting. */ X Xstatic XDoClear() X`123 X CodeSize=InitCodeSize; X MaxCode=MaxCodes`091CodeSize-2`093; X FreeCode=FirstFree; X ReadMask=Masks`091CodeSize-3`093; X`125 X Xint XGIFDisplay( Filestring, init, plot, term ) Xchar *Filestring; Xfunptr init, plot, term; X`123 X`009int i; X`009char Header`091 10 `093; X`009word Leftofs, Topofs; X`009int A, B; X X`009_GIFInit = init; X`009_GIFPlot = plot; X`009_GIFTerm = term; X X`009/* Begin the main program */ X X`009/* Initialize a bunch of variables */ X X`009ReInitialize(); /* Initialize common vars */ X X`009/* Open the file */ X X`009giffile = fopen( Filestring, "rb" ); X X`009/* Cope with I/O error should one occur */ X X if( giffile == NULL ) `123 X `009return GIF_OPEN_ERROR; X `009`125 X X/* Read in the GIF file. Reading it as one big hunk rather than N bytes resu Vlts Xin far faster disk I/O; see user notes. Error checking is turned off in Xorder to avoid 'attempt to read past EOF' errors. If the file does not exist V, Xthis will be detected at RESET */ X X/* Deal with the GIF header. Start by checking the GIF tag to make sure this Xis a GIF file */ X X for( i=0; i<6; i++ ) X `009Header`091i`093 = Getbyte(); X X Header`091 6 `093 = 0; X `032 X if( strcmp( Header, "GIF87a" ) != 0 ) `123 X return GIF_NOT_GIF; X `125 X X/* Get variables from the GIF screen descriptor */ X X RWidth = Getword(); /* The raster width and height */ X RHeight = Getword(); X X /* Get the packed byte immediately following and decode it */ X B = Getbyte(); X X if( B & 0x80 ) `123 X `009Colormap = TRUE; X `125 else X `009Colormap = FALSE; X `032 X Resolution = ((B & 0x70) >> 5) + 1; X `032 X BitsPerPixel = (B & 7) +1; X `032 X if( BitsPerPixel == 1) X `009i = 2; X else X i = 1 << BitsPerPixel; X`009 X `032 X BitMask = CodeMask`091BitsPerPixel-1`093; X `032 X Background = Getbyte(); X X `032 X B = Getbyte(); /* Skip byte of 0's */ X X/* Compute size of colormap, and read in the global one if there. Compute Xvalues to be used when we set up the EGA palette */ X X ColorMapSize = 1 << BitsPerPixel; X X if( Colormap ) `123 X `009for( i=0; i= FreeCode ) `123 X CurCode = OldCode; X OutCode`091OutCount++`093 = FinChar; X `125 X X /* X * Unless this code is raw data, pursue the chain pointed to by CurCode X * through the hash table to its end; each code in the chain puts its X * associated output code on the output queue. X */ X X if( CurCode > BitMask ) `123 X`009`009`009 X for( ;; ) `123 X X`009`009 /* Grab the next output code and put it on the queue */ X OutCode`091OutCount++`093 = Suffix`091CurCode`093; X X`009`009 /* Follow the chain */ X CurCode = Prefix`091CurCode`093; X X`009`009 /* X`009`009 * If at the end of the chain, break X`009`009 */ X`009`009 if( CurCode <= BitMask ) X`009`009 `009break; X `125 X `125 X`009 `032 X /* The last code in the chain is treated as raw data. */ X X`009 /* Mask off any garbage */ X FinChar = CurCode & BitMask; X X`009 /* Add the pixel to the queue */ X OutCode`091OutCount++`093 = FinChar; X X /* X * Now we put the data out to the using routine. It's been X`009`009* stacked LIFO, so output it back to front X */ X X`009 OutCount--; X`009 for( ; OutCount >= 0; OutCount-- ) X GIFNext(OutCode`091 OutCount `093); X X /* Make darned sure OutCount gets set back to start */ X X OutCount = 0; X X /* Build the hash table on-the-fly */ X X Prefix`091FreeCode`093 = OldCode; X Suffix`091FreeCode`093 = FinChar; X OldCode = InCode; X X /* X * Point to the next slot in the table. If we exceed the current MaxCod Ve X * value, increment the code size unless it's already 12. If it is, do X * nothing: the next code decompressed better be CLEAR. X */ X X FreeCode++; X if( FreeCode >= MaxCode ) `123 X`009 `032 X`009 /* If codesize is less than 12, increment it */ X if( CodeSize < 12 ) `123 X CodeSize++; X MaxCode = MaxCode*2; X ReadMask = Masks`091CodeSize-3`093; X `125 X`009`009 `032 X `125 X `125 /* End not Clear */; X X `125 X X`009 /* X`009 * If we have received the EOF code, exit the loop X`009 */ X`009 if( Code == EOFCode )`032 X`009`009 break; X`009 `032 X `125 X X /* Close the file */ X fclose( giffile ); X `032 X`125 /* End. */ X $ CALL UNPACK GIFDECOD.C;1 1981646605 $ create/nolog 'f' X X/*************************************************************************** V** X * X * GIFENCODE.C - GIF Image compression interface X * X * GIFEncode( FName, GHeight, GWidth, GInterlace, Background,`032 X *`009 BitsPerPixel, Red, Green, Blue, GetPixel ) X * X *************************************************************************** V**/ X`032 X#include X X/* X * Pointer to function returning an int X */ Xtypedef int (* ifunptr)(); X X#define TRUE 1 X#define FALSE 0 X Xstatic int Width, Height; Xstatic int curx, cury; Xstatic long CountDown; Xstatic int Pass = 0; Xstatic int Interlace; X X/* X * Bump the 'curx' and 'cury' to point to the next pixel X */ Xstatic XBumpPixel() X`123 X`009/* X`009 * Bump the current X position X`009 */ X`009curx++; X X`009/* X`009 * If we are at the end of a scan line, set curx back to the beginning X`009 * If we are interlaced, bump the cury to the appropriate spot, X`009 * otherwise, just increment it. X`009 */ X`009if( curx == Width ) `123 X`009`009curx = 0; X X`009 if( !Interlace )`032 X`009`009`009cury++; X`009`009else `123 X`009`009 switch( Pass ) `123 X`009 `032 X`009 case 0: X `009 cury += 8; X `009 if( cury >= Height ) `123 X`009`009 `009`009Pass++; X`009`009`009`009cury = 4; X`009`009 `009 `125 X break; X`009`009 `032 X`009 case 1: X `009 cury += 8; X `009 if( cury >= Height ) `123 X`009`009 `009`009Pass++; X`009`009`009`009cury = 2; X`009`009 `009 `125 X`009`009`009 break; X`009`009 `032 X`009 case 2: X`009 cury += 4; X`009 if( cury >= Height ) `123 X`009 Pass++; X`009 cury = 1; X`009 `125 X`009 break; X`009`009`009 `032 X`009 case 3: X`009 cury += 2; X`009 break; X`009`009`009`125 X`009`009`125 X`009`125 X`125 X X/* X * Return the next pixel from the image X */ XGIFNextPixel( getpixel ) Xifunptr getpixel; X`123 X`009int r; X X`009if( CountDown == 0 ) X`009`009return EOF; X X`009CountDown--; X X`009r = ( * getpixel )( curx, cury ); X X`009BumpPixel(); X X`009return r; X`125 X X/* public */ X XGIFEncode( FName, GWidth, GHeight, GInterlace, Background,`032 X`009 BitsPerPixel, Red, Green, Blue, GetPixel ) X`009`032 Xchar *FName; Xint GWidth, GHeight; Xint GInterlace; Xint Background; Xint BitsPerPixel; Xint Red`091`093, Green`091`093, Blue`091`093; Xifunptr GetPixel; X X`123 X`009FILE *fp; X`009int B; X`009int RWidth, RHeight; X`009int LeftOfs, TopOfs; X`009int Resolution; X`009int ColorMapSize; X`009int InitCodeSize; X`009int i; X X`009Interlace = GInterlace; X`009 X`009ColorMapSize = 1 << BitsPerPixel; X`009 X`009RWidth = Width = GWidth; X`009RHeight = Height = GHeight; X`009LeftOfs = TopOfs = 0; X`009 X`009Resolution = BitsPerPixel; X X`009/* X`009 * Calculate number of bits we are expecting X`009 */ X`009CountDown = (long)Width * (long)Height; X X`009/* X`009 * Indicate which pass we are on (if interlace) X`009 */ X`009Pass = 0; X X`009/* X`009 * The initial code size X`009 */ X`009if( BitsPerPixel <= 1 ) X`009`009InitCodeSize = 2; X`009else X`009`009InitCodeSize = BitsPerPixel; X X`009/* X`009 * Set up the current x and y position X`009 */ X`009curx = cury = 0; X X`009/* X`009 * Open the GIF file for binary write X`009 */ X`009fp = fopen( FName, "wb" ); X X`009if( fp == (FILE *)0 ) `123 X`009`009printf( "error: could not open output file\n" ); X`009`009exit(1); X`009`125 X X`009/* X`009 * Write the Magic header X`009 */ X`009fwrite( "GIF87a", 1, 6, fp ); X X`009/* X`009 * Write out the screen width and height X`009 */ X`009Putword( RWidth, fp ); X`009Putword( RHeight, fp ); X X`009/* X`009 * Indicate that there is a global colour map X`009 */ X`009B = 0x80;`009/* Yes, there is a color map */ X X`009/* X`009 * OR in the resolution X`009 */ X`009B `124= (Resolution - 1) << 5; X X`009/* X`009 * OR in the Bits per Pixel X`009 */ X`009B `124= (BitsPerPixel - 1); X X`009/* X`009 * Write it out X`009 */ X`009fputc( B, fp ); X X`009/* X`009 * Write out the Background colour X`009 */ X`009fputc( Background, fp ); X X`009/* X`009 * Byte of 0's (future expansion) X`009 */ X`009fputc( 0, fp ); X X`009/* X`009 * Write out the Global Colour Map X`009 */ X `009for( i=0; i