Metropoli BBS
VIEWER: picture.asm MODE: TEXT (ASCII)

; modulo per la visualizzazione di bitmap planari (4 piani)
; a 256 colori
       .386P
       
code32 segment para public use32
       assume cs:code32,ds:code32
       
include 386video.inc

BlastGet macro	@PIFF
@PIFF:
        mov cl,bh
        rep movsd
        add esi,ebp
        dec bl
	jne @PIFF
	endm

PlanGet macro @PIFFO
        inc ah 
        and ah,PIXMUP
	jnz @PIFFO
        inc esi
@PIFFO: out dx,ax
	endm

; 1 nudget     = 4  pixel (plane aligned, one pixel for every plane)
; 1 big nudget = 16 pixel (plane aligned, four nudgets)

; PIC format:
;            offset     size       name   description
;              0          1        WX     Width  of picture in BIG NUDGETS
;              1          1        WY     Height of picture in PIXELS
;              2       WX*WY*4     ----   First plane
;          2+WX*WY*4   WX*WY*4     ----   Second plane
;          2+WX*WY*8   WX*WY*4     ----   Third plane
;          2+WX*WY*12  WX*WY*4     ----   Fourth plane

	public _GetPic

; reads picture from screen
_GetPic:
        ; in:
        ; edi = pic dest
        ; esi = scr source
        ; eax = x in nudgets
        ; edx = y in pixels
        ; ecx = x width  in big-nudgets
        ; ebx = y height in pixels
        ; out:
        ; edi = ptr to end of picture
        push eax
        push ebx
        push ecx
        push edx
        push esi
        push ebp
        ; [esp-4] == screen start
        ; [esp-8] == counter
         
        add esi,[edx*4+_RowStart]
        add esi,eax
        
	BLITMODE BLITPLANE
        ; dx == GRAPHICS
        mov ax,RP0 
        mov ch,bl ; y height
        
        mov [edi],cx    ; registra ampiezza ed altezza
        mov bh,cl       ; store x counter
        add edi,2       ; advance pointer 
        
        xor ch,ch       ; ripulisci ch
        
        shl ecx,2       ; from big-nudgets to nudgets
        
        mov ebp,PXWIDTH ; avanzamento di linea iniziale
        mov [esp-4],esi
        sub ebp,ecx     ; correggi per avanzamento
        mov [esp-8],ebx
        
        out dx,ax ; read starting from plane 0
	BlastGet @gpbp0
        mov ebx,[esp-8]
        mov esi,[esp-4]

	PlanGet @gpgoz1
	BlastGet @gpbp1
        mov ebx,[esp-8]
        mov esi,[esp-4]

	PlanGet @gpgoz2
	BlastGet @gpbp2
        mov ebx,[esp-8]
        mov esi,[esp-4]
        
	PlanGet @gpgoz3
	BlastGet @gpbp3
        
        ; edi = posizione DOPO la lettura della bitmap
        pop ebp
        pop esi
        pop edx
        pop ecx
        pop ebx
        pop eax
        
	ret


BlastPut macro @PFFON
@PFFON:
	mov cl,bl
        rep movsd
        add edi,ebp
	dec bh
	jne @PFFON
	endm

BlastRPut macro @drzoom,@revup
@drzoom:        
        mov cl,bl
@revup:        
        lodsd
        rol  ax,8     ; one for the money
        sub edi,4     ; (interleave this instruction)
        rol  eax,16   ; two for the show
        rol  ax,8     ; three get ready
        mov [edi],eax ; & let's rock!
        loop @revup
        add edi,ebp
        dec bh
        jne @drzoom
        endm

PlanPut macro
	rol ah,1
        adc edi,00
	out dx,ax
	endm

PlanRPut macro
	 ror ah,1
         sbb edi,00
	 out dx,ax
	 endm


	public _PutPic

; blits a picture to screen
; Warning! L' unica opzione valida e' LEFTRIGHT!
_PutPic: 
        ; edi = scr dest
        ; esi = pic ptr
        ; eax =  x in pixels
        ; edx =  y in pixels
        ; bl  =  blit mode flag    1=reverse left-right
        mov ecx,eax
        shr eax,PIXSHIFT
        add edi,[edx*4+_RowStart]
        and ecx,PIXMUP
        add edi,eax
        inc ecx
	BLITMODE BLITPLANE

        and bl,LEFTRIGHT
        jnz @pleftright
@pnorm:
	mov ax,WWP0
	rol ah,cl
        mov bx,[esi]  ;width & height
        add esi,2
	mov cl,bl
        mov dx,SEQUENCER
        shl cl,2  ; big nudgets to nudgets
        mov ebp,PXWIDTH ; incremento di linea
        sub ebp,ecx     ; correggi per avanzamento
        
	out dx,ax
        
        push edi
        push ebx
	BlastPut @pbp0
        pop ebx
        pop edi

	PlanPut

        push edi
        push ebx
	BlastPut @pbp1
        pop ebx
        pop edi

	PlanPut

        push edi
        push ebx
	BlastPut @pbp2
        pop ebx
        pop edi

	PlanPut

	BlastPut @pbp3
@pgottaut:
	ret

@pleftright:
	; LEFT TO RIGHT <--> RIGHT TO LEFT
	mov dx,SEQUENCER
	mov ax,WWP3
        rol ah,cl
        dec cl
	jz @noinc
        inc edi
@noinc:
        mov bx,[esi]
	mov cl,bl
        add esi,2
        shl ecx,2 ; size in nudgets
        mov ebp,PXWIDTH ; incremento di linea
        add ebp,ecx     ; correggi per retrocessione
        
        
        add edi,ecx  ; portati a fine linea

	out dx,ax ; seleziona il primo piano

        push edi
        push ebx
        push eax
        BlastRPut @rbp1a,@rbp1b
        pop eax
        pop ebx
        pop edi

	PlanRPut

        push edi
        push ebx
        push eax
        BlastRPut @rbp2a,@rbp2b
        pop eax
        pop ebx
        pop edi

	PlanRPut

        push edi
        push ebx
        push eax
        BlastRPut @rbp3a,@rbp3b
        pop eax
        pop ebx
        pop edi

	PlanRPut

        BlastRPut @rbp4a,@rbp4b
        ret

; Un Spt (encoded SPriTe)
; ha una word di intestazione come una PICture
; offset size  significato
;      0    1  ampiezza immagine in nudgets
;      1    1  altezza immagine in pixels
; Ma poi i 4 piani di bytes sono descritti da "pacchetti"
; con colore trasparente codificato in RLE

; formato di un RLE packet:   [..] == .. e' opzionale
; RLE_HEADER, [INCR 1byte ], [DATA_HEAD 0..3 byte ],[DATA_DWORD 0..n dwords]


; RLE_HEADER  bit 0..1 = data_head lenght (0..3 BYTES)
;             bit    2 = dword data present
;             bit    3 = new line after this blit
;             bit 4..7 = dword counter n  (0..15 DWORDS)
; un pacchetto 00 (fine piano) oppure 08 (newline)
; non ha neppure il campo [INCR] (tutti gli altri invece ne hanno uno)

crunch macro
        ; decode next packet
        lodsw
        mov cl,al   ;  dword count into ecx (higher 4 bits)
        mov bl,ah   ;  skip count into ebx
        and eax,0Fh
        add edi,ebx ; skip_null_pixels increment (don't worry)
        jmp  [eax*4+offset ETable] ; go to packet decoder
        endm
      
eblast macro
        ; blit a dword count
        shr ecx,4   
        rep movsd
       endm   
        
ncrunch macro
        ; newline & decode next packet
        lodsw
        add ebp,PXWIDTH ; move to next line
        mov cl,al
        mov bl,ah 
        mov edi,ebp  ; perform newline
        and eax,0Fh
        add edi,ebx ; increment
        jmp [eax*4+ offset ETable] ; perform blit
        endm

; Hndl : Header, n== perform newline,d == dword data, l == data head lenght 

H000: ; END OF PLANE 
      pop ebp
      pop ecx
      pop eax
      dec esi  ; the [incr] field is not present, so move one step back
      rol ah,1  ; update plane pointer & index
      adc ebp,0 ;
      out dx,ax ;
      dec ecx     ;
      je  @basta  ; last plane ?
      mov edi,ebp
      push eax
      push ecx
      push ebp
      crunch
      
H001: movsb             
      crunch
      
H002: movsw 
      crunch
      
H003: movsb
      movsw
      crunch
      
H010: eblast
      crunch      
      
H011: movsb 
      eblast            
      crunch
      
H012: movsw 
      eblast  
      crunch
      
H013: movsb
      movsw
      eblast
      crunch
      
H100: dec esi  ; no [incr] field present
      ncrunch
      
H101: movsb             
      ncrunch
      
H102: movsw 
      ncrunch
      
H103: movsb
      movsw
      ncrunch
      
H110: eblast
      ncrunch      
H111: movsb 
      eblast            
      ncrunch
      
H112: movsw 
      eblast  
      ncrunch
      
H113: movsb
      movsw
      eblast
      ncrunch
      
      align dword
ETable: dd offset H000, offset H001, offset H002, offset H003
        dd offset H010, offset H011, offset H012, offset H013    
        dd offset H100, offset H101, offset H102, offset H103
        dd offset H110, offset H111, offset H112, offset H113
        align byte      

rcrunch macro
        lodsw
        mov cl,al
        mov bl,ah 
        and eax,0Fh
        sub edi,ebx ; increment
        jmp [eax*4+offset RETable] ; perform blit
        endm
      
reblast macro  @lup
        shr ecx,4   
@lup:   lodsd
        sub edi,4
        rol ax,8
        rol eax,16
        rol ax,8
        mov [edi],eax
        loop @lup
        endm
        
rncrunch macro
        lodsw
        add ebp,PXWIDTH ; to next line
        mov cl,al
        mov bl,ah 
        mov edi,ebp ; set next line
        and eax,0Fh
        sub edi,ebx ; increment
        jmp [eax*4+offset RETable] ; perform blit
        endm
        
rmovsb macro
        dec edi
        lodsb
        mov [edi],al
       endm
       
rmovsw macro
        sub edi,2
        lodsw
        rol ax,8
        mov [edi],ax
       endm       
       
rmovsbw macro
        sub edi,2
        lodsd
        rol ax,8
        mov [edi],ax
        shr eax,16   ; Pronti a blittare il terzo byte
        dec edi
        dec esi ; il byte piu alto e' stato letto "a vuoto"
        mov [edi],al
       endm       
        


RH000: pop ebp
       pop ecx
       pop eax
       dec esi ; no increment field present
       ror ah,1
       sbb ebp,0
       out dx,ax
       dec ecx
       je  @basta
       mov edi,ebp
       push eax
       push ecx
       push ebp
       rcrunch
      
RH001: rmovsb
       rcrunch
RH002: rmovsw 
       rcrunch
RH003: rmovsbw
       rcrunch
      
RH010: reblast  a0
       rcrunch      
RH011: rmovsb 
       reblast  a1          
       rcrunch
RH012: rmovsw 
       reblast  a2
       rcrunch
RH013: rmovsbw
       reblast  a3
       rcrunch
      
RH100:  dec esi ; no [incr] field present
        rncrunch
      
RH101: rmovsb             
       rncrunch
RH102: rmovsw 
       rncrunch
RH103: rmovsbw
       rncrunch
      
RH110: reblast   a4
       rncrunch      
RH111: rmovsb 
       reblast   a5         
       rncrunch
RH112: rmovsw 
       reblast   a6
       rncrunch
RH113: rmovsbw
       reblast   a7
       rncrunch
       
       align dword
RETable: dd offset RH000, offset RH001, offset RH002, offset RH003
         dd offset RH010, offset RH011, offset RH012, offset RH013    
         dd offset RH100, offset RH101, offset RH102, offset RH103
         dd offset RH110, offset RH111, offset RH112, offset RH113
       align byte  
       
@basta: ret ; terminate Spt blitting

            
;-----------------------END OF RLE BLIT CODE------------------------

        public _PutSpt
        
_PutSpt:
        ; edi = scr dest
        ; esi = encoded sprite pic ptr
        ; eax =  x in pixels
        ; edx =  y in pixels
        ; bl  =  drawing flags
        mov ecx,eax
        add edi,[edx*4+_RowStart]
        shr eax,PIXSHIFT
        and ecx,PIXMUP
        add edi,eax
        inc ecx
        BLITMODE BLITPLANE
        ; eax,edx thrashed
        and ebx,LEFTRIGHT
        jnz @esleftright
@esnorm:
        mov ax,WWP0
        mov dx,SEQUENCER
        rol ah,cl
        add esi,2    ; skip sprite header
        mov ecx,4    ; set plane count
        mov ebp,edi  ; set line start

        out dx,ax   ; plane select
        
        push eax
        push ecx
        push ebp
        crunch

@esleftright:
        ; LEFT TO RIGHT <--> RIGHT TO LEFT
        mov dx,SEQUENCER
        mov ax,WWP3
        rol ah,cl
        dec cl
        jz @esnoinc
        inc edi
@esnoinc:
        movzx ecx,byte ptr [esi]
        shl ecx,2 ;big nudgets to nudgets
        add esi,2
        add edi,ecx         
        mov ecx,4
        mov ebp,edi
        out dx,ax ; seleziona il primo piano

        push eax
        push ecx
        push ebp
        rcrunch
        
        align dword
plane   dd 0
y       dd 0
yheight dd 0
x       dd 0
        align byte
NO_WAY  db 08
       
        public _Pic2Spt
_Pic2Spt:
        ; converter from PIC bitmap format to SPT bitmap format        
        ; 
        ; ESI = pointer to PIC data
        ; EDI = pointer to buffer for SPT data
        ; returns:
        ;  ESI = end of PIC data
        ;  EDI = pointer to end of SPT bitmap data
        ;        If PIC data is too big, EDI is equal to its initial value +2
        push eax
        push ebx
        push ecx
        push edx
        push ebp
        mov eax,0
        mov ebx,0
        mov plane,4
        lodsw ; load&store bitmap header
        stosw ;
        xchg ah,bl ; eax= x  ebx= y
        shl eax,2  ; big-nudgets to nudgets
        cmp eax,63 ; 63 nudgets == 252 pixels
        jnbe the_end ; PIC too large for this bitmap compiler
        mov x,eax       ; store width for every plane
        mov yheight,ebx ; store line count
        jmp short comp_entry
newline:
        dec y        ;
        jne inplane  ; if NOT decoded last line, do not switch
        ; else switch plane
        mov byte ptr [edi],0 ; store a switch-plane packet
        inc edi              ;
        dec plane  ;
        je the_end ; is this the fourth plane ?
        ; no, another plane to compile
comp_entry:        
        mov eax,yheight ; get line count
        mov ebx, offset NO_WAY ; lock smart-newlines
        mov y,eax       ; recharge line counter
inplane:
        mov ecx,x   ; reload width counter
        mov ebp,ebx ; store previous packet head position into ebp
skippy_mode:
        mov ebx,edi ; store packet head position
        mov edx,0
        add edi,2
skip:
        mov al,[esi]
        cmp al,0
        jne xburst
        ; skip this pixels
        inc esi ; to next pix
        inc dh  ; increase skip count
skipped1:        
        dec ecx
        jne skip ; skip if not end of PIC line
        ; END OF PIC LINE WHILE SKIPPING
        test byte ptr [ebp],8 ; had last packet a newline ?
        jnz no_nu
        ; No, we can stuff a newline there
        or byte ptr [ebp],08
        sub edi,2 ; move back this pointer
        jmp newline
no_nu:  ; Yes, it had a newline.
        ; We have to waste one byte
        mov byte ptr [ebx],8 ; packet
        dec edi ; we don't need an increment for a simple newline
        jmp newline
        
burst:  mov al,[esi]
        cmp al,0
        je endburst ; test end of burst
xburst:              
        inc esi ; to next pix
        mov [edi],al ;store pix
        inc dl  ; increase pixel burst counter
        inc edi ; increase pointer
        dec ecx
        jne burst ; continue bursting pixels if not end ot PIC line
        ; compose burst packet
        mov al,dl
        and al,3  ; select non-dword count bits
        or al,8   ; set newline bit
        cmp dl,4
        jb blit_d
        or al,4   ; set dword_data bit
blit_d:
        rol dl,2
        and dl,0F0h  ; position dword count into packet
        or dl,al
        mov [ebx],dx ; store packet head
        jmp newline        
endburst:
        ; end of pixel burst, store packet & restart skip counting
        inc esi
        ; compose burst packet without newline
        mov al,dl
        and al,3  ; select non-dword count bits
        ; no newline here, next "skip" can be stuffed here
        cmp dl,4
        jb dblit_d
        or al,4   ; set dword_data bit
dblit_d:
        rol dl,2
        and dl,0F0h  ; position dword count into packet
        or dl,al
        mov [ebx],dx ; store packet head
        
        mov ebp,ebx   ; set previous_packet pointer
        mov edx,0100h ; skip count is already 1
        mov ebx,edi   ; store packet head position
        add edi,2     ; increase data pointer
        jmp skipped1
the_end:
        pop ebp
        pop edx
        pop ecx
        pop ebx
        pop eax
        ret        
                
code32 ends

 END
[ RETURN TO DIRECTORY ]