Skip to content

Instantly share code, notes, and snippets.

@cshepherd
Created August 22, 2018 14:59
Show Gist options
  • Save cshepherd/0ab62f5cbf563ca5078547b8de457d29 to your computer and use it in GitHub Desktop.
Save cshepherd/0ab62f5cbf563ca5078547b8de457d29 to your computer and use it in GitHub Desktop.
Display Apple IIgs SHR image on IBM PC/AT (286 assembly + VGA card) - Me, 1993
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment