P286 ; Code to view an Apple //GS 320x200x256 picture ($C1) ; Format is as follows: ; $0000-$7CFF Picture data, in nibbles. Each nibble has the value of ; 1-16, specifying a color in the palette assigned to that ; line. ; $7D00-$7DC7 Scanline Control Bytes. There are 200 of these, one for ; each scanline. They are byte values, and break down like this: ; Bits 0-3: Palette Number For Line (0-15) ; Bit 4 : Reserved (must be 0) ; Bit 5 : Fill Mode (0=off, 1=on) ; Bit 6 : Scanline Interrupts for this line (0=off, 1=on) ; Bit 7 : Graphics mode for this line (0=320, 1=640) ; $7DC8-$7DFF Reserved - Filled with zeroes ; $7E00-$7FFF Color Palettes 0-15. These are 16 colors, each represented ; by words. They break down like so: ; Bits 0-3 : Blue Intensity ; Bits 4-7 : Green Intensity ; Bits 8-11 : Red Intensity ; Bits 12-15: Reserved (must be 0) ; 32767 Total Bytes ; ; LIMITATIONS: This code does not support the 640x200x256 GS picture mode, ; because it sucks. Scanline interrupts were considered ; irrelevant and are not implemented. ; ; Version 1.0 by Belgorath - (c) June 1993 DTCI / CyberCorps Labs ; Version 1.1 - Fixed 256-color implementation, added optimizations, ; checking for errors on file open ; Version 1.2 - MUCH quicker color decoding / setting - Uses in, out ; instead of int 10h. Also more optimizations ; Version 1.3 - Fill mode support added ; Comments to: belgo@gnu.ai.mit.edu DOSSEG MODEL Small JUMPS STACK 400h .DATA picdata db 7d00h dup(0) ;Filler for picture data scb db 00c8h dup(0) ;Filler for SCB's shit db 0038h dup(0) ;Filler for zeroes pals db 0200h dup(0) ;Filler for palette data prmp db 'Enter filename (.C1) to view > ',0 emsg db 'Error Opening File!',0 fnam db 255 dup (0) ;Filename for the $C1 picture .CODE Start: mov ax,seg prmp mov ds,ax mov dx,offset prmp call puts_z mov ax,seg fnam mov ds,ax mov dx,offset fnam mov cx,250 call gets_z call readit ;Read in the file mov ax,0013h int 10h ;Set 320x200x256 MCGA Mode mov ax,@data mov ds,ax mov si,offset picdata ;DS:SI -> picture data mov ax,0a000h mov es,ax mov di,00h ;ES:DI -> VGA data ; Translate and set pixel values pixels: mov ah,[DS:SI] ;Get 2 pixels push ax and ah,0F0h ;Get 1st pixel shr ah,1 ;4 shr reg8,1's are faster than one shr ah,1 ;mov reg8,abs8 + shr ah,cl shr ah,1 shr ah,1 mov [ES:DI],ah ;Put our pixel inc di pop ax ;Faster than mov'ing ax again... and ah,0Fh ;Get 2nd pixel mov [ES:DI],ah ;And plot it (no translation required) inc di inc si cmp si,7d00h ;Have we done all the pixels? jne pixels ; Translate and set color palettes - note that this is not exact, but close ; Hella-fast colors thanks to Midnight and MYDE.ASM pall: mov si,offset pals ;DS:SI -> Palette data xor bx,bx llp: mov dx,03c8h mov ax,bx out dx,al mov ax,[DS:SI] ;Fetch the word and ax,0F00h ;Get Red Intensity mov cl,6 ;shr 6 = shr 8, mul 4 shr ax,cl ;shr is faster than shr, mul mov dx,03c9h out dx,al mov ax,[DS:SI] ;Get the word again and ax,00F0h ;This time, get Green Intensity mov cl,2 shr ax,cl out dx,al mov ax,[DS:SI] and ax,000Fh ;get Blue intensity mov cl,2 shl ax,cl out dx,al inc bx add si,2 cmp bx,256 ;Do all the colors... jne llp ; Check for fill-mode and set pixels accordingly fill: mov si,offset scb xor di,di xor ch,ch ;CH = scanline count leep: mov al,[ds:si] and al,00100000b ;Fill mode set? cmp al,00 jne fmode add di,320 jmp nextf fmode: xor bx,bx ;BX = pixel count xor dl,dl flp: mov al,[es:di] cmp al,00h jne nof mov [es:di],dl jmp f2 nof: mov dl,al f2: inc di inc bx cmp bx,320 jne flp nextf: inc ch inc si cmp ch,200 jne leep ; Read the SCBs and translate scanline colors accordingly colorx: mov si,offset scb ;DS:SI -> SCBs xor di,di xor ch,ch doobie: mov al,[ds:si] ;Get the scb and al,0Fh ;Mask off the palette value cmp al,00 ;If palette 0, no translation needed jne over1 add di,320 jmp next over1: shl al,1 ;Shl is faster than mul for multiplication shl al,1 ;Why do we do this 4 times rather than use cl? shl al,1 ;shl reg8,cl(4) = 9 cycles + 2 for the mov shl al,1 ;shl 4 times = 8 cycles xor bx,bx xl: add [es:di],al ;Do the color translation inc bx inc di cmp bx,320 jne xl next: inc ch inc si cmp ch,200 ;Done all the lines? jne doobie ;Nope... dndn: xor ah,ah int 16h ;Get keypress mov ax,03h int 10h ;So we go back to text... mov ax,04c00h int 21h ;Return to DOS, return code 0 ; Procedure to read in the $C1 file... ; Uses Fiver's DOS calls Proc readit mov ax,@data mov ds,ax mov dx,offset fnam xor al,al call fopen jc oerr suc: push bx mov cx,8000h mov dx,offset picdata call fread pop bx call fclose ret oerr: mov dx,offset emsg call puts_z mov ax,04c01h int 21h readit endp ; Fiver's DOS library ; By Fiver - June 1993 proc fseek ; accepts the following ; al - origin (0 : start, 1: current, 2: end) ; bx - file handle ; cx:dx offset (usually dx only for less that 65000<>) push ax dx mov ah,042h int 21h pop dx ax ret endp fseek proc fread ; accepts the following ; bx - file handle ; cx - number of bytes to read ; ds:dx - buffer for data push ax mov ah,03fh int 21h pop ax ret endp fread proc fopen ; accepts the following ; ds:dx - asciiz filename ; al - mode (0 : read only, 1 : write only, 2 : read/write) ; returns file handle in bx push ax cx xor cx,cx mov ah,03dh int 21h mov bx,ax ; filehandle returned in ax, move to bx for standard pop cx ax ret endp fopen proc fclose ; accepts the following ; bx - file handle push ax mov ah,03eh int 21h pop ax ret endp fclose proc fwrite ; accepts the following ; bx - file handle ; ds:dx - buffer to write ; cx - number of bytes to write push ax mov ah,040h int 21h pop ax ret endp fwrite proc gets_z ; accepts ds:dx as a input buffer ; cx - maximum string length push es di ax bx dx cx mov ax,ds mov es,ax mov di,dx xor al,al cld rep stosb pop cx push cx xor bx,bx mov ax,ds mov es,ax mov di,dx call fread pop cx push cx @@no13: mov al,[es:di] cmp al,13 jne @@not13 xor al,al mov [es:di],al @@not13: inc di loop @@no13 pop cx dx bx ax di es ret endp gets_z proc puts_z ; accepts asciiz string in ds:dx pusha mov ax,ds mov es,ax mov di,dx xor cx,cx xor al,al @@keepgoin: mov al,[es:di] inc di cmp al,0 je @@endgoin inc cx jmp @@keepgoin @@endgoin: mov bx,1 call fwrite popa ret endp puts_z End Start