;This is the flash display routine used to display crunched TheDraw image
;files.  It uses a custom protocol for reproducing an image with any
;possible color combinations.  The control codes below 32 are reserved
;for this function.  The following data structure shows the format of a
;sequence.  Not all operations use the optional bytes <x> or <y>..
;
;Data Structure:  <current byte>[<x>[<y>]]
;
;   0..15 = New Foreground Color
;  16..23 = New Background Color
;      24 = Go down to next line, return to same horizontal position as when
;           routine was started (akin to a c/r).
;      25 = Displays <x> number of spaces.
;      26 = Displays <x> number of <y>.  Also used to display ANY characters
;           below #32.  This function is the only way to do this although it
;           uses three bytes.  Otherwise the code would be interpreted as
;           another command.
;      27 = Toggles on/off the foreground attribute blink flag.
;
;----------------------------------------------------------------------------
;
;To use this uncrunch routine, call the procedure with the DS:SI register
;pair pointing to the TheDraw output listing, the ES:DI register pair
;pointing to the destination display address, and the length of the image
;data in the CX register.  All modified registers are restored upon exiting.
;
;Assume an output file of a 40 character by 10 line block.  The label
;'IMAGEDATA' has been added for referencing purposes. ie:
;
;
;     ;TheDraw Assembler Crunched Screen Image. Width=40 Depth=10 Length=467
;     ImageData  LABEL BYTE
;                DB      ...list of image bytes here...
;
;
;The following assembly language code could then be used to display the
;40x10 block on the screen with:
;
;                MOV     SI,offset ImageData
;                MOV     AX,0B800h
;                MOV     ES,AX
;                MOV     DI,34*2 + 5*160-162
;                MOV     CX,467
;                CALL    UNCRUNCH
;
;The data segment (DS register) is assumed to point at the segment ImageData
;resides in.   The ES:DI register pair points at position (34,5) on the color
;graphics adapter screen, calculated as an offset from the start of the screen.
;Monochrome card users, replace the 0B800h with 0B000h.
;
;The value of 467 place into CX is the length of the image data (from the
;TheDraw title block above).
;
;UnCrunch remembers the horizontal (X) starting position when it goes down
;to the next line.  This allows you to display the ImageData block correctly
;at any position on the screen.   ie:
;
;  +-------------------------------------------------+
;  |                                                 |
;  |                                                 | <- Assume this
;  |                                                 |    is the video
;  |           ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿               |    display.
;  |           ³ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ³               |
;  |           ³ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ³               |
;  |           ³ÛÛ ImageData block ÛÛ³               |
;  |           ³ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ³               |
;  |           ³ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ³               |
;  |           ³ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ³               |
;  |           ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ               |
;  |                                                 |
;  |                                                 |
;  |                                                 |
;  +-------------------------------------------------+
;
;
;The ImageData block could just as easily been displayed in the upper-left
;corner of the screen with:
;                MOV     SI,offset ImageData
;                MOV     AX,0B800H
;                MOV     ES,AX
;                MOV     DI,1*2 + 1*160-162
;                MOV     CX,467
;                CALL    UNCRUNCH
;
;Notice the offset address changed to the coordinates (1,1).  To display
;the block in the lower-right corner you would change the DI assignment to:
;
;                MOV     DI,40*2 + 15*160-162
;
;The block is 40 characters wide by 10 lines deep.  Therefore to display
;such a large block, we must display the block at coordinates (40,15);
;
;
;Obviously the documentation here attempts to describe the procedure by use
;of examples.  This was felt to be the clearest way of explaining it.  The
;routine was designed to make using it easy; however, for some people the
;best way to learn it is to experiment.  Try creating a program using the
;above example information.  Use TheDraw to make a 40 by 10 block (or any
;size) to experiment with.  Good luck.
;


UNCRUNCH PROC NEAR
;
;Parameters Required:
;  DS:SI  ImageData source pointer.
;  ES:DI  Display address pointer.
;  CX     Length of ImageData source data.
;
       PUSH    SI                      ;Save registers.
       PUSH    DI
       PUSH    AX
       PUSH    CX
       PUSH    DX

       MOV     DX,DI                   ;Save X coordinate for later.
       XOR     AX,AX                   ;Set Current attributes.
       CLD

LOOPA: LODSB                           ;Get next character.
       CMP     AL,27                   ;Does user want to toggle the blink
       JNZ     ForeGround              ;attibute?
       XOR     AH,128                  ;Done.
       JMP     Short Next

ForeGround:
       CMP     AL,16                   ;If less than 16, then change the
       JNC     BackGround              ;foreground color.  Otherwise jump.
       AND     AH,70H                  ;Strip off old foreground.
       OR      AH,AL
       JMP     Short Next

BackGround:
       CMP     AL,24                   ;If less than 24, then change the
       JZ      NextLine                ;background color.  If exactly 24,
       JNC     MultiOutput             ;then jump down to next line.
       SUB     AL,16                   ;Otherwise jump to multiple output
       ADD     AL,AL                   ;routines.
       ADD     AL,AL
       ADD     AL,AL
       ADD     AL,AL
       AND     AH,8FH                  ;Strip off old background.
       OR      AH,AL
       JMP     Short Next

NextLine:
       ADD     DX,160                  ;If equal to 24,
       MOV     DI,DX                   ;then jump down to
       JMP     Short Next              ;the next line.

MultiOutput:
       CMP     AL,25                   ;If equal to 25,
       JNZ     NotMultiSpaces          ;then using the
       LODSB                           ;following code as
       PUSH    CX                      ;a count, output
       XOR     CH,CH                   ;said number of
       MOV     CL,AL                   ;spaces.
       MOV     AL,32
       JMP     Short StartOutput       ;Use below loop.

NotMultiSpaces:
       CMP     AL,26                   ;If equal to 26, then using
       JNZ     NormalLetter            ;the following two codes, display
       LODSB                           ;<x> number of <y> characters.
       DEC     CX                      ;Adjust main counter.
       PUSH    CX                      ;Display as many of
       XOR     CH,CH                   ;whatever the user
       MOV     CL,AL                   ;wants.
       LODSB                           ;Get character.

StartOutput:
       JCXZ    Stop                    ;Abort if already at zilch.
LOOPB: STOSW
       LOOP    LOOPB
Stop:  POP     CX
       DEC     CX                      ;Adjust main counter.

NormalLetter:
       STOSW                           ;Save screen letter.

Next:  JCXZ    Done                    ;Get next, unless CX
       LOOP    LOOPA                   ;has already gone to zero.

Done:  POP     DX                      ;Restore registers.
       POP     CX
       POP     AX
       POP     DI
       POP     SI
       RET

UNCRUNCH ENDP