CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

XORDELTA.ASM (18679B)


      1 ;
      2 ; Copyright 2020 Electronic Arts Inc.
      3 ;
      4 ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 ; software: you can redistribute it and/or modify it under the terms of 
      6 ; the GNU General Public License as published by the Free Software Foundation, 
      7 ; either version 3 of the License, or (at your option) any later version.
      8 
      9 ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 ; in the hope that it will be useful, but with permitted additional restrictions 
     11 ; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 ; distributed with this program. You should have received a copy of the 
     13 ; GNU General Public License along with permitted additional restrictions 
     14 ; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.
     15 
     16 ; **************************************************************************
     17 ; **   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   *
     18 ; **************************************************************************
     19 ; *                                                                        *
     20 ; *                 Project Name : WSA Support routines			   *
     21 ; *                                                                        *
     22 ; *                    File Name : XORDELTA.ASM                            *
     23 ; *                                                                        *
     24 ; *                   Programmer : Scott K. Bowen			   *
     25 ; *                                                                        *
     26 ; *                  Last Update :May 23, 1994   [SKB]                     *
     27 ; *                                                                        *
     28 ; *------------------------------------------------------------------------*
     29 ; * Functions:                                                             *
     30 ;*   Apply_XOR_Delta -- Apply XOR delta data to a buffer.                  *
     31 ;*   Apply_XOR_Delta_To_Page_Or_Viewport -- Calls the copy or the XOR funti*
     32 ;*   Copy_Delta_buffer -- Copies XOR Delta Data to a section of a page.    *
     33 ;*   XOR_Delta_Buffer -- Xor's the data in a XOR Delta format to a page.   *
     34 ; * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*
     35 
     36 ;IDEAL
     37 ;P386
     38 ;MODEL USE32 FLAT
     39 .model flat
     40 
     41 
     42 
     43 ;LOCALS ??
     44 
     45 ; These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter.  If
     46 ; These change, make sure and change their values in wsa.cpp.
     47 DO_XOR		equ	0
     48 DO_COPY		equ	1
     49 TO_VIEWPORT	equ	0
     50 TO_PAGE		equ	2
     51 
     52 ;
     53 ; Routines defined in this module
     54 ;
     55 ;
     56 ; UWORD Apply_XOR_Delta(UWORD page_seg, BYTE *delta_ptr);
     57 ; PUBLIC Apply_XOR_Delta_To_Page_Or_Viewport(UWORD page_seg, BYTE *delta_ptr, WORD width, WORD copy)
     58 ;
     59 ;	PROC	C XOR_Delta_Buffer
     60 ;	PROC	C Copy_Delta_Buffer
     61 ;
     62 
     63 externdef C Apply_XOR_Delta:NEAR
     64 externdef C Apply_XOR_Delta_To_Page_Or_Viewport:NEAR
     65 
     66 
     67 
     68 	;CODESEG
     69 	.code
     70 
     71 
     72 ;***************************************************************************
     73 ;* APPLY_XOR_DELTA -- Apply XOR delta data to a linear buffer.             *
     74 ;*   AN example of this in C is at the botton of the file commented out.   *
     75 ;*                                                                         *
     76 ;* INPUT:  BYTE *target - destination buffer.                              *
     77 ;*         BYTE *delta - xor data to be delta uncompress.                  *
     78 ;*                                                                         *
     79 ;* OUTPUT:                                                                 *
     80 ;*                                                                         *
     81 ;* WARNINGS:                                                               *
     82 ;*                                                                         *
     83 ;* HISTORY:                                                                *
     84 ;*   05/23/1994 SKB : Created.                                             *
     85 ;*=========================================================================*
     86 Apply_XOR_Delta proc C public USES ebx ecx edx esi edi target:DWORD, delta:DWORD
     87 	
     88 	;USES 	ebx,ecx,edx,edi,esi
     89 	;ARG	target:DWORD 		; pointers.
     90 	;ARG	delta:DWORD		; pointers.
     91 
     92 	; Optimized for 486/pentium by rearanging instructions.
     93 	mov	edi,[target]		; get our pointers into offset registers.
     94 	mov	esi,[delta]
     95 
     96 	cld				; make sure we go forward
     97 	xor	ecx,ecx			; use cx for loop
     98 
     99 top_loop:
    100 	xor	eax,eax			; clear out eax.
    101 	mov	al,[esi]		; get delta source byte
    102 	inc	esi
    103 
    104 	test	al,al			; check for a SHORTDUMP ; check al incase of sign value.
    105 	je	short_run
    106 	js	check_others
    107 
    108 ;
    109 ; SHORTDUMP
    110 ;
    111 	mov	ecx,eax			; stick count in cx
    112 
    113 dump_loop:
    114 	mov	al,[esi]		;get delta XOR byte
    115 	xor	[edi],al		; xor that byte on the dest
    116 	inc	esi
    117 	inc	edi
    118 	dec	ecx
    119 	jnz	dump_loop
    120 	jmp	top_loop
    121 
    122 ;
    123 ; SHORTRUN
    124 ;
    125 
    126 short_run:
    127 	mov	cl,[esi]		; get count
    128 	inc	esi			; inc delta source
    129 
    130 do_run:
    131 	mov	al,[esi]		; get XOR byte
    132 	inc	esi
    133 
    134 run_loop:
    135 	xor	[edi],al		; xor that byte.
    136 
    137 	inc	edi			; go to next dest pixel
    138 	dec	ecx			; one less to go.
    139 	jnz	run_loop
    140 	jmp	top_loop
    141 
    142 ;
    143 ; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP
    144 ;
    145 
    146 check_others:
    147 	sub	eax,080h		; opcode -= 0x80
    148 	jnz	do_skip		; if zero then get next word, otherwise use remainder.
    149 
    150 	mov	ax,[esi]
    151 	lea	esi,[esi+2]		; get word code in ax
    152 	test	ax,ax			; set flags. (not 32bit register so neg flag works)
    153 	jle	not_long_skip
    154 
    155 ;
    156 ; SHORTSKIP AND LONGSKIP
    157 ;
    158 do_skip:
    159 	add	edi,eax			; do the skip.
    160 	jmp	top_loop
    161 
    162 
    163 not_long_skip:
    164 	jz	stop			; long count of zero means stop
    165 	sub	eax,08000h     		; opcode -= 0x8000
    166 	test	eax,04000h		; is it a LONGRUN (code & 0x4000)?
    167 	je	long_dump
    168 
    169 ;
    170 ; LONGRUN
    171 ;
    172 	sub	eax,04000h		; opcode -= 0x4000
    173 	mov	ecx,eax			; use cx as loop count
    174 	jmp	do_run		; jump to run code.
    175 
    176 
    177 ;
    178 ; LONGDUMP
    179 ;
    180 
    181 long_dump:
    182 	mov	ecx,eax			; use cx as loop count
    183 	jmp	dump_loop		; go to the dump loop.
    184 
    185 stop:
    186 
    187 	ret
    188 
    189 Apply_XOR_Delta endp
    190 
    191 
    192 ;----------------------------------------------------------------------------
    193 
    194 
    195 ;***************************************************************************
    196 ;* APPLY_XOR_DELTA_To_Page_Or_Viewport -- Calls the copy or the XOR funtion.           *
    197 ;*                                                                         *
    198 ;*									   *
    199 ;* 	This funtion is call to either xor or copy XOR_Delta data onto a   *
    200 ;*	page instead of a buffer.  The routine will set up the registers   *
    201 ;*	need for the actual routines that will perform the copy or xor.	   *
    202 ;*									   *
    203 ;*	The registers are setup as follows :				   *
    204 ;*		es:edi - destination segment:offset onto page.		   *
    205 ;*		ds:esi - source buffer segment:offset of delta data.	   *
    206 ;*		dx,cx,ax - are all zeroed out before entry.		   *
    207 ;*                                                                         *
    208 ;* INPUT:                                                                  *
    209 ;*                                                                         *
    210 ;* OUTPUT:                                                                 *
    211 ;*                                                                         *
    212 ;* WARNINGS:                                                               *
    213 ;*                                                                         *
    214 ;* HISTORY:                                                                *
    215 ;*   03/09/1992  SB : Created.                                             *
    216 ;*=========================================================================*
    217 
    218 
    219 Apply_XOR_Delta_To_Page_Or_Viewport proc C public USES ebx ecx edx esi edi target:DWORD, delta:DWORD, xwidth:DWORD, nextrow:DWORD, copy:DWORD
    220 
    221 	;USES 	ebx,ecx,edx,edi,esi
    222 	;ARG	target:DWORD		; pointer to the destination buffer.
    223 	;ARG	delta:DWORD		; pointer to the delta buffer.
    224 	;ARG	width:DWORD		; width of animation.
    225 	;ARG	nextrow:DWORD		; Page/Buffer width - anim width.
    226 	;ARG	copy:DWORD		; should it be copied or xor'd?
    227 
    228 
    229 	mov	edi,[target]		; Get the target pointer.
    230 	mov	esi,[delta]		; Get the destination pointer.
    231 
    232 	xor	eax,eax			; clear eax, later put them into ecx and edx.
    233 
    234 	cld				; make sure we go forward
    235 
    236 	mov	ebx,[nextrow]		; get the amount to add to get to next row from end.  push it later...
    237 
    238 	mov	ecx,eax			; use cx for loop
    239 	mov	edx,eax			; use dx to count the relative column.
    240 
    241 	push	ebx			; push nextrow onto the stack for Copy/XOR_Delta_Buffer.
    242 	mov	ebx,[xwidth]		; bx will hold the max column for speed compares
    243 
    244 ; At this point, all the registers have been set up.  Now call the correct function
    245 ; to either copy or xor the data.
    246 
    247 	cmp	[copy],DO_XOR		; Do we want to copy or XOR
    248 	je	xorfunct		; Jump to XOR if not copy
    249 	call	Copy_Delta_Buffer	; Call the function to copy the delta buffer.
    250 	jmp	didcopy		; jump past XOR
    251 xorfunct:
    252 	call	XOR_Delta_Buffer	; Call funtion to XOR the deltat buffer.
    253 didcopy:
    254 	pop	ebx			; remove the push done to pass a value.
    255 
    256 	ret
    257 
    258 Apply_XOR_Delta_To_Page_Or_Viewport ENDP
    259 ;----------------------------------------------------------------------------
    260 
    261 
    262 ;***************************************************************************
    263 ;* XOR_DELTA_BUFFER -- Xor's the data in a XOR Delta format to a page.     *
    264 ;*	This will only work right if the page has the previous data on it. *
    265 ;*	This function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport.   *
    266 ;*      The registers must be setup as follows :                           *
    267 ;*                                                                         *
    268 ;* INPUT:                                                                  *
    269 ;*	es:edi - destination segment:offset onto page.		 	   *
    270 ;*	ds:esi - source buffer segment:offset of delta data.	 	   *
    271 ;*	edx,ecx,eax - are all zeroed out before entry.		 	   *
    272 ;*                                                                         *
    273 ;* OUTPUT:                                                                 *
    274 ;*                                                                         *
    275 ;* WARNINGS:                                                               *
    276 ;*                                                                         *
    277 ;* HISTORY:                                                                *
    278 ;*   03/09/1992  SB : Created.                                             *
    279 ;*=========================================================================*
    280 
    281 XOR_Delta_Buffer proc C nextrow:DWORD
    282 
    283 top_loop2:
    284 	xor	eax,eax			; clear out eax.
    285 	mov	al,[esi]		; get delta source byte
    286 	inc	esi
    287 
    288 	test	al,al			; check for a SHORTDUMP ; check al incase of sign value.
    289 	je	short_run2
    290 	js	check_others2
    291 
    292 ;
    293 ; SHORTDUMP
    294 ;
    295 	mov	ecx,eax			; stick count in cx
    296 
    297 dump_loop2:
    298 	mov	al,[esi]		; get delta XOR byte
    299 	xor	[edi],al		; xor that byte on the dest
    300 	inc	esi
    301 	inc	edx			; increment our count on current column
    302 	inc	edi
    303 	cmp	edx,ebx			; are we at the final column
    304 	jne	end_col1		; if not the jmp over the code
    305 
    306 	sub	edi,edx			; get our column back to the beginning.
    307 	xor	edx,edx			; zero out our column counter
    308 	add	edi,[nextrow]		; jump to start of next row
    309 end_col1:
    310 
    311 	dec	ecx
    312 	jnz	dump_loop2
    313 	jmp	top_loop2
    314 
    315 ;
    316 ; SHORTRUN
    317 ;
    318 
    319 short_run2:
    320 	mov	cl,[esi]		; get count
    321 	inc	esi			; inc delta source
    322 
    323 do_run2:
    324 	mov	al,[esi]		; get XOR byte
    325 	inc	esi
    326 
    327 run_loop2:
    328 	xor	[edi],al		; xor that byte.
    329 
    330 	inc	edx			; increment our count on current column
    331 	inc	edi			; go to next dest pixel
    332 	cmp	edx,ebx			; are we at the final column
    333 	jne	end_col2		; if not the jmp over the code
    334 
    335 	sub	edi,ebx			; get our column back to the beginning.
    336 	xor	edx,edx			; zero out our column counter
    337 	add	edi,[nextrow]		; jump to start of next row
    338 end_col2:
    339 
    340 
    341 	dec	ecx
    342 	jnz	run_loop2
    343 	jmp	top_loop2
    344 
    345 ;
    346 ; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP
    347 ;
    348 
    349 check_others2:
    350 	sub	eax,080h		; opcode -= 0x80
    351 	jnz	do_skip2		; if zero then get next word, otherwise use remainder.
    352 
    353 	mov	ax,[esi]		; get word code in ax
    354 	lea	esi,[esi+2]
    355 	test	ax,ax			; set flags. (not 32bit register so neg flag works)
    356 	jle	not_long_skip2
    357 
    358 ;
    359 ; SHORTSKIP AND LONGSKIP
    360 ;
    361 do_skip2:
    362 	sub	edi,edx			; go back to beginning or row.
    363 	add	edx,eax			; incriment our count on current row
    364 recheck2:
    365 	cmp	edx,ebx			; are we past the end of the row
    366 	jb	end_col3  		; if not the jmp over the code
    367 
    368 	sub	edx,ebx			; Subtract width from the col counter
    369 	add	edi,[nextrow]  		; jump to start of next row
    370 	jmp	recheck2		; jump up to see if we are at the right row
    371 end_col3:
    372 	add	edi,edx			; get to correct position in row.
    373 	jmp	top_loop2
    374 
    375 
    376 not_long_skip2:
    377 	jz	stop2			; long count of zero means stop
    378 	sub	eax,08000h     		; opcode -= 0x8000
    379 	test	eax,04000h		; is it a LONGRUN (code & 0x4000)?
    380 	je	long_dump2
    381 
    382 ;
    383 ; LONGRUN
    384 ;
    385 	sub	eax,04000h		; opcode -= 0x4000
    386 	mov	ecx,eax			; use cx as loop count
    387 	jmp	do_run2		; jump to run code.
    388 
    389 
    390 ;
    391 ; LONGDUMP
    392 ;
    393 
    394 long_dump2:
    395 	mov	ecx,eax			; use cx as loop count
    396 	jmp	dump_loop2		; go to the dump loop.
    397 
    398 stop2:
    399 
    400 	ret
    401 
    402 
    403 XOR_Delta_Buffer	ENDP	
    404 
    405 ;----------------------------------------------------------------------------
    406 
    407 
    408 ;***************************************************************************
    409 ;* COPY_DELTA_BUFFER -- Copies XOR Delta Data to a section of a page.      *
    410 ;*	This function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport.   *
    411 ;*      The registers must be setup as follows :                           *
    412 ;*                                                                         *
    413 ;* INPUT:                                                                  *
    414 ;*	es:edi - destination segment:offset onto page.		 	   *
    415 ;*	ds:esi - source buffer segment:offset of delta data.	 	   *
    416 ;*	dx,cx,ax - are all zeroed out before entry.		 	   *
    417 ;*                                                                         *
    418 ;* OUTPUT:                                                                 *
    419 ;*                                                                         *
    420 ;* WARNINGS:                                                               *
    421 ;*                                                                         *
    422 ;* HISTORY:                                                                *
    423 ;*   03/09/1992  SB : Created.                                             *
    424 ;*=========================================================================*
    425 Copy_Delta_Buffer proc C nextrow:DWORD
    426 
    427 	;ARG	nextrow:DWORD
    428 
    429 top_loop3:
    430 	xor	eax,eax			; clear out eax.
    431 	mov	al,[esi]		; get delta source byte
    432 	inc	esi
    433 
    434 	test	al,al			; check for a SHORTDUMP ; check al incase of sign value.
    435 	je	short_run3
    436 	js	check_others3
    437 
    438 ;
    439 ; SHORTDUMP
    440 ;
    441 	mov	ecx,eax			; stick count in cx
    442 
    443 dump_loop3:
    444 	mov	al,[esi]		; get delta XOR byte
    445 
    446 	mov	[edi],al		; store that byte on the dest
    447 
    448 	inc	edx			; increment our count on current column
    449 	inc	esi
    450 	inc	edi
    451 	cmp	edx,ebx			; are we at the final column
    452 	jne	end_col1_3		; if not the jmp over the code
    453 
    454 	sub	edi,edx			; get our column back to the beginning.
    455 	xor	edx,edx			; zero out our column counter
    456 	add	edi,[nextrow]		; jump to start of next row
    457 end_col1_3:
    458 
    459 	dec	ecx
    460 	jnz	dump_loop3
    461 	jmp	top_loop3
    462 
    463 ;
    464 ; SHORTRUN
    465 ;
    466 
    467 short_run3:
    468 	mov	cl,[esi]		; get count
    469 	inc	esi			; inc delta source
    470 
    471 do_run3:
    472 	mov	al,[esi]		; get XOR byte
    473 	inc	esi
    474 
    475 run_loop3:
    476 	mov	[edi],al		; store the byte (instead of XOR against current color)
    477 
    478 	inc	edx			; increment our count on current column
    479 	inc	edi			; go to next dest pixel
    480 	cmp	edx,ebx			; are we at the final column
    481 	jne	end_col2_3		; if not the jmp over the code
    482 
    483 	sub	edi,ebx			; get our column back to the beginning.
    484 	xor	edx,edx			; zero out our column counter
    485 	add	edi,[nextrow]		; jump to start of next row
    486 end_col2_3:
    487 
    488 
    489 	dec	ecx
    490 	jnz	run_loop3
    491 	jmp	top_loop3
    492 
    493 ;
    494 ; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP
    495 ;
    496 
    497 check_others3:
    498 	sub	eax,080h		; opcode -= 0x80
    499 	jnz	do_skip3		; if zero then get next word, otherwise use remainder.
    500 
    501 	mov	ax,[esi]		; get word code in ax
    502 	lea	esi,[esi+2]
    503 	test	ax,ax			; set flags. (not 32bit register so neg flag works)
    504 	jle	not_long_skip3
    505 
    506 ;
    507 ; SHORTSKIP AND LONGSKIP
    508 ;
    509 do_skip3:
    510 	sub	edi,edx			; go back to beginning or row.
    511 	add	edx,eax			; incriment our count on current row
    512 recheck3:
    513 	cmp	edx,ebx			; are we past the end of the row
    514 	jb	end_col3_3  		; if not the jmp over the code
    515 
    516 	sub	edx,ebx			; Subtract width from the col counter
    517 	add	edi,[nextrow]  		; jump to start of next row
    518 	jmp	recheck3		; jump up to see if we are at the right row
    519 end_col3_3:
    520 	add	edi,edx			; get to correct position in row.
    521 	jmp	top_loop3
    522 
    523 
    524 not_long_skip3:
    525 	jz	stop3			; long count of zero means stop
    526 	sub	eax,08000h     		; opcode -= 0x8000
    527 	test	eax,04000h		; is it a LONGRUN (code & 0x4000)?
    528 	je	long_dump3
    529 
    530 ;
    531 ; LONGRUN
    532 ;
    533 	sub	eax,04000h		; opcode -= 0x4000
    534 	mov	ecx,eax			; use cx as loop count
    535 	jmp	do_run3		; jump to run code.
    536 
    537 
    538 ;
    539 ; LONGDUMP
    540 ;
    541 
    542 long_dump3:
    543 	mov	ecx,eax			; use cx as loop count
    544 	jmp	dump_loop3		; go to the dump loop.
    545 
    546 stop3:
    547 
    548 	ret
    549 
    550 Copy_Delta_Buffer	ENDP	
    551 
    552 ;----------------------------------------------------------------------------
    553 
    554 	END
    555 
    556 
    557 ;----------------------------------------------------------------------------
    558 ;
    559 ;PUBLIC UWORD Apply_XOR_Delta(UWORD page_seg, BYTE *delta_ptr)
    560 ;{
    561 ;
    562 ;	register UWORD loop;
    563 ;	BYTE opcode, xor_byte;
    564 ;	UWORD bytes_to_uncompress = 64000U;
    565 ;
    566 ;
    567 ;	/* Make our buffer pointer */
    568 ;
    569 ;	to    = MK_FP(page_seg, 0);
    570 ;	delta = Normalize_Pointer(delta_ptr);
    571 ;
    572 ;
    573 ;	while (bytes_to_uncompress) {
    574 ;
    575 ;		opcode = *delta++;
    576 ;
    577 ;
    578 ;		/* Check for SHORTDUMP */
    579 ;
    580 ;		if (opcode > 0) {
    581 ;
    582 ;
    583 ;			bytes_to_uncompress -= opcode;
    584 ;
    585 ;			for (loop = 0; loop < opcode; loop++) {
    586 ;				xor_byte = *delta++;
    587 ;				*to++ ^= xor_byte;
    588 ;			}
    589 ;			continue;
    590 ;		}
    591 ;
    592 ;		/* Check for SHORTRUN */
    593 ;
    594 ;		if (opcode == 0) {
    595 ;
    596 ;			word_count = *delta++;
    597 ;			xor_byte   = *delta++;
    598 ;
    599 ;			bytes_to_uncompress -= word_count;
    600 ;
    601 ;			for (loop = 0; loop < word_count; loop++) {
    602 ;				*to++ ^= xor_byte;
    603 ;			}
    604 ;			continue;
    605 ;		}
    606 ;
    607 ;		/* By now, we know it must be a LONGDUMP, SHORTSKIP, or LONGSKIP */
    608 ;
    609 ;		opcode -= 0x80;
    610 ;
    611 ;
    612 ;		/* Is it a SHORTSKIP? */
    613 ;
    614 ;		if (opcode != 0) {
    615 ;
    616 ;			to += opcode;
    617 ;			bytes_to_uncompress -= (WORD) opcode;
    618 ;			continue;
    619 ;		}
    620 ;
    621 ;
    622 ;		word_count = *((UWORD *) delta)++;
    623 ;
    624 ;		/* Is it a LONGSKIP? */
    625 ;
    626 ;		if ((WORD) word_count > 0) {
    627 ;
    628 ;			to += word_count;
    629 ;			bytes_to_uncompress -= (WORD) word_count;
    630 ;			continue;
    631 ;		}
    632 ;
    633 ;
    634 ;		word_count -= 0x8000;
    635 ;
    636 ;		/* Is it a LONGRUN? */
    637 ;
    638 ;		if (word_count & 0x4000) {
    639 ;
    640 ;			word_count -= 0x4000;
    641 ;
    642 ;			bytes_to_uncompress -= word_count;
    643 ;
    644 ;			xor_byte = *delta++;
    645 ;
    646 ;			for (loop = 0; loop < word_count; loop++) {
    647 ;				*to++ ^= xor_byte;
    648 ;			}
    649 ;			continue;
    650 ;		}
    651 ;
    652 ;
    653 ;		/* It must be a LONGDUMP */
    654 ;
    655 ;		bytes_to_uncompress -= word_count;
    656 ;
    657 ;		for (loop = 0; loop < word_count; loop++) {
    658 ;			xor_byte = *delta++;
    659 ;			*to++ ^= xor_byte;
    660 ;		}
    661 ;	}
    662 ;
    663 ;
    664 ;	return(64000U);
    665 ;}
    666 ;
    667 
    668