home *** CD-ROM | disk | FTP | other *** search
- ;============================
- ;Linkable module for PCX.PAS
- ;============================
-
- DATA SEGMENT WORD
-
- extrn datalength: word
- extrn scratch: dword
- extrn abuff0, abuff1: word
- extrn is_CGA: byte
- extrn page_addr: word
- extrn video_index: word
- extrn columncount: word
- extrn plane: word
- extrn repeatcount: byte
- extrn bytes_per_line: word
-
- writeproc dw (?)
-
- DATA ENDS
-
- CODE SEGMENT WORD PUBLIC
-
- assume cs:code, ds:data
-
- public decode_pcx
- public decode_pcx256
-
- LOCALS
-
- ;==========================================================================
-
- ;Here's how the data compression system works. Each byte is either image
- ;data or a count byte that tells how often the next image byte is repeated.
- ;The byte is image data if it follows a count byte, or if either of the top
- ;two bits is clear. Otherwise it is a count byte, with the count derived
- ;from the lower 6 bits.
-
- GET_DATA_BYTE MACRO
-
- @@getbyte: cmp si, datalength ;end of scratch buffer?
- je @@exit ;yes, quit
- push es ;save output address
- push di
- les di, scratch ;scratch start in ES:DI
- add di, si ;add offset
- mov al, [es:di] ;get byte from scratch
- inc si ;increment index
- pop di ;restore output address
- pop es
- cmp bl, 0 ;was prev. byte a count?
- jg @@repeats ;yes, this is data
- mov ah, al ;no, copy byte to AH
- and ah, 192 ; and test high bits
- cmp ah, 192
- jne @@is_data ;not set, not a count
- ;It's a count byte
- xor al, 192 ;get count from 6 low bits
- mov bl, al ;store repeat count
- jmp @@getbyte ;go get data byte
-
- ENDM
-
- ;===================== Store CGA image in buffers ========================
-
- STOREBYTE PROC NEAR
-
- stosb ;AL into ES:DI, increment DI
- inc dx ;increment column count
- cmp dx, bytes_per_line
- je row_ends ;end of a row
- ret ;not end of row, so finished
- row_ends: xor bp, 1 ;switch banks
- cmp bp, 1 ;is bank 1?
- je bank1 ;yes, jump
- mov abuff1, di ;no, save index into bank 1
- mov es, abuff0[2] ;load bank 0 segment
- mov di, abuff0 ;load bank 0 index
- xor dx, dx ;reset column counter
- ret
- bank1: mov abuff0, di ;save index into bank 0
- mov es, abuff1[2] ;load bank 1 segment
- mov di, abuff1 ;load bank 1 index
- xor dx, dx ;reset column counter
- ret
-
- STOREBYTE ENDP
-
- ;====================== Write EGA/VGA image to video =====================
-
- ;The data in the .PCX file is organized by color plane, by line; that is,
- ;all the data for plane 0 for line 1, then for plane 1, line 1, etc.
- ;Writing the data to display memory is just a matter of masking out the
- ;other planes while one plane is being written to. This is done with the
- ;map mask register in the sequencer. All the other weird and wonderful
- ;registers in the EGA/VGA do just fine with their default settings, thank
- ;goodness.
-
- WRITEBYTE PROC NEAR
-
- stosb ;AL into ES:DI, inc DI
- inc dx ;increment column
- cmp dx, bytes_per_line ;reached end of scanline?
- je doneline ;yes
- ret ;no, go get a byte
- doneline: shl bp, 1 ;shift to next plane
- cmp bp, 8 ;done 4 planes?
- jle setindex ;no
- mov bp, 1 ;yes, reset plane to 1
- jmp short setplane ; but don't reset index
- setindex: sub di, dx ;reset to start of line
- setplane: push ax ;save data in AL
- cli ;clear interrupts
- mov ax, bp ;plane is 1, 2, 4, or 8
- mov dx, 3C5h ;sequencer data register
- out dx, al ;mask out 3 planes
- sti ;enable interrupts
- pop ax ;restore data byte
- xor dx, dx ;reset column count
- ret
-
- WRITEBYTE ENDP
-
- ;======================= Decode data from file ===========================
-
- DECODE_PCX PROC NEAR
-
- push bp
- cmp is_CGA, 1
- je CGAonly
- mov bp, plane ;store plane in BP
- mov es, page_addr ;video display segment
- mov writeproc, offset writebyte ;choose EGA/VGA procedure
- mov di, video_index ;output pointer
- jmp short alltypes
- CGAonly: mov writeproc, offset storebyte ;choose CGA procedure
-
- ;It's assumed that CGA files will require only one pass through the buffer,
- ;therefore output pointer is initialized to first row bank.
-
- mov es, abuff0[2] ;segment of bank 0 buffer
- mov di, abuff0 ;offset of buffer
- mov bp, 0 ;bank in BP
- alltypes: mov bl, repeatcount ;count in BL
- mov dx, columncount ;column counter
- xor cx, cx ;clean up CH for counter
- mov si, cx ;initialize scratch ptr.
- cld ;clear DF for stosb
-
- ;--------------------- Loop through scratch buffer ------------------------
-
- get_data_byte ;macro
- ;It's a single data byte; call CGA or EGA routine once
- @@is_data: call writeproc
- jmp @@getbyte
- ;It's data to be written "count" times; call CGA or EGA routine repeatedly
- @@repeats: mov cl, bl ;set loop counter
- @@go: call writeproc
- loop @@go ;write byte CX times
- mov bl, 0 ;clear count byte
- jmp @@getbyte
-
- ;----------------------- Finished with buffer ----------------------------
-
- @@exit: mov plane, bp ;save status for next
- mov repeatcount, bl ; run thru buffer
- mov columncount, dx
- mov video_index, di
- pop bp
- ret
-
- DECODE_PCX ENDP
-
- ;==================== Decode data from 256-color file ====================
-
- ;The following procedure is fundamentally the same as DECODE_PCX, and the
- ;code could be made more compact by merging the two. I've done things this
- ;way solely in the interests of speed: it would waste time to call
- ;a "writeproc" procedure 64,000 times when that procedure consisted of just
- ;a single instruction.
-
- DECODE_PCX256 PROC NEAR
-
- mov es, page_addr ;video segment
- mov bl, repeatcount ;count in BL
- mov di, video_index ;index into video
- xor cx, cx ;clean up loop counter
- mov si, cx ;index into scratch
- cld ;clear DF
-
- ;---------------------- Loop through scratch buffer -----------------------
-
- get_data_byte ;macro
- ;It's a single data byte
- @@is_data: stosb ;byte into video
- jmp @@getbyte
- ;It's data to be written "count" times
- @@repeats: mov cl, bl ;set counter
- rep stosb ;write byte CX times
- mov bl, 0 ;clear count byte
- jmp @@getbyte
-
- ;------------------------- Finished with buffer --------------------------
-
- @@exit: mov video_index, di ;save status for next
- mov repeatcount, bl ; run thru buffer
- ret
-
- DECODE_PCX256 ENDP
-
- ;=========================================================================
- CODE ENDS
- END
-