Path: utzoo!mnetor!uunet!husc6!mailrus!tut.cis.ohio-state.edu!bloom-beacon!gatech!purdue!decwrl!ucbvax!MITRE-BEDFORD.ARPA!jrv From: jrv@MITRE-BEDFORD.ARPA (James R. Van Zandt) Newsgroups: comp.sys.zenith.z100 Subject: Interlace stuff Message-ID: <8805011404.AA00141@mitre-bedford.ARPA> Date: 1 May 88 14:04:30 GMT Sender: daemon@ucbvax.BERKELEY.EDU Organization: The Internet Lines: 386 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=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