1 /***********************************************************************
2 This file is part of HA, a general purpose file archiver.
3 Copyright (C) 1995 Harri Hirvola
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 ************************************************************************
19 HA arithmetic coder
20 ***********************************************************************/
21
22 /***********************************************************************
23 This file contains some small changes made by Nico de Vries (AIP-NL)
24 allowing it to be compiled with Borland C++ 3.1.
25 ***********************************************************************/
26
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include "ha.h"
31 #include "haio.h"
32 #include "acoder.h"
33
34 static U16B h,l,v;
35 static S16B s;
36 static S16B gpat,ppat;
37
38 /***********************************************************************
39 Bit I/O
40 ***********************************************************************/
41
42 #define putbit(b) { ppat<<=1; \
43 if (b) ppat|=1; \
44 if (ppat&0x100) { \
45 putbyte(ppat&0xff); \
46 ppat=1; \
47 } \
48 }
49
50
51 #define getbit(b) { gpat<<=1; \
52 if (!(gpat&0xff)) { \
53 gpat=getbyte(); \
54 if (gpat&0x100) gpat=0x100; \
55 else { \
56 gpat<<=1; \
57 gpat|=1; \
58 } \
59 } \
60 b|=(gpat&0x100)>>8; \
61 }
62
63
64 /***********************************************************************
65 Arithmetic encoding
66 ***********************************************************************/
67
68 #ifndef __BORLANDC__
69
ac_out(U16B low,U16B high,U16B tot)70 void ac_out(U16B low, U16B high, U16B tot) {
71
72 register U32B r;
73
74 r=(U32B)(h-l)+1;
75 h=(U16B)(r*high/tot-1)+l;
76 l+=(U16B)(r*low/tot);
77 if (!((h^l)&0x8000)) {
78 putbit(l&0x8000);
79 while(s) {
80 --s;
81 putbit(~l&0x8000);
82 }
83 l<<=1;
84 h<<=1;
85 h|=1;
86 while (!((h^l)&0x8000)) {
87 putbit(l&0x8000);
88 l<<=1;
89 h<<=1;
90 h|=1;
91 }
92 }
93 while ((l&0x4000)&&!(h&0x4000)) {
94 ++s;
95 l<<=1;
96 l&=0x7fff;
97 h<<=1;
98 h|=0x8001;
99 }
100 }
101
102 #else
103
ac_out(U16B low,U16B high,U16B tot)104 void ac_out(U16B low, U16B high, U16B tot) {
105
106 asm {
107 mov ax,h
108 mov bx,l
109 sub ax,bx
110 add ax,1
111 mov cx,ax
112 jc aco0
113 mul high
114 jmp aco1
115 }
116 aco0:
117 asm {
118 mov dx,high
119 }
120 aco1:
121 asm {
122 cmp dx,tot
123 je aco2
124 div tot
125 sub ax,1
126 jmp aco3
127 }
128 aco2:
129 asm {
130 mov ax,0xffff
131 }
132 aco3:
133 asm {
134 add ax,bx
135 mov h,ax
136 mov ax,cx
137 cmp ax,0
138 je aco4
139 mul low
140 jmp aco5
141 }
142 aco4:
143 asm {
144 mov dx,low
145 }
146 aco5:
147 asm {
148 div tot
149 add l,ax
150 }
151 if (!((h^l)&0x8000)) {
152 putbit(l&0x8000);
153 while(s) {
154 --s;
155 putbit(~l&0x8000);
156 }
157 l<<=1;
158 h<<=1;
159 h|=1;
160 while (!((h^l)&0x8000)) {
161 putbit(l&0x8000);
162 l<<=1;
163 h<<=1;
164 h|=1;
165 }
166 }
167 while ((l&0x4000)&&!(h&0x4000)) {
168 ++s;
169 l<<=1;
170 l&=0x7fff;
171 h<<=1;
172 h|=0x8001;
173 }
174 }
175
176 #endif
177
ac_init_encode(void)178 void ac_init_encode(void) {
179
180 h=0xffff;
181 l=s=0;
182 ppat=1;
183 }
184
ac_end_encode(void)185 void ac_end_encode(void) {
186
187 ++s;
188 putbit(l&0x4000);
189 while (s--) {
190 putbit(~l&0x4000);
191 }
192 if (ppat==1) {
193 flush();
194 return;
195 }
196 while(!(ppat&0x100)) ppat<<=1;
197 putbyte(ppat&0xff);
198 flush();
199 }
200
201
202 /***********************************************************************
203 Arithmetic decoding
204 ***********************************************************************/
205
206 #ifndef __BORLANDC__
207
ac_in(U16B low,U16B high,U16B tot)208 void ac_in(U16B low, U16B high, U16B tot) {
209
210 register U32B r;
211
212 r=(U32B)(h-l)+1;
213 h=(U16B)(r*high/tot-1)+l;
214 l+=(U16B)(r*low/tot);
215 while (!((h^l)&0x8000)) {
216 l<<=1;
217 h<<=1;
218 h|=1;
219 v<<=1;
220 getbit(v);
221 }
222 while ((l&0x4000)&&!(h&0x4000)) {
223 l<<=1;
224 l&=0x7fff;
225 h<<=1;
226 h|=0x8001;
227 v<<=1;
228 v^=0x8000;
229 getbit(v);
230 }
231 }
232
ac_threshold_val(U16B tot)233 U16B ac_threshold_val(U16B tot) {
234
235 register U32B r;
236
237 r=(U32B)(h-l)+1;
238 return (U16B)((((U32B)(v-l)+1)*tot-1)/r);
239 }
240
241 #else
242
ac_in(U16B low,U16B high,U16B tot)243 void ac_in(U16B low, U16B high, U16B tot) {
244
245 asm {
246 mov ax,h
247 mov bx,l
248 sub ax,bx
249 add ax,1
250 mov cx,ax
251 jc aci0
252 mul high
253 jmp aci1
254 }
255 aci0:
256 asm {
257 mov dx,high
258 }
259 aci1:
260 asm {
261 cmp dx,tot
262 je aci2
263 div tot
264 sub ax,1
265 jmp aci3
266 }
267 aci2:
268 asm {
269 mov ax,0xffff
270 }
271 aci3:
272 asm {
273 add ax,bx
274 mov h,ax
275 mov ax,cx
276 cmp ax,0
277 je aci4
278 mul low
279 jmp aci5
280 }
281 aci4:
282 asm {
283 mov dx,low
284 }
285 aci5:
286 asm {
287 div tot
288 add l,ax
289 }
290 while (!((h^l)&0x8000)) {
291 l<<=1;
292 h<<=1;
293 h|=1;
294 v<<=1;
295 getbit(v);
296 }
297 while ((l&0x4000)&&!(h&0x4000)) {
298 l<<=1;
299 l&=0x7fff;
300 h<<=1;
301 h|=0x8001;
302 v<<=1;
303 v^=0x8000;
304 getbit(v);
305 }
306 }
307
ac_threshold_val(U16B tot)308 U16B ac_threshold_val(U16B tot) {
309
310 U16B rv;
311
312 asm {
313 mov ax,h
314 sub ax,l
315 add ax,1
316 jc atv1
317 mov cx,ax
318 mov ax,v
319 sub ax,l
320 inc ax
321 mul [tot]
322 sub ax,1
323 sbb dx,0
324 div cx
325 mov rv,ax
326 jmp atv3
327 }
328 atv1:
329 asm {
330 mov ax,v
331 sub ax,l
332 add ax,1
333 jc atv2
334 mul [tot]
335 sub ax,1
336 sbb dx,0
337 mov rv,dx
338 jmp atv3
339 }
340 atv2:
341 asm {
342 mov ax,tot
343 dec ax
344 mov rv,dx
345 }
346 atv3:
347 return rv;
348 }
349
350 #endif
351
ac_init_decode(void)352 void ac_init_decode(void) {
353
354 h=0xffff;
355 l=0;
356 gpat=0;
357 v=getbyte()<<8;
358 v|=0xff&getbyte();
359 }
360
361