----------------------------------------- ZCP : ZShell Compressed Pictures v2.0 Stephane JANTZEN - February 1996 Stephane.Jantzen@scinfo.u-nancy.fr I wish it was a standard ! :) ----------------------------------------- How does it work ? ------------------ I've chosen a RLE such as implemented in PCX format, but adapted to fit B&W TI-85 pictures. It is the best compromise between the size of the compressed data and the complexity of the encoding/decoding operations. So let's suppose we can have : 76543210 FBCCCCCC (1) - a 'stream' chunk. FDDDDDDD (2) - a 'copy' chunk. The two possible byte formats. In both (1) and (2), F represents a flag that allows to determine what sort of byte it is : if F is zero, then the rest of the byte conforms to (1), else it conforms to (2). Here is the problem : PCX-RLE stores the number of data in one byte, then the data itself in the following byte (this is not _exactly_ how it does, but this is the idea). But in TI-85, the only data we have to store is 1 or 0, so we don't need a whole byte to store it, but only a bit. I store it in bit B. Then the next 6 bits give me the number of contiguous B's in my stream (let's call that 'count'), until I meet the B's opposite, or the end of the picture, or I reach count = 63, which is the greater number storable in 6 bits. Here it is ! Just a note : the convention I've used for B is B = 0 : next pixels are white B = 1 : guess what ? :) It should be enough, but we can make better ... Then (2) : You can easily see that if 'count' is small, then the compression ratio for this chunk is low, as I use 8 bits to store 'count' bits. So here is the trick (tadaaa !) : if I see that count is smaller or equal than 7, I di- rectly store the 7 following bit in my byte : this is the byte format (2). The local compression ratio for this byte is greater than 1, as I use 8 bits to store 7 bits of data. Nevertheless, this is _far_ better than only using the (1) chunk format. Examples -------- A picture starting with several blank lines should be coded : .db $3F,$3F,$3F, ..... $3F = 00111111, which means : I am in case (1) (given by bit 7), I want to store zero's (given by bit 6), and I have 63 of them. (63d = 00111111b) On the other side, if I meet : .db ...... ,$F3 The most significant bit tells me that I'm in 'copy' mode (2). F3h = 11110011b so the next seven pixels to be written are 1110011, with the previous conven- tion. Related programs ---------------- The first program I've joined uses this algorithm to convert a TI-85 picture into a series of db's. Only the executable form is available, as the source is quite ugly (written using BP7 - I'm too lazy to rewrite it in C). This version is a little bit faster and shorter than the previous one. As the com- pression algorithm hasn't changed, performances are the same as version 1. The decoder source follows. You'll have to use the encoder to generate a file containing the db's and concat this file to the ASM program, then recompile it and send it to your TI. This program has been written for ZShell 4.0 by Pascal Bouron (Bouron@YOKO.ENS-Cachan.fr) : frenchies on the top :) and is now fast enough to be fully usable. Its size is actually 97 bytes. Just one thing about the decoder : as you may have noticed, the data stream is zero-terminated. This allows another compression : if your picture ends with a series of blank lines, they're just replaced by a $00 : useless data are not stored. Ideas ----- It would be great if a format of this kind was a standard for all Zshell pro- grammers, and I propose mine to you : I think the compression ratio is good enough for an efficient use (I had first thought about a LZW compression, but the decoding time would have been far greater, for a small efficience on the size of the data). ZCP gives a compression of 50% for 'normal' pictures, which is rather acceptable. Now that the decoding speed is not a problem anymore (Thanx God and Pascal), it may be a good alternative to 'normal' picture sto- rage in a TI-85. Please let me know by mail if you _really_use it. The PC-based encoder : zcp.exe ------------------------------ begin 644 zcp.exe M35H0`!,`G@`J`-$'T:?H!0!```"J`@``'````*T"``"R`@``O0(``-("``#7 M`@``W`(``.T"``#R`@``]P(```@#```-`P``$@,``",#```H`P``+0,``#<# M```\`P``30,``%@#``!N`P``>@,``'\#``"$`P``H`,``*T#``"\`P``T0,` M`-L#``#H`P``]P,```,$```(!```'00``"D$```U!```.@0``#\$``!F5N0'-C:6YF M;RYU+6YA;F-Y+F9R(""S4,#$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$ MQ,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$Q,3$ MQ,3$Q,39"$524D]2(#H@#T)A9"!P87)A;65T97)S+@$N!"XX-6D0(&1O97,@ M;F]T(&5X:7-T+@@J*E1).#4J*AT@:7,@;F]T(&$@5$DM.#4@<&EC='5R92!F M:6QE+C`[+2TM(%I#4"!E;F-O9&5R('8R+C`@+2!3=&5P:&%N92!*04Y46D5. M("T@,#(O.38A.RTM+2!"96=I;FYI;F<@;V8@6D-0(&1A=&$@6X`@.:S0(6`8'L`@._+#P>5[\```Y7:@":<`86 M`9K^!18!FI$"%@&_+#P>5[]1``Y7:@":<`86`9K^!18!FI$"%@&_+#P>5[^B M``Y7:@":<`86`9K^!18!FI$"%@&_+#P>5[_S``Y7:@":<`86`9K^!18!FI$" M%@&_+#P>5YK=!18!FI$"%@&_1`$.5[]B`!Y7:@B:M@H6`<<&%CL9`)HZ"18! M/0(`="R_+#P>5[]B`!Y7:@":<`86`;]-`0Y7:@":<`86`9K=!18!FI$"%@'& M!FL``8`^:P``=`/IL0"-O@#_%E=J`9KK"!8!OVP`'E=H_P":M@H6`;]=`0Y7 MOVP`'E>:1PL6`3T"`'\GC;X`_Q97OVP`'E>:G`H6`;]?`0Y7FAL+%@&_;``> M5VC_`)JV"A8!OVP!'E>_;``>5YHM!Q8!OVP!'E=J`9IH!Q8!FHH"%@$)P'0X MORP\'E>_8@`>5VH`FG`&%@&_;``>5VH`FG`&%@&_9`$.5VH`FG`&%@&:W046 M`9J1`A8!Q@9K``&`/FL``'0#Z_^CD>5YJ< M"A8!C;X`_Q97BS[V.8J%[`)0FK@+%@&:&PL6`;_Z.1Y7:@B:M@H6`8,^]CD' M=<"_^CD>5[]U`0Y7FHT+%@%T1[\L/!Y7OV(`'E=J`)IP!A8!OVP`'E=J`)IP M!A8!OWX!#E=J`)IP!A8!FMT%%@&:D0(6`<8&:P`!OVP!'E>:Z0<6`9J1`A8! M@#YK``!T`^F;!;_L`1Y7C;X`_Q97:@*:ZP@6`9KF`A8!O^P!'E>::0,6`9J1 M`A8!O^P!'E>:O@,6`9J1`A8!OVP!'E=J`&H\FKL(%@&:D0(6`;]L`1Y7OP,Z M'E=J`3'`4%":4P@6`9J1`A8!OVP!'E>_;`$>5YKY#A8!FI$"%@&+R(O:H`,Z M,.0QT@/!$],%!`"#T@!24)J["!8!FI$"%@&_;`$>5[_L`AY7:/`#,L$_P;V.:'V.9FY"`#W^9*+T+@'`"O"B]BA]CF9N0@` M]_F+^(J%[`(PY(O+T^@E`0"+/O8YB(7`/@0Z/W7;@#X$.@=V%J`$.C#DB]"@`SHP MY,'@!@/"H@,ZZWO&!@,Z@,<&^#E``,8&%#L`H`0Z,.2+T*$*.BO"!0<`B4;^ MH`0Z,.2+T*$*.BO".T;^?S>C]CGK!/\&]CF+/O8YBH7:;@,6`9J1`A8!O^P!'E>-OO[^%E>_ M;``>5VH!H&P`,.1(4)K:"A8!:@":<`86`9K=!18!FI$"%@&A##M`F?<^%CN2 M"MYH?8Y2)FY$`#W^9()P'5J_P8,.Z$,.YGW M/A8[D@G`=0^_[`$>5YIN`Q8!FI$"%@&_[`$>5[]L`!Y7:@":<`86`9K=!18! MFI$"%@&A##M`F?<^%CN2"5YIN`Q8!FI$"%@&_[`$>5YK= M!18!FI$"%@'_-@@Z_S8&.FH`OVP`'E=H_P":?0X6`;_L`1Y7OS$"#E=J`)IP M!A8!OVP`'E=J`)IP!A8!OTH"#E=J`)IP!A8!FMT%%@&:D0(6`;_L`1Y7FKX# M%@&:D0(6`;\L/!Y7OU("#E=J`)IP!A8!_S8(.O\V!CIJ`)KX!A8!OVH"#E=J M`)IP!A8!FOX%%@&:D0(6`;\L/!Y7H08ZBQ8(.KED`#';FG,)%@&Y\`,QVYJP M"18!4E!J`)KX!A8!OW,"#E=J`)IP!A8!FMT%%@&:D0(6`3'`HPX[,<"C$#O' M!A([`0"`/FL``'1CORP\'E>:W046`9J1`A8!ORP\'E>_=@(.5VH`FG`&%@&: MW046`9J1`A8!ORP\'E>:W046`9J1`A8!ORP\'E>_E@(.5VH`FG`&%@&:_@46 M`9J1`A8!ORP\'E>:W046`9J1`A8!R3'`FA8!%@$`````````````````58GE MN/\`FA8!%@%=PU6)Y>@H`+\L.QY7#N@@`[\L.QY7FF0#%@&_+#P>5P[H#0._ M+#P>5YII`Q8!7.XO* MBA8B.^@;!,NX`0?K`[@!!E#H_0)8BCX>.XH.(#N*[HL6(CLZ[G4",L#H]@/+ MB]PVBE<&-HIW!/[*`A8@.W(7.A8B.W<1_LX"-B$[<@DZ-B,[=P/HP@+*!`#H MM0**PBH&(#O^P,OHJ0**QBH&(3O^P,N+W#:*1P2H\'0$)`\,@(`F'CMP"`8> M.\H"`(O<-HI'!"0'L032X(`F'CN/"`8>.\H"`(`F'COWRX`.'CL(RZ`H.Z(> M.\N+W#:+3P3C$XX&5``S_R:*':$D.S/2Z`4`XO;*`@`M`0"#V@!R!28Z'73S MPXO<-HM?!+C=-+H2`#O3-L5_!,=%`K#7QT4$@`"-A8``B44,C%T.QT40 M9P.,31+&13``'\H$`(O<'C;%?P2XGP.[?02+RX%]`K'7=`K'10*RU[A,!(O8 MB444C$T6B5T8C$T:B4T,\`?R@0`58OLQ'X&)HM5!$I*)HMU"";$?0PS MV\8&*3L`#NA<_[D!`#P(=#0\$W0P/`1T1$D\&W0G/`%T(SP&=#<\&G1&/`UT M3SP@=L"+\^N\"]MTN+`(Z(<`L"#H@@"P".A]`$OB MZNND.]YTH":*`3P@@"`+`*4U%2!E#H<@!8/`=T M*CP(="T\#70S/`IT-;0)BAX>.S+_N0$`4NAC`5K^PCH6(CMV((H6(#OK%[0. MZ$\!ZQ,Z%B`[=`W^RNL)BA8@.^L#Z`@`Z"T`!UI96\/^QCHV(SMV&/[.45*X M`0:*/AX[BPX@.XL6(COH%`%:6<.T`S+_Z0H!M`(R_^D#`1Z.'E0`BQ90`!^+ MVHOW)HH%/`=T(3P(="P\"G0U/`UT.4?^PCH6(CMV/.AN`.BA_XH6(#OK+.AB M`%%2N`<.Z,(`6EGK'.A3`#H6(#MT$_[*ZP_H1@#H>?_K!^@^`(H6(#M'B_>+ MVN*FZ#``'HX>5`")%E``BL;V)DH`,O8#PHO(BQ9C`+`.[NL`BL5"[NL`2K`/ M[NL`BL%"[A_#._=T8U%25QX&B\\KSAZ.'E0`BL?V)DH`,O\#P]'@B_B+%F,` M@\(&@#Y)``.P8?CL#\"MMT%JR*V.RH`77[^NRH M`73[B\.K^^+LZP:*YZRKXOP''U]:6<-65U4&S1`'75]>PP"Z$`*.VHP&2``S M[>AW#^B@`(O$!1,`L033Z(S2`\*C&@"C'``#!A0`HQX`HR@`HRP`HS0`C@9( M`":A`@"C,`#'!CH`U@",#CP`ORP]OCD"N1,`D/PNK+0US2&)'8Q%`H/'!.+O M'@X?N@P!N``ES2&Z$P&X(R7-(;K;`+@D)4+AC M`@Y0#NA.`@[HR`*X+#P>4!Y0N&,"#E`.Z#H"#NBY`LLSP)Q;@.T5,TAB^R`3A8!6%M96EY?71\'S[C0`(/$!NL#N,@`65OK![C_`#/) M,]NZ$`*.VONC0@"+P0O#=#VA(``+P'0OCL`FH1``"\!T&RO#=Q?WV#T`$',0 MNA``]^(#P7(')CL&"`!R!B:A%`#KT8O(C,,K'D@`@^L0B0Y$`(D>1@#$'CX` MC,`+PW03,\"C/@"C0`"C3`"X;@$.4`93R[@L.QY0#N@J`K@L/!Y0#N@A`K\L M/;XY`KD3`)#\+JRT)1[%%KN(``JS/`JZNKC45T MJXS`J[BS#*NX%@&K,\"Y#@#SJ[E/``O2=0FL.LAV!(K(XPBL"L!T`ZKB^#+` MJA_*"`"+W#;$?PHVBT<$)HE%!#:+1P8FB44,-HM'"":)10XSP":)10@FB44* MR@H`NK'7ZPBZLM?K`[JSUU6+[,1^!B:+10(]L==T$CVRUW0-/;#7=!#'!DP` M9@#K)%(&5P[H)0!:,\`FB54")HE%"":)10J[$`#H3`!T!B;'10*PUUW*!`"P M`.L"L`%5B^S$?@8F@7T"L==T&":!?0*RUW0(QP9,`&<`ZQA0NQ0`Z!4`6`K` M=`R['`#H"@`FQT4"L-==R@0`!E<&5R;_&0O`=`.C3`!?!\.+W!XVQ'\$)L55 M#":+300FBQVT/\TA-L1_!";%50PSR2:' M30@FBQVT0,TA<@(SP!_*!`"+W#;$?P0FBQV#^P1V!K0^S2%R`C/`R@0`@SY, M``!U-2:!?P*QUW4N)HMW""8[=PIT*QX&4U(FQ5<,)HM?"@<#V@/R_/_0*_*, MPEL''R:)=P@+P'4(P\<&3`!H`,-045)7!E/H,P%;!U]:65@FBW<()CMW"G6\ MPX,^3```=4`F@7\"LM=U.2:+3P0FBW\(*\\KT7,$`\HST@8FQ'<,`_ZP(/SS MJBO^!R:)?P@F.W\$=0E2!E/HX@!;!UH+TG7(P\<&3`!I`,.#/DP``'5()H%_ M`K+7=4$FBT\$)HM_""O/*\%S!`/(,\`>!E..VB;$7PP#^_SSI"O[6P6E@+P'7`P\<&3`!I`,-5B^S$7@:XNP4STNCN M_G4*)H-_&@!T`^AP`%W*!`"L/`UT##P:=!$[\W7SN+L%PSOS=`FL/`IT`4XS MP,.XT`7#58OLQ%X&N`(`OF``C-KH6/]U"B:#?QH`=`/H+0!=R@0`58OLQ%X& M)H-_&@!T"H,^3```=0/H$@!=R@0`!E,F_U\4"\!T`Z-,`,,&4R;_7Q@+P'0# MHTP`PU6+[,1>#+A8!HM.!HM^"(M6"D?H3OZ+Q\1^""O'2*I=R@8`K#P-=`\\ M&G0+JCOSX/+C!;A8!L-.,\##58OLQ%X()HH',N3$7@R+5@8KT'X%4.AN_E@+ MP'0*BW8(BU8*1NBN_EW*!@!5B^R#["#$7@:XTP:Y(`"-?N",TNCF_8O/C7[@ M*\]T#Q8'Z!4'<@+C"L<&3`!J`#/`B]"+Y5W+K#P@=Q$\&G08._-U\[C3!L.L M/"!V"ZH[\^#VXP6XY`;#3C/`PU6+[(/L((M&"(M6"HU^`!8'Z(X&Q%X,BU8& M*]%^!U%7Z-S]7UF+P8OWC-+H(/Z+Y5W*!@"Z,]*+W!XVQ'\(-L5W!/PSP*NX ML->K,\"Y%@#SJ[E/``O2=0FL.LAV!(K(XPBL"L!T`ZKB^#+`JA_*"`"@7@"T M/3/2ZP:X`#RZ`0!5B^S$?@@F@7T"L-=T&B:!?0*SUW0(QP9,`&8`ZS104@97 M#NA,`%I8)H!],`!T$AZ-53`&'S/)S2$?4L56!B:+300FBQW-(5H?<@8[P70%B\*C M3`!=R@0`LS^Y9`#K!;-`N64`58OLQ'X0Z*;_=3^+1@H+P'0<'E$F]V4$B\C% M5@R*XR:+'L<.T8*=!>)#DP`ZQ&C M3`#$?@:,P@O7=`4SP":)!5W*#@!5B^S$?@KH2O]U(8M&"";W902+R(M&!B;W M900#RHO0)HL=N`!"S2%S`Z-,`%W*"`!5B^R+5@8+TG0%Z$D`ZS"T,,TA/`.X M``!R)8X&2``FC@8L`#/__"8Z!70'N?__\J[K](/'`XOWN0`!\JZ1]M`>!A_$ M?@C\JI'SI!]=R@(`,]+H`@"3RXX&2`"_@``FB@TR[4`09@^LT!!FP>$09@^LV1!T7F:99O?Y9HO*9@^DPA!F#Z3+$,M5,^T+ MTGD(1??8@](`]]H+VW0^>0M%1??9@],`]]MT,U6+\8O[,]N+RHO0,\"]$`#1 MX-'2T='1TT`KSAO?H0RX/A'W0&T>K1V.+ZRX`^7``"(0B]!FT^*+PF;!ZA#+@^$?=`;1 MX-'2XOK+_(O+V8O*2?.F=`Z+ M^(O+BW8*1NOF,\#K!$@K1@8?7X`0!0BT8(2%`.Z%C^C;X` M_A97Q'X*!E>+1@@#1@90N/\`4`[H/OX.Z'O^Q'X*!E>X_P!0#N@)_HOE7`'#^<-'273Z)HH=@/MA M<@.`ZR"`ZSJ`PPIR"X#K%X##!G/)@,,*MP31X-'2B_<6'\1^"(M6!HM&##O" M?@*+PCO*?@*+RCO!?0*+P?RJ*\%T"%&+R+`@\ZI9\Z0?B^5=R@P`58OLQ'X* M)HH-,NU'XPDF@#T@=0-'XO?H]/YR`N,)B\\K3@HSP#/2Q'X&)HD-7Y>#TKS]'I,\#\\ZO#```````````````P,3(S-#4V-S@Y04)# M1$5&````````````````````````__\````````````````````````````` M```````````````````````````````00```H`"P`+@```(`#0H````````` '```````````` ` end The TI-based decoder source : zcp.asm ------------------------------------- ;--- ;--- ZCP decoding routine for ZShell 4.0 ;--- original by Stephane Jantzen - 12/16/1995 ;--- ;--- This version by Pascal Bouron - 02/11/96 ;--- ;--- Please report all bugs to : ;--- Bouron@YOKO.ENS-cachan.fr, or ;--- Stephane.Jantzen@scinfo.u-nancy.fr ;--- #include "ti-85.h" .org $00 .db "ZCP decoder v2.0",0 Start: DI ld HL,$FFFF xor A ld (HL),A ld DE,$FFFE ld BC,$03FF lddr exx ld HL,(PROGRAM_ADDR) ld DE,ZCP add HL,DE ld C,$80 Loop: ld A,(HL) inc HL ld D,A or A jr Z,EndDecode rlca jr C,Copy Stream: ld A,D and $3F ld B,A ld A,D and $40 StreamLoop: or A jr Z,SLSuite ex AF,AF' ld A,C exx or (HL) ld (HL),A exx ex AF,AF' SLSuite: srl C jr NC,DjnzSL exx inc HL exx ld C,$80 DjnzSL: djnz StreamLoop jr Loop Copy: ld B,$07 CopyLoop: rlca jr NC,CLSuite ex AF,AF' ld A,C exx or (HL) ld (HL),A exx ex AF,AF' CLSuite: srl C jr NC,DjnzCL exx inc HL exx ld C,$80 DjnzCL: djnz CopyLoop jr Loop EndDecode: call GET_KEY or A jr Z,EndDecode exx EI ret .end --