From JIADAR@delphi.com Fri Dec 31 00:47:21 1993 Path: klaava!news.funet.fi!sunic!EU.net!howland.reston.ans.net!cs.utexas.edu!news.tamu.edu!bloom-beacon.mit.edu!noc.near.net!news.delphi.com!usenet From: Ross Martin Andrew Capdeville Newsgroups: comp.sys.cbm Subject: Re: Programming Date: Tue, 28 DEC 93 23:49:13 EST Organization: Delphi Internet Lines: 796 Message-ID: <931228.85753.JIADAR@delphi.com> References: <931228.10928.JIADAR@delphi.com> NNTP-Posting-Host: bos3a.delphi.com Ratastic Programming, Inc. page 1. 931228-0134.mls 28 December 1993 Program: 931228-0134.mls Sprite! Description: ML conversion of basic program. Demonstration of sprite creation and movement. *= $c000 o:.s Instructions to the asembler. The start address will be $c000, we want to poke data to memory and display to the screen. v = 53248 Set the variable (label) V to the starting address of the VIC chip, 53248. We can use this as an offset to access VIC regesters. print = $ffd2 strout = $ab1e Define two more variables, these are kernal routines to print a character and string. lda #5:jsr print:lda #6:sta 53280:sta 53281:ldx #64 This sets the color to white, backround and border colors to light blue, and puts 64 in .x. .X will be the index to read in the sprite data. loop lda data,x:sta 832,x:dex:bne loop This simply puts the sprite data into block 13 of sprite memory in bank 1. It is sorta like a backwards (step-1) for next loop in basic, sorta... lda #255:sta x:lda #200:sta y Here we set the default values for the X and Y variables. Do not confuse these with the regesters. These variables will be used to hold the position of the sprite. lda #4:sta v+21 ; set the sprite enable regester to enable ; sprite 2 lda #1:sta v+41 ; color sprite 2 white lda x:sta v+4 ; position x lda y:sta v+5 ; position y lda #13:sta 2042; data block 13 lda #0:sta 53264; zero MSB of X lda #1:sta i ; not needed The above code just sets the VIC regesters and displays the sprite at x,y from data block 13. Ratastic Programming, Inc. page 2. 931228-0134.mls 28 December 1993 lda #txt:jsr strout This prints some text on the screen. When we run into this text with the sprite, the program will end. rj lda 56320:and #15:sta j This reads the joystick. It is like j=peek(56320)and15 in basic. We will get the following values: 14 10 6 11 15 7 9 5 13 We put the value recieved into the variable J. lda 56320:and #16:bne ctu1:rts We check if the fire button is pressed. This is like the basic if(peek(56320)and16)=0thenend. We use the BNE instruction because if it is TRUE the fire button is NOT pressed. ctu1 lda 53279:lda j:ldy y:ldx x First we latch 53279 to reset the collision detect. Then we load the variable J into the .a regester, y into .y, and x into .x. Now we can directly access the varibles through the regesters. lda j:cmp #14:bne ctu2:dey:jmp chadr ; up ctu2 lda j:cmp #13:bne ctu3:iny:jmp chadr ; down ctu3 lda j:cmp #11:bne ctu4:dex:jmp chadr ; left ctu4 lda j:cmp #7:bne ctu5:inx:jmp chadr ; right ctu5 lda j:cmp #10:bne ctu6:dex:dey:jmp chadr ; up-left ctu6 lda j:cmp #6:bne ctu7:dey:inx:jmp chadr ; up-right ctu7 lda j:cmp #5:bne ctu8:inx:iny:jmp chadr ; down-right ctu8 lda j:cmp #9:bne ctu9:dex:iny:jmp chadr ; down-left ctu9 jmp chadr This block of code increments regesters according to the variable J. This is like basic - if j=xx then do this. If not it is ignored. All in all, we end up at CHADR. chadr jsr delay:jmp ruda We jsr to a delay subroutine so we can actually SEE the sprite on the screen, and then we jump to RUDA. Ratastic Programming, Inc. page 3. 931228-0134.mls 28 December 1993 lda 53264:and #4:beq nl lda #0:sta 53264:ldx #255:jmp ruda nl lda 53264:ora #4:sta 53264:ldx #0 This code was sopose to check for the LINE and deal with the MSB X regester, but I could not figure out how to do it. If you know how, help me! ruda lda 53279:and #4:beq rdt:rts Here we check the sprite to data collision regester, and if it is true (you touch **STOP** with the sprite) then we end the program. rdt stx x:sty y:stx v+4:sty v+5:jmp rj We update the X and Y variables and actually move the sprite. Then we go back to RJ (read-joystick) to do it all over again. rts I just have this here so it does not crash if I forgot it. delay sty y:pha:tya:pha:ldy #0 lop1 dey:sty v+41:bne lop1 pla:tay:pla:ldy #1:sta v+41:ldy y:rts Simple longated delay subroutine which attempts to save the variables. i .byte 1 x .byte 0 y .byte 0 j .byte 0 txt .byte 147:.byte "**stop**":.byte 0 Variables used in the program. 'I' is not used but the others are. data .byte 255 128 0 255 0 0 byte 254 0 0 252 0 0 byte 252 0 0 254 0 0 byte 231 0 0 195 128 0 byte 129 192 0 0 224 0 byte 0 112 0 0 48 0 byte 0 0 0 0 0 0 byte 0 0 0 0 0 0 byte 0 0 0 0 0 0 byte 0 0 0 0 0 0 byte 0 0 0 0 0 0 Ratastic Programming, Inc. page 4. 931228-0134.mls 28 December 1993 The data for the sprite. end We tell the asembler to stop assembling. Here is the complete listing for easier typing in via an assembler such as RLASS (avaliable from me). 10 *= $c000 20 .o:.s 30 v = 53248 40 print = $ffd2 50 strout = $ab1e 100 lda #5:jsr print:lda #6:sta 53280:sta 53281:ldx #64 110 loop lda data,x:sta 832,x:dex:bne loop 120 lda #255:sta x:lda #200:sta y 130 lda #4:sta v+21 140 lda #1:sta v+41 150 lda x:sta v+4 160 lda y:sta v+5 170 lda #13:sta 2042 180 lda #0:sta 53264 190 lda #1:sta i 200 lda #txt:jsr strout 210 rj lda 56320:and #15:sta j 220 lda 56320:and #16:bne ctu1:rts 230 ctu1 lda 53279:lda j:ldy y:ldx x 240 lda j:cmp #14:bne ctu2:dey:jmp chadr 250 ctu2 lda j:cmp #13:bne ctu3:iny:jmp chadr 260 ctu3 lda j:cmp #11:bne ctu4:dex:jmp chadr 270 ctu4 lda j:cmp #7:bne ctu5:inx:jmp chadr 280 ctu5 lda j:cmp #10:bne ctu6:dex:dey:jmp chadr 290 ctu6 lda j:cmp #6:bne ctu7:dey:inx:jmp chadr 300 ctu7 lda j:cmp #5:bne ctu8:inx:iny:jmp chadr 310 ctu8 lda j:cmp #9:bne ctu9:dex:iny:jmp chadr 320 ctu9 jmp chadr 330 chadr jsr delay:jmp ruda 340 lda 53264:and #4:beq nl 350 lda #0:sta 53264:ldx #255:jmp ruda 360 nl lda 53264:ora #4:sta 53264:ldx #0 370 ruda lda 53279:and #4:beq rdt:rts 380 rdt stx x:sty y:stx v+4:sty v+5:jmp rj 39999 rts 40000 delay sty y:pha:tya:pha:ldy #0 40010 lop1 dey:sty v+41:bne lop1 40020 pla:tay:pla:ldy #1:sta v+41:ldy y:rts Ratastic Programming, Inc. page 5. 931228-0134.mls 28 December 1993 49999 rts 50000 i .byte 1 50010 x .byte 0 50020 y .byte 0 50030 j .byte 0 55000 txt .byte 147:.byte "**stop**":.byte 0 60000 data .byte 255 128 0 255 0 0 60010 .byte 254 0 0 252 0 0 60020 .byte 252 0 0 254 0 0 60030 .byte 231 0 0 195 128 0 60040 .byte 129 192 0 0 224 0 60050 .byte 0 112 0 0 48 0 60060 .byte 0 0 0 0 0 0 60070 .byte 0 0 0 0 0 0 60080 .byte 0 0 0 0 0 0 60090 .byte 0 0 0 0 0 0 60100 .byte 0 0 0 0 0 0 63999 .end ready. And if you do not have an assembler, here is a listing of a BASIC loader which loads the ML from data statements. You can type this in directly in BASIC. BE VERY CAREFUL and watch out for errors. There are 365 data items to type in! 0 rem sprite! by ratastic 1 rem 931228-0134.mls 2 rem sprite - joystick mover 10 forx=49152to49517:ready:pokex,y:next 20 print"finished...[down 9]":print"sys49152 to start" 30 poke 49417,0 :rem speed 1 is fastest 0 is slowest 255 is slow, 5 is fast exc 60000 data 169, 5, 32, 210, 255, 169 60001 data 6, 141, 32, 208, 141, 33 60002 data 208, 162, 64, 189, 43, 193 60003 data 157, 64, 3, 202, 208, 247 60004 data 169, 255, 141, 30, 193, 169 60005 data 200, 141, 31, 193, 169, 4 60006 data 141, 21, 208, 169, 1, 141 60007 data 41, 208, 173, 30, 193, 141 60008 data 4, 208, 173, 31, 193, 141 60009 data 5, 208, 169, 13, 141, 250 60010 data 7, 169, 0, 141, 16, 208 60011 data 169, 1, 141, 29, 193, 169 60012 data 33, 160, 193, 32, 30, 171 60013 data 173, 0, 220, 41, 15, 141 60014 data 32, 193, 173, 0, 220, 41 60015 data 16, 208, 1, 96, 173, 31 60016 data 208, 173, 32, 193, 172, 31 60017 data 193, 174, 30, 193, 173, 32 Ratastic Programming, Inc. page 6. 931228-0134.mls 28 December 1993 60018 data 193, 201, 14, 208, 4, 136 60019 data 76, 201, 192, 173, 32, 193 60020 data 201, 13, 208, 4, 200, 76 60021 data 201, 192, 173, 32, 193, 201 60022 data 11, 208, 4, 202, 76, 201 60023 data 192, 173, 32, 193, 201, 7 60024 data 208, 4, 232, 76, 201, 192 60025 data 173, 32, 193, 201, 10, 208 60026 data 5, 202, 136, 76, 201, 192 60027 data 173, 32, 193, 201, 6, 208 60028 data 5, 136, 232, 76, 201, 192 60029 data 173, 32, 193, 201, 5, 208 60030 data 5, 232, 200, 76, 201, 192 60031 data 173, 32, 193, 201, 9, 208 60032 data 5, 202, 200, 76, 201, 192 60033 data 76, 201, 192, 32, 2, 193 60034 data 76, 234, 192, 173, 16, 208 60035 data 41, 4, 240, 10, 169, 0 60036 data 141, 16, 208, 162, 255, 76 60037 data 234, 192, 173, 16, 208, 9 60038 data 4, 141, 16, 208, 162, 0 60039 data 173, 31, 208, 41, 4, 240 60040 data 1, 96, 142, 30, 193, 140 60041 data 31, 193, 142, 4, 208, 140 60042 data 5, 208, 76, 78, 192, 96 60043 data 140, 31, 193, 72, 152, 72 60044 data 160, 0, 136, 140, 41, 208 60045 data 208, 250, 104, 168, 104, 160 60046 data 1, 141, 41, 208, 172, 31 60047 data 193, 96, 96, 1, 56, 54 60048 data 14, 147, 42, 42, 83, 84 60049 data 79, 80, 42, 42, 0, 255 60050 data 128, 0, 255, 0, 0, 254 60051 data 0, 0, 252, 0, 0, 252 60052 data 0, 0, 254, 0, 0, 231 60053 data 0, 0, 195, 128, 0, 129 60054 data 192, 0, 0, 224, 0, 0 60055 data 112, 0, 0, 48, 0, 0 60056 data 0, 0, 0, 0, 0, 0 60057 data 0, 0, 0, 0, 0, 0 60058 data 0, 0, 0, 0, 0, 0 60059 data 0, 0, 0, 0, 0, 0 60060 data 0, 0, 0, 0, 0, 0 60061 data 0, 0, 0, 0, 0, 0 ready. That is quite alot of data and if you do not really need the speed, here is the BASIC version before I coded it to ML. It does check for the MSB. The explination for this program is also contained. Ratastic Programming, Inc. page 7. 931228-0134.mls 28 December 1993 0 printchr$(5):poke53280,6:poke53281,6 Make backround and border light blue and change text to white. 10 forx=832to832+63:ready:pokex,y:nextx Read in sprite data into block 13 of bank 1. Bank 1 is the default bank. We get block 13 by 832/64. If we were to use 704 to 704+64 then it would be block 11 (704/64). We use this block number with the sprite pointer regester. We read 63 bytes from data statements and poke them into memory. 15 x=255:y=200 Set the x and y co-ordinates of the sprite. 20 v=53248 :rem set 'v' to vic adr Set the varible 'v' to the start of VIC memory. This allows us to address specific regesters of the vic with V+regvalue. 30 pokev+21,4 :rem enable spr 2 Regester 21 of the VIC chip is the sprite enable regester. We poke it like this: POKE V+21, PEEK (V+21) OR (sprite enable^2) to enable a specific sprite. Since we will be using only sprite 3, we just poke it with a 4. This is done by binary representation: Sprite -> 7 6 5 4 3 2 1 0 Binary -> 1 1 1 1 1 1 1 1 ->255 (one byte) Value -> 128 64 32 16 8 4 2 1 The 'value' for sprite 2 is 4, so we poke that into the Sprite Enable Regester and that allows the sprite to be visable. 40 pokev+41,1 :rem color spr 2 white This sets the color of the sprite just as you would set the backround or border colors. The arguments are the same. This sets sprite 2. Each sprite has a seperate color register. Sprite 0 has reg. 39, all the way for all 7 sprites. 50 pokev+4,x :rem position spr 2 x This is the X position (lower 8 bits) of sprite 2. Each sprite has an X position and a Y position. We defined X earlier, so we poke register 4 with the value of X, thus placing the sprite on the visual screen. 60 pokev+5,y :rem position spr 2 y We must poke the Y value also. Ratastic Programming, Inc. page 8. 931228-0134.mls 28 December 1993 70 poke2042,13 :rem data block for spr 2 This tells the VIC chip where to get the data. This is a block number, thus the number poked here times 64 will give the actual starting address of the data. 13*64 = 832 and that is where we are putting the sprite data. 80 poke53264,0 :rem 0 msb of x This is the 9th bit of the X regester. The arguments work like the sprite enable regester, one bit for each sprite. Since there are more than 255 (one byte) scan lines for X, we must provide another bit to provide for five hundered something places. We set this to 0 because we are setting the X position at 255. If we wanted to set X at the 256th position, we would set bit two of this regester to 1 and the X position regester to 0. That would give a binary value of %100000000 which is the nine bit representation of 256. 90 i=1 Delares the variable I and sets its value to 1. This will be used to increment the joystick control. 91 printchr$(147)"**stop** " Print a prompt. This will be used to stop the program. When the pointer comes into contact with this text, the program will end. We can check by the sprite to data collision regester. 100 rem move sprite by joystick in 110 rem port 2 subroutine We will now write a subroutine that will allow us to move the sprite via a joystick in port 2. 120 j=not peek(56320)and15 This peeks the CIA#1 chip (complex-interface-adapter) to get the value of joystick 2. No need to HOW it works, just know that it does. 121 if((peek(56320)and16)/16)=0thenend This is a test for the fire button. If it is false, 0, then we will abort the program. Again, no need to know how it works. (If you want to I will explain but it will confuse you!) 122 a=peek(53279) All this does is clear the sprite to data collision regester. This regester is cleared when read and we need to set it to 0 before we start anything else. Ratastic Programming, Inc. page 9. 931228-0134.mls 28 December 1993 130 ifj=1theny=y-i 140 ifj=2theny=y+i 150 ifj=4thenx=x-i 160 ifj=8thenx=x+i 170 ifj=5thenx=x-i:y=y-i 180 ifj=9theny=y-i:x=x+i 190 ifj=10thenx=x+i:y=y+i 200 ifj=6thenx=x-i:y=y+i The above code checks for all possible joystick positions and adjusts the x and y variables accordingly. Here is a chart of the possible values of J: 1 5 9 4 0 8 6 10 2 201 ifj=0thenp=1:i=1 202 if(p/15)=int(p/15)theni=i+1 203 ifjthenp=p+1 204 ifi>5theni=5 This code adjusts the speed of the poiner if it is held down for an extended amount of time. In line 201, we check to see if the joystick is stationary (0 value) and if it is then we set P (pulse-counter) to 1 and I to 1. This is the slowest speed and is also the default. In line 202 we check if P is a mutiple of 15 and if so then we increment I. So I will be incremented when P reaches 15, 30, 45, 60, 75, so on until the joystick is released. In line 203 we check if J is non-zero (boleon logic tests...) and if it is not that means that the joystick is being held in one direction so we increment P. Line 204 makes sure we do not allow the joystick to go TOO fast. The variable I cannot go over 5. 210 if(x<256)and(x>-1)then220 211 if(peek(53264)and4)thenpoke53264,0:x=255:goto220 212 poke53264,peek(53264)or4:x=0 This code allows us to get over the invisible LINE. Since there are over 255 X scan lines, we must be able to move the sprite past the 255th X position. There is a MSB regester that works like the sprite enable regester. Follow the logic... In line 210 we check to see if X is out of range. A byte can only be >-1 and <256 so we check that and if X is within range than no changing needs to be done and we continue with 220. If X is out of range, though, we need to fix something as we can not POKE a value greater than 255 or less than 0. In line 211 we check (by boleon logic) to see if the MSB is ON. We use the AND 4 at the end to strip all bits except the 2nd binary diget. Therefore, if it is true Ratastic Programming, Inc. page 10. 931228-0134.mls 28 December 1993 we will get 4 and if it is false we will get 0. If it is true, then we make it 0 and make X 255 and go to 220. If it is not true, then only one other condition could be- its false! If it is false, then we must turn the MSB ON and make X 0. Then the sprite will be at the 256th position. I know, it is confusing... 220 if(peek(53279)and4)thenend This is the sprite to data collision detect regester. The expression peek(53279)and4 will return 0 or 4 depending on if the sprite has touched any characters on the screen. If it has, it will be 4, thus true. If it has not it will be 0. If it is true then we end the program as the user moved the sprite and touched the **STOP** prompt printed earlier. 230 pokev+4,x:pokev+5,y:goto120 Here we update the co-ordinants, thus actually moving the sprite. We go back to 120 to get another joystick value and we do it all over again! 60000 data 255, 128, 0, 255, 0, 0 60001 data 254, 0, 0, 252, 0, 0 60002 data 252, 0, 0, 254, 0, 0 60003 data 231, 0, 0, 195, 128, 0 60004 data 129, 192, 0, 0, 224, 0 60005 data 0, 112, 0, 0, 48, 0 60006 data 0, 0, 0, 0, 0, 0 60007 data 0, 0, 0, 0, 0, 0 60008 data 0, 0, 0, 0, 0, 0 60009 data 0, 0, 0, 0, 0, 0 60010 data 0, 0, 0, 0, 0, 0 That is the data for the sprite shaped like a pointer. Here is the complete uncommented program for easier typing in. ready. 0 printchr$(5):poke53280,6:poke53281,6 10 forx=832to832+63:ready:pokex,y:nextx 15 x=255:y=200 20 v=53248 :rem set 'v' to vic adr 30 pokev+21,4 :rem enable spr 3 40 pokev+41,1 :rem color spr 3 white 50 pokev+4,x :rem position spr 3 x 60 pokev+5,y :rem position spr 3 y Ratastic Programming, Inc. page 11. 931228-0134.mls 28 December 1993 70 poke2042,13 :rem data block for spr3 80 poke53264,0 :rem 0 msb of x 90 i=1 91 printchr$(147)"**stop** " 100 rem move sprite by joystick in 110 rem port 2 subroutine 120 j=not peek(56320)and15 121 if((peek(56320)and16)/16)=0thenend 122 a=peek(53279) 130 ifj=1theny=y-i 140 ifj=2theny=y+i 150 ifj=4thenx=x-i 160 ifj=8thenx=x+i 170 ifj=5thenx=x-i:y=y-i 180 ifj=9theny=y-i:x=x+i 190 ifj=10thenx=x+i:y=y+i 200 ifj=6thenx=x-i:y=y+i 201 ifj=0thenp=1:i=1 202 if(p/15)=int(p/15)theni=i+1 203 ifjthenp=p+1 204 ifi>5theni=5 210 if(x<256)and(x>-1)then220 211 if(peek(53264)and4)thenpoke53264,0:x=255:goto220 212 poke53264,peek(53264)or4:x=0 220 if(peek(53279)and4)thenend 230 pokev+4,x:pokev+5,y:goto120 60000 data 255, 128, 0, 255, 0, 0 60001 data 254, 0, 0, 252, 0, 0 60002 data 252, 0, 0, 254, 0, 0 60003 data 231, 0, 0, 195, 128, 0 60004 data 129, 192, 0, 0, 224, 0 60005 data 0, 112, 0, 0, 48, 0 60006 data 0, 0, 0, 0, 0, 0 60007 data 0, 0, 0, 0, 0, 0 60008 data 0, 0, 0, 0, 0, 0 60009 data 0, 0, 0, 0, 0, 0 60010 data 0, 0, 0, 0, 0, 0 ready. Ratastic Programming, Inc. page 12. 931228-0134.mls 28 December 1993 UUENCODINGS. If you do not want to type it in, here are the uuencodings for three programs. GFX.PTR-EXAMPL is the basic program. BLR.SPRITE is the basic loader for the machine language program. GFX.SPR-EDITOR is my sprite editor. Here are the instructions for that -> type RUN and you will get a grid. Design your sprite with astricts * on the grid. Then go right below the grid and type RUN 100. It will draw your sprite. If you are not satisified, then fix it with * and . and then RUN 100 again and it will re-draw. When you are satisfied, you can save the numbered data to a SEQ file or have the program write data statements for you. If you want to save it to a seq file RUN 200, to load it RUN 300. To print out data RUN 400. When it asks you to erase the program tell it yes. It will give you data statements and some lines to set up the sprite. Its small, but it works and is all I need to make awesome sprite demos like the ones contained within this document! begin 644 gfx.ptr-exampl M_0@="___F<_!* MLJ@@PB@U-C,R,"FO,34_T_EY_(LH*,(H-38S,C_IKS$V*:TQ-BFR,*>_("_@ M("_@("_@("_@("_@("__WPEZ_$&RPB@U,S(W.2D_[@F"_(M*LC&G6;)9JTD_ M_0F,_(M*LC*G6;)9JDD_#_J6_(M*LC2G6+)8JTD_&PJ@_(M*LCBG6+)8JDD_ M,_JJ_(M*LC6G6+)8JTDZ6;)9JTD_10JT_(M*LCFG6;)9JTDZ6+)8JDD_6PJ^ M_(M*LC$PIUBR6*I).EFR6:I)_'_*R_"+2K(VIUBR6*M).EFR6:I)_($*R0"+ M2K(PIU"R,3I)LC$_FPK*_(LH4*TQ-2FRM2A0K3$U*:=)LDFJ,0"H"LL_BTJG M4+)0JC$_M0K,_(M)L36G2;(U_,T*T@"+*%BS,C4V*:\H6+&K,2FG,C(P_/,* MTP"+*,(H-3,R-C0IKS0IIY__#@+Y@"75JHT M+%@ZEU:J-2Q9.HDQ,C__50M@ZH,@,C4U+"_Q,C@L(#_L(#(U-2P@,"P@,_!P M"V'J@R_R-30L(#_L(#_L(#(U,BP@,"P@,_"+"V+J@R_R-3(L(#_L(#_L(#(U M-"P@,"P@,_"H"V/J@R_R,S$L(#_L(#_L(#$Y-2P@,3(X+"_P_,4+9.J#(#$R M.2P@,3DR+"_P+"_P+"_R,C0L(#__WPMEZH,@,"P@,3$R+"_P+"_P+"_T."P@ M,_#V"V;J@R_P+"_P+"_P+"_P+"_P+"_P__T,9^J#(#_L(#_L(#_L(#_L(#_L M(#__)_QHZH,@,"P@,"P@,"P@,"P@,"P@,__[#&GJ@R_P+"_P+"_P+"_P+"_P =+"_P_%(,:NJ#(#_L(#_L(#_L(#_L(#_L(#______ _ end Ratastic Programming, Inc. page 13. 931228-0134.mls 28 December 1993 begin 644 blr.sprite M_0@?"___CR!34%))5$4A("_@("!"62!2051!4U1)0P_U"_$_CR_Y,S$R,C@M M,#$S-"Y-3%,_4P@"_(\@4U!2251%("T@2D]94U1)0TL@34]615(_<_@*_(%8 MLC0Y,34RI#0Y-3$W.H=9.I=8+%DZ@@"A"!0_F2)&24Y)4TA%1"XN+A$1$1$1 M$1$1$2(ZF2)365,T.3$U,B!43R!35$%25"(_[0@>_)<@-#DT,3J# M(#(P,"P@,30Q+"_S,2P@,3DS+"_Q-CDL(#0_SPEFZH,@,30Q+"_R,2P@,C_X M+"_Q-CDL(#$L(#$T,0#P"6?J@R_T,2P@,C_X+"_Q-S,L(#,P+"_Q.3,L(#$T M,0_0"FCJ@R_T+"_R,#@L(#$W,RP@,S$L(#$Y,RP@,30Q_#_*:>J#(#4L(#(P M."P@,38Y+"_Q,RP@,30Q+"_R-3__3@IJZH,@-RP@,38Y+"_P+"_Q-#$L(#$V M+"_R,#@_;@IKZH,@,38Y+"_Q+"_Q-#$L(#(Y+"_Q.3,L(#$V.0"."FSJ@R_S M,RP@,38P+"_Q.3,L(#,R+"_S,"P@,3J#(#$W,RP@,"P@,C(P+"_T M,2P@,34L(#$T,0#,"F[J@R_S,BP@,3DS+"_Q-S,L(#_L(#(R,"P@-#$_Z@IO MZH,@,38L(#(P."P@,2P@.38L(#$W,RP@,S$_"PMPZH,@,C_X+"_Q-S,L(#,R M+"_Q.3,L(#$W,BP@,S$_+_MQZH,@,3DS+"_Q-S0L(#,P+"_Q.3,L(#$W,RP@ M,S(_3_MRZH,@,3DS+"_R,#$L(#$T+"_R,#@L(#0L(#$S-@!M"W/J@R_W-BP@ M,C_Q+"_Q.3(L(#$W,RP@,S(L(#$Y,P","W3J@R_R,#$L(#$S+"_R,#@L(#0L M(#(P,"P@-S8_K@MUZH,@,C_Q+"_Q.3(L(#$W,RP@,S(L(#$Y,RP@,C_Q_,T+ M=NJ#(#$Q+"_R,#@L(#0L(#(P,BP@-S8L(#(P,0#M"W?J@R_Q.3(L(#$W,RP@ M,S(L(#$Y,RP@,C_Q+"_W__T,>.J#(#(P."P@-"P@,C,R+"_W-BP@,C_Q+"_Q M.3(_+@QYZH,@,30ED_)PZ0[(X.H%9LC"D,C_Z@5BR,:0R-#I0LL(H,3_R,ZI8JC0PK%DI.D.R M0ZLQ.HM0LC0RIU&R4:HRKD,_F0EN_(M#LC"G0[(X.D>R1ZHQ.IJ#(#_L(#_L(#_L(#_L(#_L(#__;_QBZH,@,"P@,"P@,"P@ M,"P@,"P@,_"##&/J@R_P+"_P+"_P+"_P+"_P+"_P_)H,9.J#(#_L(#_L(#_L M(#_L(#_L(#__L0QEZH,@,"P@,"P@,"P@,"P@,"P@,_#(#&;J@R_P+"_P+"_P M+"_P+"_P+"_P_-\,9^J#(#_L(#_L(#_L(#_L(#_L(#__]@QHZH,@,"P@,"P@ M,"P@,"P@,"P@,__-#6GJ@R_P+"_P+"_P+"_P+"_P+"_P_"0-:NJ#(#_L(#_L (#_L(#_L(#_L(#______ _ end -- Ross Martin Andrew Capdeville of Ratastic Programming, Inc. Inet: Jiadar@delphi.com 604 N St Patrick Jiadar@mintir.new-orleans.la.us New Orleans/LA 70119 Fido: 1:396/65 The Digital Cottage Eye of Leveta II! A Proud Programmer of the Commodore 64/128!!! -- The chant of a resistor: ohm... ohm... ohm...