GUBBINS@RADC-TOPS20.ARPA (Gern) (04/14/88)
Forward Msg:
12-Apr-88 15:57:08-EST,2069;000000000001
Return-Path: <SAC.DYESGPF@E.ISI.EDU>
Received: from E.ISI.EDU by RADC-TOPS20.ARPA with TCP; Tue 12 Apr 88 15:57:02-EST
Date: 11 Apr 1988 23:22-CDT
Sender: SAC.DYESGPF@E.ISI.EDU
Subject: Interlace Mode for HZ100
From: SAC.DYESGPF@E.ISI.EDU
To: INFO-HZ100-REQUEST@RADC-TOPS20.ARPA
Message-ID: <[E.ISI.EDU]11-Apr-88 23:22:30.SAC.DYESGPF>
For the individuals who were wondering about the interlace mode on the
HZ100, I hope the following code gets you going in the right direction.
The following program is included in the ASMUTIL1.ARC file in PD1:<HZ100>
on SIMTEL20 and demonstrates how to toggle this mode on/off.
With a little modification this code could easily be used as a proceedure
within assembly, pascal and C programs. The proc would be passed a 1 (turn
on interlace) or a 0 (turn off it off). As is, the program functions
as a transient dos command. If activated at the dos level before loading
ZBASIC the interlace mode will be in effect during all graphics and text
outputs to the screen, however the coorinates for graphics (e.g.
circle (x,y),r) remain unchanged (0 to 639 and 0 to 224)
Al Holecek
<SAC.DYESGPF@E.ISI.EDU>
------------------------------ CUT HERE --------------------------------
title. INTERLAC - turn on or off the interlace video only mode
;;; INTERLAC - turn on or off the interlace video only mode
;
; Usage: INTERLAC [0 | 1]
;
; An argument of 1 will turn interlace video only mode on, 0 will turn
; it off.
;
; To build INTERLAC use:
; MASM INTERLAC;
; LINK INTERLAC;
; EXE2BIN INTERLAC .COM
;
; Code comes from REMark Volume 5 Issue 12 (Dec. '84)
; Article by Frank T. Clark, Zenith Data Systems
;
code segment
assume cs:code,ds:code,es:code,ss:code
org 0100H
begin: cli
mov al,8
out 0DCH,al
mov al,ds:[082H]
and al,1
out 0DDH,al
sti
ret
code ends
end begin
-------jrv@MITRE-BEDFORD.ARPA (James R. Van Zandt) (05/01/88)
The real value of the interlace mode, as far as I'm concerned, is that
it allows you to use more than the standard 225 scan lines. 64K of
video memory is required (not the 32K that most were shipped with), and
a slow phosphor monitor is recommended to control the flicker. You
also have to reprogram the 6845 video controller chip, and restore it
afterwards. To show the method, I've appended the relevant parts of
the device controller from my graphics package for the Z-100.
In 400*640 mode, the screen has the same format as in 225*640 mode,
but there are no "skipped" scan lines. The first 8 pixels of the first
scan in the blue plane are at c000:0000, and the first 8 pixels of the
next scan are 640/8 = 128 bytes further, at c000:0080. To turn on the
3rd pixel in the second scan, write 20H to c000:0080.
The standard system routines for displaying text still work after a
fashion. They treat the screen as having 25 text lines, each with 16
scan lines. They put the character on scans 1-9, but they also put the
ASCII code on scan 10 and the foreground/background color codes on the
scan 11. These are now visible, which is distracting to say the least.
For that reason, I developed a routine to access the font table and
display characters without the extra information. In 400*640 mode, it
treats the screen as having 400/9 = 44 text lines.
For restoring the screen, I rely on the video reset function in the
system code.
- Jim Van Zandt
--------------------------------------------------------------
/* */
/* Constants */
/* */
#define BLUE 1
#define P_BLUE 0xC000
#define RED 2
#define P_RED 0xD000
#define GREEN 4
#define P_GREEN 0xE000
#define VIDEO_LATCH_ADDR 0xD8
static unsigned ram_page=P_GREEN; /* segment for brightest plane in use */
static int color_ram=1; /* nonzero if color RAM installed */
int pixels_wide = 640;
int pixels_high = 225;
double best_width = 1.;
double best_height = .872;
/* text parameters */
int char_height = 9;
static font_height = 9; /* no blank scans */
int char_width = 8;
int char_rows = 25;
int char_columns = 80;
int x_offset = 0;
int y_offset = 8;
/* init_graphics - initialize hardware for graphics */
init_graphics()
{ static int result,not_z100;
char buf[25];
puts("\033z"); /* reset video parameters and clear screen */
puts("\033y?"); /* disable key expansion */
puts("\033x1"); /* enable 25th line */
puts("\033x5"); /* disable cursor */
#asm
push es
mov al,78h ;d7=0 VRAM cpu access enabled
;d6=d5=d4=1 no simultaneous write
;d3=1 VRAM data displayed
;d2=d1=d0=0 all planes displayed
out 0d8h,al
mov bx,3
mov ax,0c000H ;BLUE plane
mov es,ax
mov cx,es:[0]
push cx
mov es:[0],bx
; color ram green plane only
add bx,es:[0] ; 3+3 => 6 3+(-1) => 2
mov ax,0d000H ;RED plane
mov es,ax
mov cx,es:[0]
push cx
mov es:[0],bx
add bx,es:[0] ; 6+6 => 12 2+(-1) => 1
mov ax,0e000H ;GREEN plane
mov es,ax
mov cx,es:[0]
push cx
mov es:[0],bx
add bx,es:[0] ; 12+12 => 24 1+1 => 2
mov word init_graphics_result_,bx
;
; Is this machine a Z-100?
; (Test the video hardware)
;
mov al,08h ;d7=0 VRAM cpu access enabled
;d6=d5=d4=0 simultaneous write to all planes
;d3=1 VRAM data displayed
;d2=d1=d0=0 all planes displayed
out 0d8h,al
mov ax,0c000H ;BLUE plane
mov es,ax
mov word es:[0],0 ; clear all planes (if Z-100)
mov ax,0e000H ;GREEN plane
mov es,ax
mov ax,es:[0] ;get one of the cleared (?) bytes
mov word init_graphics_not_z100_,ax ; zero if Z-100
mov al,78h ;d7=0 VRAM cpu access enabled
;d6=d5=d4=1 no simultaneous write
;d3=1 VRAM data displayed
;d2=d1=d0=0 all planes displayed
out 0d8h,al
mov ax,0e000H ;GREEN plane
mov es,ax
pop cx
mov es:[0],cx
mov ax,0d000H ;RED plane
mov es,ax
pop cx
mov es:[0],cx
mov ax,0c000H ;BLUE plane
mov es,ax
pop cx
mov es:[0],cx
mov al,88h ;d7=1 VRAM cpu access disabled
;d6=d5=d4=0 simultaneous write for all planes
;d3=1 VRAM data displayed
;d2=d1=d0=0 all planes displayed
out 0d8h,al
;
; fetch address of font table in RAM
;
push ds
xor ax,ax
mov ds,ax
mov ax,[3feh]
mov ds,ax
mov ax,[6fh]
mov bx,[71h]
pop ds
mov word font_seg_,bx
mov word font_off_,ax
pop es
#endasm
if(not_z100)
{puts("This version is for the Z-100!\007\n");
exit(1);
}
clear_graphics();
color_ram=(result==24);
if(version()>=0x200) envsearch("GRAPHICS",buf); else buf[0]=0;
if(buf[0]==0 | strcmp(buf,"1")==0) /* leave in 225 * 640 mode */
{draw_char=putchar2;
draw_text=puts2;
}
else if(strcmp(buf,"2")==0)
{draw_char=putchar2;
draw_text=puts2;
#asm
cli ; disable interrupts, accessing CRTC
mov al,4 ; 30 -> R4 = vertical total
out 0dch,al
mov al,30
out 0ddh,al
mov al,5 ; 9 -> R5 = vertical adjust
out 0dch,al
mov al,9
out 0ddh,al
; 25 -> R6 = vertical displayed (default)
; 28 -> R7 = sync position (default)
mov al,8 ; 3 -> R8 = interlace sync & video
out 0dch,al
mov al,011B
out 0ddh,al
mov al,9 ; 14 -> R9 = rasters per char
out 0dch,al
mov al,14
out 0ddh,al
sti ;enable interrupts
push es
mov al,78h ;d7=0 VRAM cpu access enabled
;d6=d5=d4=1 no simultaneous write
;d3=1 VRAM data displayed
;d2=d1=d0=0 all planes displayed
out 0d8h,al
mov bx,3
mov ax,0c000H ;BLUE plane
mov es,ax
mov cx,es:[0]
push cx
mov es:[0],bx
; color ram green plane only
add bx,es:[0] ; 3+3 => 6 3+(-1) => 2
mov ax,0d000H ;RED plane
mov es,ax
mov cx,es:[0]
push cx
mov es:[0],bx
add bx,es:[0] ; 6+6 => 12 2+(-1) => 1
mov ax,0e000H ;GREEN plane
mov es,ax
mov cx,es:[0]
push cx
mov es:[0],bx
add bx,es:[0] ; 12+12 => 24 1+1 => 2
mov word init_graphics_result_,bx
mov al,08h ;d7=0 VRAM cpu access enabled
;d6=d5=d4=0 simultaneous write to all planes
;d3=1 VRAM data displayed
;d2=d1=d0=0 all planes displayed
out 0d8h,al
mov ax,0c000H ;BLUE plane
mov es,ax
mov word es:[0],0 ; clear all planes (if Z-100)
mov ax,0e000H ;GREEN plane
mov es,ax
mov ax,es:[0] ;get one of the cleared (?) bytes
mov word init_graphics_not_z100_,ax
mov al,78h ;d7=0 VRAM cpu access enabled
;d6=d5=d4=1 no simultaneous write
;d3=1 VRAM data displayed
;d2=d1=d0=0 all planes displayed
out 0d8h,al
mov ax,0e000H ;GREEN plane
mov es,ax
pop cx
mov es:[0],cx
mov ax,0d000H ;RED plane
mov es,ax
pop cx
mov es:[0],cx
mov ax,0c000H ;BLUE plane
mov es,ax
pop cx
mov es:[0],cx
mov al,88h ;d7=1 VRAM cpu access disabled
;d6=d5=d4=0 simultaneous write for all planes
;d3=1 VRAM data displayed
;d2=d1=d0=0 all planes displayed
out 0d8h,al
pop es
#endasm
/* height/width parameters of screen */
pixels_wide=640;
pixels_high=400;
best_width=1.;
best_height=.777;
clear_graphics();
color_ram=(result==24);
draw_line=draw2; /* pointers to line routines */
erase_line=erase2;
char_rows=pixels_high/char_height; /* text parameters */
char_columns=80;
char_width=8;
x_offset=0;
y_offset=15;
}
else
{puts("graphics mode "); puts(buf); puts(" not implemented");
getchar();
}
}
/* finish_graphics - clean up after graphics */
finish_graphics()
{ puts("\033z"); /* reset video parameters and clear screen */
}
static puts2(s) char *s;
{ while(*s) putchar2(*s++);
}
/* */
/* Calculate address of pixel on Z100 color plane (9 lines/char) */
/* address = pixel_addr(x, y);
/* */
pixel_addr(x, y)
int x, y; /* Coordinates (x:0 - 639, y:0 - 224) */
{ int row_start; /* Address of first byte in row */
int pixel_byte; /* Location of pixel byte in row */
row_start = ((y/9)<<4) + (y%9);
pixel_byte = x>>3;
return( (row_start*128) + pixel_byte );
}
/*
Calculate address of pixel on Z100 color plane (16 lines/char)
address = pixel2_addr(x, y);
*/
pixel2_addr(x, y)
int x, y; /* Coordinates (x:0 - 639, y:0 - 399) */
{ int row_start; /* Address of first byte in row */
int pixel_byte; /* Location of pixel byte in row */
row_start = y;
pixel_byte = x>>3;
return( (row_start*128) + pixel_byte );
}
static putchar2(c) int c;
{ static char *f, *start;
int i, x, y, vls;
static scans;
if(c=='\n')
{cursor_x=0; cursor_y += char_height; return c;
}
x=cursor_x+4;
#ifdef INCLUDING
if(cursor_y<font_height) cursor_y=font_height;
else if(cursor_y>=pixels_high) cursor_y=pixels_high-1;
if(x<0) x=0;
else if(x+char_width>=pixels_wide)
x=pixels_wide-char_width;
#endif
y=cursor_y-font_height;
if(x>=0 && x<=pixels_wide-char_width &&
y>=0 && cursor_y<pixels_high)
{f=font_off+font_height*(c-' ');
vls = _inb(VIDEO_LATCH_ADDR);
/* _outb(vls&0x0F, VIDEO_LATCH_ADDR ); */
_outb( ((vls&0x7F)|0x70)^(color_code<<4),VIDEO_LATCH_ADDR );
if(pixels_high==400) {start=pixel2_addr(x,y); scan_row=15;}
else {start=pixel_addr(x,y); scan_row=9-y%9;}
scans=font_height;
#asm
PUSH DS
PUSH ES
MOV SI,WORD putchar2_f_ ; font offset
MOV AX,WORD ram_page_ ; destination segment...
MOV ES,AX
MOV DI,WORD putchar2_start_ ; ...and offset
MOV AH,BYTE scan_row_ ; starting scan (0 to 8)
MOV CX,WORD putchar2_scans_ ; # bytes to move
MOV BX,WORD font_seg_
MOV DS,BX ; font segment
putchar_1:
MOVSB ; es:di++ = ds:si++
DEC AH
JZ putchar_3
ADD DI,127 ; Increment to next line (same text row)
JMP putchar_5
putchar_3:
; (in 400*640 mode, this instruction
; never gets executed)
ADD DI,1023 ; Increment to next line (next text row)
putchar_5:
LOOP putchar_1
POP ES
POP DS
#endasm
_outb( vls, VIDEO_LATCH_ADDR );
}
cursor_x += char_width;
return c;
}