summaryrefslogtreecommitdiffstats
path: root/private/rpc/install/compress/unpack.asm
blob: 73b602e20ccb9c914fd2fe8972cf1deaf0c396d0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
; This module implements an lz unpacking function.
;
;			   (C) Microsoft Corperation
;			Written by Steven Zeck May 1989


.model small,c

cBufMax equ 4096
cStrMax equ 18
cbIndex equ 2

.data
    ; The following sets of pointers provide input and output buffers
    ; The ??End pointers are the end points of the buffers.  When
    ; the current buffer point equals this value, functions must be
    ; called to flush, read more data.

    extrn pOutBuff:dWord, pOutBuffEnd:dWord
    extrn pInBuff:dWord, pInBuffEnd:dWord

    extrn cbExpanded:dWord	; expanded file size, set by caller to unpack
    extrn ringBuf:byte		; byte buffer of cBufMax size

.code
    ; Functions to read data into pInBuff, and write to pOutBuff.
    ;
    ; readInBuff returns the next character in AL and resets pInBuff.
    ;
    ; writeOutBuff writes the buffer bounded by pOutBuff and the beginning
    ; of the buffer (initial pOutBuff).  It also resets pOutBuff.

    extrn readInBuff:proc, writeOutBuff:Proc

unpack proc uses si di
    local cbOut:dWord

    ; register useage:
    ;
    ;	    dx - flags
    ;	    es:si - pInBuff
    ;	    es:di - pOutBuff
    ;	    bx - iBuffCur, pointer to ringBuff

    xor     ax,ax
    mov     word ptr (cbOut),ax
    mov     word ptr (cbOut).2,ax
    mov     dx,ax
    mov     bx, cBufMax - cStrMax

    mov     ax, "  "			; initial ringBuf to blanks
    push    ds
    pop     es
    mov     di, offset ringBuf
    mov     cx, (cBufMax - cStrMax)/2
    rep     stosw

    les     si,pInBuff			; pInBuff and pOutBuff are based
    mov     di,word ptr pOutBuff
;
;	pOutBuff must be incremented initially to simulate the
;	effect of calls to writeOutBuff.  After flushing the buffer,
;	writeOutBuff does the following, leaving pOutBuff incremented:
;
;		pOutBuff = pCopyBuff2;
;		*pOutBuff++ = c;
;
    inc     word ptr pOutBuff		; Very tricky -- confer with IO.C
    jmp     decodeChar

@@:
    push    bx
    call    readInBuff
    pop     bx
    mov     dx,si
    les     si,pInBuff
    jmp     fromReloadInBuff

reloadInBuff:

    mov     si,di			; if (cbOut + byteInCurrent record >=
    sub     si,word ptr pOutBuff	;    cbExpanded)
    inc     si				; return -- done
    mov     ax,word ptr (cbOut)
    add     ax,si
    mov     si,dx

    mov     dx,word ptr (cbOut).2	; AX:DX -> bytes written
    adc     dx,0

    cmp     dx,word ptr cbExpanded.2
    jb	    @B
    ja	    exit
    cmp     ax,word ptr cbExpanded
    jb	    @B
exit:
    mov     word ptr pOutBuff,di
    ret

@@:
    mov     si,dx
    push    bx
    call    readInBuff
    pop     bx
    mov     dx,si
    les     si,pInBuff
    jmp     short fromGetFlagWord

getFlagWord:			      ; process char as a flag byte
    mov     dh,0ffh
    mov     dl,al		      ; flag = 0ff | char

    cmp     si, word ptr pInBuffEnd
    jae     @B
    lods    byte ptr es:[si]

    test    dl,1
    jz	    putString

addChar:			      ; process char as literal character

    mov     [bx].ringBuf,al	      ; ringBuff[bx] = char
    inc     bx
    and     bh,0fh		      ; bx = bx+1 % cBufMax

    cmp     di, word ptr pOutBuffEnd
    jae     writeOutBuff1
    stos    byte ptr es:[di]	      ; writeChar(char)

decodeChar:

    cmp     si, word ptr pInBuffEnd   ; al = char = readChar()
    jae     reloadInBuff
    lods    byte ptr es:[si]

fromReloadInBuff:
    shr     dx,1		      ; flag >>= 1
    or	    dh,dh
    jz	    getFlagWord 	      ; if high byte 0, then al is flag byte

fromGetFlagWord:
    test    dl,1
    jnz     addChar		      ; if (flag&1) procss as single character

putString:
				      ; char & next byte form string index & count
    mov     cl,al
    cmp     si, word ptr pInBuffEnd
    jae     reloadInBuff1
    lods    byte ptr es:[si]	      ; al = readChar()

fromReloadInBuff1:
    push    si

    xchg    al,cl		      ; cx = cb = char
    xor     ah,ah		      ; compute ring index to SI
    mov     si,ax		      ; si = (cb&0f0 << 4) | char
    mov     al,cl
    and     al,0f0h
    shl     ax,1
    shl     ax,1
    shl     ax,1
    shl     ax,1

    or	    si,ax

    and     cx,0fh		      ; cx = cb = (cb&0fh) + 3
    add     cl,3

putStringChar:
    mov     al, byte ptr [si].ringBuf ; al = ringBuf[si]
    inc     si
    and     si,0fffh
				      ; si = si+1 % cBufMax
    cmp     di, word ptr pOutBuffEnd
    jae     writeOutBuff2
    stosb			      ; writeChar(al)

fromWriteOutBuff2:
    mov     [bx].ringBuf,al	      ; ringBug[bx] = al
    inc     bx
    and     bh,0fh		      ; bx = bx+1 % cBufMax
    loop    putStringChar	      ; while(--cb)

    pop     si
    jmp     decodeChar

; The following are out of line functions to reading and writing into the
; input and output buffers

reloadInBuff1:

    push    cx
    push    bx
    mov     si,dx
    call    readInBuff
    pop     bx
    pop     cx

    mov     dx,si
    les     si,pInBuff
    jmp     fromReloadInBuff1

writeOutBuff1:

    mov     word ptr pOutBuff,di

    push    di
    push    bx
    push    ax
    mov     di,dx
    call    writeOutBuff
    pop     ax
    pop     bx
    mov     dx,di
    les     di,pOutBuff

    pop     cx
    sub     cx,di			; cbOut += sizeof buffer written
    inc     cx				; increment ONCE to get size
    add     word ptr (cbOut),cx
    adc     word ptr (cbOut).2,0

    jmp     decodeChar

writeOutBuff2:

    push    cx
    push    di
    mov     word ptr pOutBuff,di

    mov     di,dx
    push    bx
    push    ax				; write wants a character on stack
    call    writeOutBuff
    mov     dx,di
    pop     ax
    pop     bx
    les     di,pOutBuff

    pop     cx
    sub     cx,di			; cbOut += sizeof buffer written
    inc     cx				; increment ONCE to get size
    add     word ptr (cbOut),cx
    adc     word ptr (cbOut).2,0

    pop     cx
    jmp     short fromWriteOutBuff2

unpack endp

    end