Created
August 22, 2018 14:59
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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: [email protected] | |
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