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; }