; unvcomp.asm Copyright 1987 Dancing Flame all rights reserved. ; ; This file contains a single function which is set up to be called from ; C. Ie the parameters are on the stack instead of registers. ; decode_vplane(in, out, linebytes) ; where in is a bit-plane's worth of vertical-byte-run data ; and out is a bit-plane that gets completely over-written. ; Linebytes is the number of bytes-per-line in the out bitplane, and it ; should certainly be noted that the external pointer variable ytable ; must be initialized to point to a multiplication table of ; 0*linebytes, 1*linebytes ... n*linebytes before this routine is called. ; ; The format of "in": ; Each column of the bitplane is compressed separately. A 320x200 ; bitplane would have 40 columns of 200 bytes each. The linebytes ; parameter is used to count through the columns, it is not in the ; "in" data, which is simply a concatenation of columns. ; ; Each columns is an op-count followed by a number of ops. ; If the op-count is zero, that's ok, it just means there's no change ; in this column from the last frame. ; The ops are of two classes, and followed by a varying amount of ; data depending on which class. ; 1. Uniq ops - this is a byte with the hi bit set. The hi bit is ; masked down and the remainder is a count of the number of bytes ; of data to copy literally. It's of course followed by the ; data to copy. ; 2. Same ops - this is a byte with hi bit cleared interpreted as ; a count byte. Its followed by a byte value to repeat count times. ; Do bear in mind that the data is compressed vertically rather than ; horizontally, so to get to the next byte in the destination (out) ; we add linebytes instead of one! ; public _decode_vplane firstp set 12 in set 4+firstp out set 8+firstp linebytes set 14+firstp _decode_vplane movem.l a2/d4/d5,-(sp) ; save register for aztec. move.l in(sp),a0 move.l out(sp),a2 move.w linebytes(sp),d2 move.w d2,d4 ; make a copy of linebytes to use as a column counter. bra zdcp ; branch to the end of the column loop. dcp ; this loop goes through once for each column move.l a2,a1 ; grab a copy of the out column pointer clr.w d0 ; clear hi-byte of op-count for this column move.b (a0)+,d0 ; and get lo-byte from in data stream bra zdcvclp ; branch to end of op-loop (cause count = 0 is ok!) dcvclp clr.w d1 ;clear hi byte of op move.b (a0)+,d1 ;grab the lo byte from in data stream bmi dcvuniq ;if it's a uniq run (yuck!) have to branch dcvsame move.b (a0)+,d3 ;yea! we get to repeat d3 d1 times! move.w d1,d5 ; so set up a "tower" to do it. asr.w #3,d5 ; d5 is number of loops through tower and.w #7,d1 ; d1 is where in tower to start. add.w d1,d1 ; 4 bytes/tower element means we add to self twice add.w d1,d1 neg.w d1 jmp 34+same_tower(pc,d1) ;why the 34 isn't 32 = 8(els in tower)*4 ;is pure pure voodoo. It's not just the ;jmp instruction.... same_tower move.b d3,(a1) adda.w d2,a1 move.b d3,(a1) adda.w d2,a1 move.b d3,(a1) adda.w d2,a1 move.b d3,(a1) adda.w d2,a1 move.b d3,(a1) adda.w d2,a1 move.b d3,(a1) adda.w d2,a1 move.b d3,(a1) adda.w d2,a1 move.b d3,(a1) adda.w d2,a1 dbra d5,same_tower dbra d0,dcvclp ; through with decoding one op, go fetch next op bra z1dcp ; through with this column even. dcvuniq and.b #$7f,d1 ;it's a uniq run, so mask down to get count move.w d1,d5 ; and start setting up another tower.... asr.w #3,d5 and.w #7,d1 add.w d1,d1 add.w d1,d1 neg.w d1 jmp 34+uniq_tower(pc,d1) uniq_tower move.b (a0)+,(a1) adda.w d2,a1 move.b (a0)+,(a1) adda.w d2,a1 move.b (a0)+,(a1) adda.w d2,a1 move.b (a0)+,(a1) adda.w d2,a1 move.b (a0)+,(a1) adda.w d2,a1 move.b (a0)+,(a1) adda.w d2,a1 move.b (a0)+,(a1) adda.w d2,a1 move.b (a0)+,(a1) adda.w d2,a1 dbra d5,uniq_tower zdcvclp dbra d0,dcvclp z1dcp addq.l #1,a2 ;all through with this column, so put a2 to next one zdcp dbra d4,dcp ; maybe we're all done? movem.l (sp)+,a2/d4/d5 rts