From ugle.unit.no!sunic!mcsun!uunet!utcsri!torn!maccs!mcshub!csx.cciw.ca!hcp Mon Sep 14 19:00:41 1992
Article: 31586 of comp.sys.ibm.pc.hardware
Newsgroups: comp.sys.ibm.pc.hardware
Path: ugle.unit.no!sunic!mcsun!uunet!utcsri!torn!maccs!mcshub!csx.cciw.ca!hcp
From: hcp@csx.cciw.ca (H.C. Pulley)
Subject: Re: CGA 160x100x16
Organization: Canada Centre for Inland Waters
Date: Sun, 13 Sep 1992 16:19:27 GMT
Message-ID: <1992Sep13.161927.19097@csx.cciw.ca>
References: <1992Sep11.120323.16528@nuscc.nus.sg>
Lines: 485
In article <1992Sep11.120323.16528@nuscc.nus.sg> isc30108@nusunix3.nus.sg (AMBAT SASI S/O PALISSERY P) writes:
>can some1 please post some code (c/asm/pas)
>describing how to arrive at this simulated "graphics"
>mode with 16 colors 160x100 resolution.
>thanks.
>
>sasi.
><last request posted expired>
Alright, but you asked for it!
Like I said before, it doesn't work properly.
Please don't give me any comments on my assembly style. This was an
experimental program only.
If you manage to get it to work properly, please send me the modified source.
This program simply goes into 160x100x16 mode (or tries to anyways) and draws
200 lines changing colors as it goes.
--- CUT HERE ---
; This program goes into text/graphics mode (160*100) in 16 colors
; It draws 200 lines and then exits
; By Harry C. Pulley, IV. MAR92.
.MODEL small
.STACK 200h
.DATA
Current_pos_x DW 159 ; to hold current pixel x value
Current_pos_y DW 0 ; to hold current pixel y value
Last_pos_x DW 0 ; to hold last pixel x value
Last_pos_y DW 99 ; to hold last pixel y value
Saved_video_mode DB ? ; to hold the old video mode for return to DOS
Set_video_mode DB 5 ; new video mode=5
Plot_mode DB 0 ; plot mode: pixel color
signed_rise DW ? ; signed rise
signed_run DW ? ; signed run
rise_sign DB ? ; rise + | -
run_sign DB ? ; run + | -
Hold_x DW ? ; starting x value
Hold_y DW ? ; starting y value
.CODE
Start: ; start of program
mov ax,@data ; set up ds to point to .DATA segment
mov ds,ax ; use ax since mov ds,@data is illegal
mov ah,0fh ; video function to get video parameters
int 10h ; video interrupt
mov [Saved_video_mode],al ; save video mode in variable for later
sub al,al ; set al to zero
mov dx,3d8h ; cga mode control register
out dx,al ; disable display
mov dx,3d4h
out dx,al ; set CRTC reg 0
mov al,83
mov dx,3d5h
out dx,al ; set horizontal total to 83
mov al,1
mov dx,3d4h
out dx,al ; set CRTC reg 1
mov al,80
mov dx,3d5h
out dx,al ; set horizontal displayed to 80
mov al,2
mov dx,3d4h
out dx,al ; set CRTC reg 2
mov al,81
mov dx,3d5h
out dx,al ; set horizontal sync to 81
mov al,3
mov dx,3d4h
out dx,al ; set CRTC reg 3
mov al,1
mov dx,3d5h
out dx,al ; set horizontal sync width 1
mov al,4
mov dx,3d4h
out dx,al ; set CRTC reg 4
mov al,107
mov dx,3d5h
out dx,al ; set vertical total to 107
mov al,5
mov dx,3d4h
out dx,al ; set CRTC reg 5
sub al,al ; al=0
mov dx,3d5h
out dx,al ; set vertical adjust 0
mov al,6
mov dx,3d4h
out dx,al ; set CRTC reg 6
mov al,107
mov dx,3d5h
out dx,al ; set vertical displayed 107
mov al,7
mov dx,3d4h
out dx,al ; set CRTC reg 7
mov al,100
mov dx,3d5h
out dx,al ; set vertical sync 100
mov al,8
mov dx,3d4h
out dx,al ; set CRTC reg 8
mov al,2
mov dx,3d5h
out dx,al ; set interlace 2
mov al,9
mov dx,3d4h
out dx,al ; set CRTC reg 9
mov al,7
mov dx,3d5h
out dx,al ; set max scan 7
mov al,10
mov dx,3d4h
out dx,al ; set CRTC reg 10
mov al,6
mov dx,3d5h
out dx,al ; set cursor start 6
mov al,11
mov dx,3d4h
out dx,al ; set CRTC reg 11
mov al,7
mov dx,3d5h
out dx,al ; set cursor end 7
mov al,12
mov dx,3d4h
out dx,al ; set CRTC reg 12
sub al,al
mov dx,3d5h
out dx,al ; set high start addr 0
mov al,13
mov dx,3d4h
out dx,al ; set CRTC reg 13
sub al,al
mov dx,3d5h
out dx,al ; set low start addr 0
mov al,14
mov dx,3d4h
out dx,al ; set CRTC reg 14
sub al,al
mov dx,3d5h
out dx,al ; set high end addr 0
mov al,15
mov dx,3d4h
out dx,al ; set CRTC reg 15
sub al,al
mov dx,3d5h
out dx,al ; set low end addr 0
mov al,01000001b
mov dx,3d8h
out dx,al ; set psuedographics mode 160x100x16
mov ax,0b800h
mov es,ax ; set es to video memory
cld
mov ax,00deh ; set even bytes to deh character
mov cx,8000 ; 8000 words long
mov di,0 ; set di to offset of start of video buffer
rep stosw ; fill video memory
mov al,01001001b
mov dx,3d8h
out dx,al ; enable display
Mainloop:
Call Plot_line
dec [Current_pos_x]
inc [Current_pos_y]
inc [Last_pos_x]
dec [Last_pos_y] ; adjust point values
cmp [Last_pos_x],100
jge OutofLoop
inc [Plot_mode]
and [Plot_mode],0fh ; get Plot_mode%16
; mov ax,10h
; int 16h ; wait for key
jmp Mainloop ; get next character/mouse action
OutofLoop:
mov ah,0 ; set video mode
mov al,[Saved_video_mode] ; restore video mode
int 10h ; video interrupt
mov ah,4ch ; DOS terminate program function
int 21h ; DOS interrupt
; Procedure to plot a pixel using direct memory writes
; Input: Plot_mode, Current_pos_x, Current_pos_y
; Registers destroyed: ax,bx,cx,dx
; Output: none
Plot_pixel PROC
mov ax,[Current_pos_y] ; set ax to current # of lines
mov dx,80 ; mul by 160
mul dx ; get current pixel count in lines
add ax,[Current_pos_x] ; add x pos to count
mov dx,ax
and dx,1 ; get odd bit of count
and ax,0fffeh ; get even count
inc ax ; make count odd bye
mov bx,ax ; quotient is byte count in bx
mov cl,2
sal dl,cl ; multiply dl by 4 for correct shift
add dl,4 ; add 4 to dl to compensate for endianess
mov cl,dl ; cl is the shift count, which is the bit count
mov dl,[Plot_mode] ; make dl pixel color
mov dh,0f0h ; prepare to erase
ror dl,cl ; rotate the bit to the correct position in dl
ror dh,cl ; rotate erasure window to correct pos
and BYTE PTR es:[bx],dh ; clear pixel
or BYTE PTR es:[bx],dl ; draw pixel
ret
Plot_pixel ENDP
; Procedure to plot a line from Last_pos_? to Current_pos_? using Plot_pixel
; Input: Last_pos_x,Last_pos_y,Current_pos_x,Current_pos_y
; Registers destroyed: ax,bx,cx,dx
; Output: none
Plot_line PROC
mov cx,[Current_pos_y]
mov dx,[Current_pos_x] ; put current pos in registers cx,dx
mov ax,cx
sub ax,[Last_pos_y]
mov [signed_rise],ax ; get signed rise
mov ax,dx
sub ax,[Last_pos_x]
mov [signed_run],ax ; get signed run
mov ax,[Last_pos_y]
push ax
mov ax,[Last_pos_x]
push ax ; preserve last x,y
cmp cx,[Last_pos_y] ; we want a positive rise
jl Last_y_bigger
mov [rise_sign],1 ; remember rise sign +
jmp Do_run
Last_y_bigger:
xchg cx,[Last_pos_y] ; swap current y and last y
mov [rise_sign],-1 ; remember rise sign -
Do_run:
sub cx,[Last_pos_y] ; get +rise
cmp dx,[Last_pos_x] ; want a pos rise
jl Last_x_bigger
mov [run_sign],1 ; remember run sign +
jmp Do_line
Last_x_bigger:
xchg dx,[Last_pos_x] ; swap current x and last x
mov [run_sign],-1 ; remember run sign -
Do_line:
sub dx,[Last_pos_x] ; want pos run
pop ax
mov [Last_pos_x],ax
pop ax
mov [Last_pos_y],ax ; restore last x,y
mov ax,cx
add ax,dx
cmp ax,0 ; if cx==dx==0 no draw needed
jne Continue
ret
Continue:
mov ax,[Current_pos_y]
push ax
mov ax,[Current_pos_x]
push ax ; preserve current position x & y
cmp cx,dx ; compare rise to run
jg Skip
jmp Run_bigger ; ignore = case, doesn't matter y | x if equal
Skip:
cmp [rise_sign],1
je Start_last ; determine starting point, last or current
jmp Start_next
Start_last:
mov ax,[Last_pos_y]
mov [Current_pos_y],ax ; set last y to start
mov ax,[Last_pos_x]
mov [Current_pos_x],ax ; set last x to start
Start_next:
mov ax,[Current_pos_y]
mov [Hold_y],ax ; keep start y
Rise_loop:
mov ax,[Current_pos_y]
sub ax,[Hold_y] ; ax=delta y
mov bx,[signed_run]
imul bx ; mul y*run
mov bx,[signed_rise]
idiv bx ; div (y*run)/rise
add ax,[Current_pos_x] ; add ((y*run)/rise)+b
xchg ax,[Current_pos_x] ; save x
push ax ; preserve ax for Current_pos_x
push cx ; preserve cx for Loop counter
call Plot_pixel
pop cx ; restore cx
pop ax ; restore ax
mov [Current_pos_x],ax ; restore x
inc [Current_pos_y] ; go to next y pos
loop Rise_loop ; do next y pos
jmp Restore ; exit procedure
Run_bigger:
mov cx,dx ; put run into counter
cmp [run_sign],1
je Start_lst ; determine starting point, last or current
jmp Start_nxt
Start_lst:
mov ax,[Last_pos_y]
mov [Current_pos_y],ax ; set last y to start
mov ax,[Last_pos_x]
mov [Current_pos_x],ax ; set last x to start
Start_nxt:
mov ax,[Current_pos_x]
mov [Hold_x],ax ; keep starting x value
Run_loop:
mov ax,[Current_pos_x]
sub ax,[Hold_x] ; ax=delta x
mov bx,[signed_rise]
imul bx ; mul x*rise
mov bx,[signed_run]
idiv bx ; div (x*rise)/run
add ax,[Current_pos_y] ; add ((x*rise)/run)+b
xchg ax,[Current_pos_y] ; save y
push ax ; preserve ax for Current_pos_y
push cx ; preserve cx for Loop counter
call Plot_pixel
pop cx ; restore cx
pop ax ; restore ax
mov [Current_pos_y],ax ; restore y
inc [Current_pos_x] ; go to next x pos
loop Run_loop ; do next x pos
jmp Restore
Restore:
pop ax
mov [Current_pos_x],ax ; restore x
pop ax
mov [Current_pos_y],ax ; restore y
ret
Plot_single:
call Plot_pixel
ret
Plot_line ENDP
END Start
--- CUT HERE ---
Harry
--
hcp@csx.cciw.ca | This message | It takes all kinds,
hcpiv@grumpy.cis.uoguelph.ca | released to the | and to each his own.
------------------------------------| PUBLIC DOMAIN. | This thought in mind,
Stay away from the DOS side, Luke! | | I walk alone.
From ugle.unit.no!sunic!mcsun!uunet!spool.mu.edu!yale.edu!jvnc.net!nuscc!nusunix3.nus.sg!isc30108 Mon Sep 14 19:01:21 1992
Article: 31648 of comp.sys.ibm.pc.hardware
Newsgroups: comp.sys.ibm.pc.hardware
Path: ugle.unit.no!sunic!mcsun!uunet!spool.mu.edu!yale.edu!jvnc.net!nuscc!nusunix3.nus.sg!isc30108
From: isc30108@nusunix3.nus.sg (AMBAT SASI S/O PALISSERY P)
Subject: Re: CGA 160x100x16
Message-ID: <1992Sep14.122249.14656@nuscc.nus.sg>
Sender: usenet@nuscc.nus.sg
Organization: National University of Singapore
References: <1992Sep13.161927.19097@csx.cciw.ca>
Date: Mon, 14 Sep 1992 12:22:49 GMT
Lines: 21
hey, ur code works ! (after some minor twiddling}
here's what u need to change
3d4[1] = 71h
2 50h
5ah
0ah
7fh
6
64h
70h
2
1
6
7
0
0
0
thanks for everything.
sasi.