home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* This module is based upon David Troendle's article in the May-June */
- /* issue of SEXtant. The module may be freely used for public domain */
- /* software, but remains the sole property of the author, and may not */
- /* included in any software offered for sale without the express written*/
- /* consent of the author: Wayne J. Parnin II (70310,362) */
- /************************************************************************/
- /* bugs...
- Needs special code for vertical and horizontal lines.
- Should combine line drawing, erasing, & flipping routines.
-
- history...
- 12 Aug 85 JVZ
- Resetting screen modes to power-up default before setting them.
- 11 Aug 85 JVZ
- Combined 225*640 and 400*640 modes.
- 4 Jul 85 JVZ
- Changed names to set_intensity(), set_color(), inquire_intensity(),
- and inquire_color() per revised CORE standard.
- 11 May 85 JVZ
- declaring that cursor keys aren't preceded by anything.
- Handling vertical lines as a special case.
- 27 Apr 85 JVZ
- exporting "down_arrow" rather than "cursor_down", etc.
- 21 Apr 85 JVZ
- Exporting pointers to line routines & definitions of cursor keys.
- 25 Mar 85 JVZ
- gotoxy() added. set_intensity() now takes double argument. Character
- parameters exported.
- 7 Feb 85 JVZ
- Clearing screen with ESC E rather than lots of carriage returns.
- 6 Feb 85 JVZ
- Using shifts instead of multiplies and divides in pixel_addr().
- 1 Feb 85 JVZ
- moved iline(), ierase(), imove(), icline(), icerase(), current_x, and
- current_y to g3.c
- 20 Jan 85 JVZ
- draw and erase no longer have color arguments,
- set_current_color() sets the variables current_color and ram_page.
- draw() and erase() use "simultaneous write" to write into
- more than one plane at a time. (Doesn't work if some pixels in
- different planes differ.)
- 19 Jan 85 JVZ
- In each inner loop, DI is compared with zero rather than DX. DX now
- carries twice as large a value, so it need only be added to (or
- subtracted from) DI once . Together, these changes resulted in a 7%
- increase in speed.
- Debug [ ] V1.0 13-May-84 WJP Initial Release
- Debug [ ] Vn.n dd-mmm-yy WJP Description of change
- /************************************************************************/
- /* Z100 Graphics utilities: */
- /* address = pixel_addr(x, y) Calculate pixel address */
- /* draw(x1,y1, x2,y2) Draw line between points */
- /* erase(x1,y1,x2,y2) Erase line between points */
- /************************************************************************/
-
- /************************************************************************/
- /* LOCAL DEFINITIONS ****************************************************/
-
- /* */
- /* 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
-
- int current_color=GREEN; /* Line color code: RED, BLUE, or GREEN */
- double current_intensity=.5714; /* current intensity (0 to 1) */
- static unsigned ram_page=P_GREEN; /* segment for brightest plane in use */
- static int color_ram=1; /* nonzero if color RAM installed */
- static int color_code=2; /* internal code for color (see below) */
- static int draw(), erase(); /* straight line routines */
-
- /* exported function pointers (initialized at end of listing) */
-
- extern int (*draw_line)(), (*erase_line)();
-
- /* exported graphics variables */
-
- char *machine="Z-100";
- int max_color=7;
- /* height/width parameters of screen */
- int pixels_wide=640;
- int pixels_high=225;
- double best_width=1.;
- double best_height=.872;
- /* text parameters */
- int char_rows=25;
- int char_columns=80;
- int char_height=9;
- int char_width=8;
- int x_offset=0;
- int y_offset=8;
- /* cursor key codes */
- int up_arrow=0xa5;
- int down_arrow=0xa6;
- int right_arrow=0xa7;
- int left_arrow=0xa8;
- int escaped_arrows=0;
- int escape_char=0;
-
- /* an 'A' on row r, column c has lower left corner on raster
- r*char_height + y_offset
- at pixel
- c*char_width + x_offset */
-
- /* set_color - set color to be used for subsequent primitives
- internal relative
- code intensity color monochrome
- 0 0 black 0%
- 4 1 blue 11%
- 1 2 red 30%
- 5 3 magenta 41%
- 2 4 green 59%
- 6 5 cyan 70%
- 3 6 yellow 89%
- 7 7 white 100%
- */
- set_color(color) int color;
- { if(color_ram)
- {current_color=color&7; color_code=0;
- if(current_color&BLUE) {ram_page=P_BLUE; color_code+=4;}
- if(current_color&RED) {ram_page=P_RED; color_code+=1;}
- if(current_color&GREEN) {ram_page=P_GREEN; color_code+=2;}
- current_intensity=current_color/7.;
- }
- }
- set_intensity(intensity) double intensity;
- { int i;
- i=(int)(intensity*8.);
- if(i<0) i=0;
- else if(i>7) i=7;
- set_color(i);
- }
- inquire_color() {return (current_color);}
- double inquire_intensity() {return (current_intensity);}
-
- /* */
- /* 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 );
-
- }
-
- static int pattern[8]={0,128,192,224,240,248,252,254};
-
- /* */
- /* Draw line on Z100 display */
- /* draw1(x1,y1, x2,y2) */
- /* */
-
- static int draw1(x1,y1, x2,y2)
-
- int x1,y1; /* Coordinates of first point */
- int x2,y2; /* Coordinates of last point */
-
- {
- static int start_addr; /* Initial display address line (min y) */
- static int delta_x, delta_y;
- static int pixel_bit,cnt,i;
- int video_latch_setting;
- static unsigned ram_page;
-
- if(current_color==0)return; /* black lines */
- delta_y = y2-y1;
-
- /* enable video RAM access and "simultaneous write" to all
- planes which should be active for the current color */
- video_latch_setting = _inb(VIDEO_LATCH_ADDR);
- _outb( ((video_latch_setting&0x7F)|0x70)^(color_code<<4),
- VIDEO_LATCH_ADDR );
-
-
-
- /* cases for different line directions...
- 8 4
- 7 3
- 9 10
- 1 5
- 2 6
- */
- if (delta_y == 0) /* horizontal? */
- {if( x2 > x1 )
- {start_addr = pixel_addr(x1,y1); /* case 10 */
- pixel_bit = 0x0100 >> (x1 & 7);
- delta_x = x2-x1+1;
- }
- else
- {start_addr = pixel_addr(x2,y2); /* case 9 */
- pixel_bit = 0x0100 >> (x2 & 7);
- delta_x = x1-x2+1;
- }
- cnt=delta_x;
- while(pixel_bit!=1)
- {
- #asm
- ; pixel_bit>>=1;
- MOV BX,WORD draw1_pixel_bit_ ; BX- Pixel map
- ROR BX,1 ; Next pixel
- MOV WORD draw1_pixel_bit_,BX
- ; pixel_insert(start_addr,pixel_bit);
- ; MOV DI,AX
- MOV SI,WORD draw1_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- ; MOV AX,DI
- OR DS:[SI],BL ; Set bit in ram (turn pixel on)
- POP DS
- #endasm
- if(--cnt ==0)return;
- }
- i=cnt>>3;
- #asm ; case 9
- dcase1_9:
- ; while(i--)
- ; {byte_insert(++start_addr,255);
- MOV CX,WORD draw1_i_ ; CX- Length of line
- OR CX,CX
- JZ dcase1_91 ; z => no iterations
- MOV DI,WORD draw1_start_addr_ ; DI- RAM pointer
- INC DI
- PUSH ES
- MOV AX,WORD ram_page_
- MOV ES,AX
- MOV AX,0FFH
- REP STOSB ; MOV ES:[DI],AL CX times; Set bits in ram
- DEC DI
- MOV WORD draw1_start_addr_,DI ; DI- RAM pointer
- POP ES
- dcase1_91:
- ; }
- #endasm
-
- pixel_bit=pattern[cnt&7];
- #asm
- ; pixel_insert(++start_addr,pixel_bit);
- MOV AX,WORD draw1_pixel_bit_ ; AX- Pixel map
- MOV DI,AX
- MOV SI,WORD draw1_start_addr_ ; SI- RAM pointer
- INC SI
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- OR DS:[SI],AL ; Set bits in ram (turn pixels on)
- POP DS
- #endasm
-
- return;
- }
- if( delta_y > 0 ) {
- start_addr = pixel_addr(x1,y1); /* cases 3,4,7,8 */
- pixel_bit = 0x0100 >> ((x1 & 7) + 1);
- delta_x = x2-x1;
- }
- else {
- start_addr = pixel_addr(x2,y2); /* cases 1,2,5,6 */
- pixel_bit = 0x0100 >> ((x2 & 7) + 1);
- delta_x = x1-x2;
- }
-
- if(delta_x > 0 ) { /* cases 1,2 (3,4) */
-
- delta_x = abs(delta_x);
- delta_y = abs(delta_y);
-
- if(delta_x==0) /* vertical */
- {
- #asm ; case 7
- dcase1_7:
- MOV DI,WORD draw1_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD draw1_delta_x_
- MOV CX,WORD draw1_delta_y_ ; CX- length of line
- INC CX ; number of iterations
- MOV SI,WORD draw1_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- dcase1_70:
- OR DS:[SI],AL ; Set bit in ram (turn pixel on)
- TEST SI,0400H ; On line 8 of "character" ?
- JZ dcase1_71 ; No
- ADD SI,0380H ; Yes, skip lines 9 thru 15
- dcase1_71:
- ADD SI,80H ; Increment to next line
- LOOP dcase1_70
- POP DS
- #endasm
- return;
- }
- if( delta_x > delta_y ) { /* case 1 (3) */
-
- #asm ; case 1
- dcase1_1:
- MOV DI,WORD draw1_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD draw1_delta_y_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD draw1_delta_x_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of iterations
- MOV SI,WORD draw1_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- dcase1_10:
- OR DS:[SI],AL ; Set bit in ram (turn pixel on)
- ROR AL,1 ; Next pixel
- ADC SI,0 ; Next byte, if required
- dcase1_11:
- ADD DI,BX ; DEV + DELTA_P
- JL dcase1_13
- TEST SI,0400H ; On line 8 OF "character" ?
- JZ dcase1_12 ; No
- ADD SI,0380H ; Yes, skip lines 9 thru 15
- dcase1_12:
- ADD SI,80H ; Increment to next line
- SUB DI,DX ; DEV - 2*DELTA_M
- dcase1_13:
- LOOP dcase1_10
- POP DS
- #
- }
- else { /* case 2 (4) */
-
- #asm ; case 2
- dcase1_2:
- MOV DI,WORD draw1_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD draw1_delta_x_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD draw1_delta_y_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of iterations
- MOV SI,WORD draw1_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- dcase1_20:
- OR DS:[SI],AL ; Set bit in ram (turn pixel on)
- TEST SI,0400H ; On line 8 of "character" ?
- JZ dcase1_21 ; No
- ADD SI,0380H ; Yes, skip lines 9 thru 15
- dcase1_21:
- ADD SI,80H ; Increment to next line
- ADD DI,BX ; DEV + DELTA_P
- JL dcase1_23
- ROR AL,1
- ADC SI,0
- SUB DI,DX ; DEV - 2*DELTA_M
- dcase1_23:
- LOOP dcase1_20
- POP DS
- #
- }
- }
- else { /* delta_x < 0: cases 5,6 (7,8) */
-
- delta_x = abs(delta_x);
- delta_y = abs(delta_y);
-
- if( delta_x > delta_y ) { /* case 5 (7) */
-
- #asm ; case 5
- dcase1_5:
- MOV DI,WORD draw1_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD draw1_delta_y_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD draw1_delta_x_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of iterations
- MOV SI,WORD draw1_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- dcase1_50:
- OR DS:[SI],AL ; Set bit in ram (turn pixel on)
- ROL AL,1 ; Next pixel
- SBB SI,0 ; Next byte
- dcase1_51:
- ADD DI,BX ; DEV + DELTA_P
- JL dcase1_53
- TEST SI,0400H ; On line 8 OF "character" ?
- JZ dcase1_52 ; No
- ADD SI,0380H ; Yes, skip lines 9 thru 15
- dcase1_52:
- ADD SI,80H ; Increment to next line
- SUB DI,DX ; DEV - 2*DELTA_M
- dcase1_53:
- LOOP dcase1_50
- POP DS
- #
- }
- else { /* case 6 (8) */
-
- #asm ; case 6
- dcase1_6:
- MOV DI,WORD draw1_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD draw1_delta_x_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD draw1_delta_y_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of iterations
- MOV SI,WORD draw1_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- dcase1_60:
- OR DS:[SI],AL ; Set bit in ram (turn pixel on)
- TEST SI,0400H ; On line 8 of "character" ?
- JZ dcase1_61 ; No
- ADD SI,0380H ; Yes, skip lines 9 thru 15
- dcase1_61:
- ADD SI,80H ; Increment to next line
- ADD DI,BX ; DEV + DELTA_P
- JL dcase1_63
- ROL AL,1
- SBB SI,0
- SUB DI,DX ; DEV - 2*DELTA_M
- dcase1_63:
- LOOP dcase1_60
- POP DS
- #
- }
- }
- _outb( video_latch_setting, VIDEO_LATCH_ADDR );
- }
-
-
- /* */
- /* Erase line from Z100 display */
- /* erase(x1,y1, x2,y2) */
- /* */
-
- static int erase1(x1,y1, x2,y2)
-
- int x1,y1; /* Coordinates of first point */
- int x2,y2; /* Coordinates of last point */
-
- {
- static int start_addr; /* Initial display address line (min y) */
- static int delta_x, delta_y;
- static int pixel_bit;
- int video_latch_setting;
-
- delta_y = y2-y1;
-
- video_latch_setting = _inb(VIDEO_LATCH_ADDR);
- _outb( ((video_latch_setting&0x7F)|0x70)^(color_code<<4),
- VIDEO_LATCH_ADDR );
-
- if( delta_y > 0 ) {
- start_addr = pixel_addr(x1,y1); /* cases 3,4,7,8 */
- pixel_bit = ~(0x0100 >> ((x1 & 7) + 1));
- delta_x = x2-x1;
- }
- else {
- start_addr = pixel_addr(x2,y2); /* cases 1,2,5,6 */
- pixel_bit = ~(0x0100 >> ((x2 & 7) + 1));
- delta_x = x1-x2;
- }
-
- if(delta_x > 0 ) { /* cases 1,2 (3,4) */
-
- delta_x = abs(delta_x);
- delta_y = abs(delta_y);
-
- if( delta_x > delta_y ) { /* case 1 (3) */
-
- #asm ; CASE 1
- ecase1_1:
- MOV DI,WORD erase1_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD erase1_delta_y_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD erase1_delta_x_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of iterations
- MOV SI,WORD erase1_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- ecase1_10:
- AND DS:[SI],AL ; Clear bit in ram (turn pixel off)
- ROR AL,1 ; Next pixel
- CMC
- ADC SI,0 ; Next byte, if required
- ecase1_11:
- ADD DI,BX ; DEV + DELTA_P
- JL ecase1_13
- TEST SI,0400H ; On line 8 OF "character" ?
- JZ ecase1_12 ; No
- ADD SI,0380H ; Yes, skip lines 9 thru 15
- ecase1_12:
- ADD SI,80H ; Increment to next line
- SUB DI,DX ; DEV - 2*DELTA_M
- ecase1_13:
- LOOP ecase1_10
- POP DS
- #
- }
- else { /* CASE 2 (4) */
-
- #asm ; CASE 2
- ecase1_2:
- MOV DI,WORD erase1_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD erase1_delta_x_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD erase1_delta_y_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of iterations
- MOV SI,WORD erase1_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- ecase1_20:
- AND DS:[SI],AL ; Clear bit in ram (turn pixel off)
- TEST SI,0400H ; On line 8 of "character" ?
- JZ ecase1_21 ; No
- ADD SI,0380H ; Yes, skip lines 9 thru 15
- ecase1_21:
- ADD SI,80H ; Increment to next line
- ADD DI,BX ; DEV + DELTA_P
- JL ecase1_23
- ROR AL,1
- CMC
- ADC SI,0
- SUB DI,DX ; DEV - 2*DELTA_M
- ecase1_23:
- LOOP ecase1_20
- POP DS
- #
- }
- }
- else { /* CASEs 5,6 (7,8) */
-
- delta_x = abs(delta_x);
- delta_y = abs(delta_y);
-
- if( delta_x > delta_y ) { /* CASE 5 (7) */
-
- #asm ; CASE 5
- ecase1_5:
- MOV DI,WORD erase1_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD erase1_delta_y_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD erase1_delta_x_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of iterations
- MOV SI,WORD erase1_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- ecase1_50:
- AND DS:[SI],AL ; Clear bit in ram (turn pixel off)
- ROL AL,1 ; Next pixel
- CMC
- SBB SI,0 ; Next byte
- ecase1_51:
- ADD DI,BX ; DEV + DELTA_P
- JL ecase1_53
- TEST SI,0400H ; On line 8 OF "character" ?
- JZ ecase1_52 ; No
- ADD SI,0380H ; Yes, skip lines 9 thru 15
- ecase1_52:
- ADD SI,80H ; Increment to next line
- SUB DI,DX ; DEV - 2*DELTA_M
- ecase1_53:
- LOOP ecase1_50
- POP DS
- #
- }
- else { /* CASE 6 (8) */
-
- #asm ; CASE 6
- ecase1_6:
- MOV DI,WORD erase1_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD erase1_delta_x_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD erase1_delta_y_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of iterations
- MOV SI,WORD erase1_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- ecase1_60:
- AND DS:[SI],AL ; Clear bit in ram (turn pixel off)
- TEST SI,0400H ; On line 8 of "character" ?
- JZ ecase1_61 ; No
- ADD SI,0380H ; Yes, skip lines 9 thru 15
- ecase1_61:
- ADD SI,80H ; Increment to next line
- ADD DI,BX ; DEV + DELTA_P
- JL ecase1_63
- ROL AL,1
- CMC
- SBB SI,0
- SUB DI,DX ; DEV - 2*DELTA_M
- ecase1_63:
- LOOP ecase1_60
- POP DS
- #
- }
- }
- _outb( video_latch_setting, VIDEO_LATCH_ADDR );
- }
-
- /* clear_graphics - clear screen in .1077 sec */
- clear_graphics()
- {
- /* puts("\033E"); easy way to clear 24 lines */
- #asm
- push es
- mov al,08h ;d7=0 VRAM cpu access enabled
- ;d6=d5=d4=0 simultaneous write for all planes
- ;d3=1 VRAM data displayed
- ;d2=d1=d0=0 all planes displayed
- out 0d8h,al
-
- mov ax,0d000H ;starting address
- mov es,ax
- mov ax,0 ;used to clear memory
- mov bx,ax ;displacement for first raster
- mov dx,400 ;rasters cleared
- cld
- next_line:
- mov di,bx
- mov cx,64 ;words cleared per raster
- rep stosw ;clear one raster
- add bx,128 ;displacement to next raster
- dec dx
- jnz next_line
-
- 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
- puts("\033Y "); /* home the cursor */
- }
-
- /* gotoxy - direct cursor positioning */
- gotoxy(x,y) int x,y;
- { if(y<0) y=0; else if (y>=char_rows) y=char_rows-1;
- if(x<0) x=0; else if (x>=char_columns) x=char_columns-1;
- puts("\033Y"); putchar(y+32); putchar(x+32);
- }
-
- /* */
- /* 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 );
-
- }
-
-
- /* */
- /* Draw line on Z100 display */
- /* draw(x1,y1, x2,y2) */
- /* */
-
- static draw2(x1,y1, x2,y2)
-
- int x1,y1; /* Coordinates of first point */
- int x2,y2; /* Coordinates of last point */
-
- {
- static int start_addr; /* Initial display address line (min y) */
- static int delta_x, delta_y;
- static int pixel_bit;
- int video_latch_setting;
- static unsigned ram_page;
-
- if(current_color==0)return;
-
- delta_y = y2-y1;
-
- /* enable video RAM access and "simultaneous write" to all
- planes which should be active for the current color */
- video_latch_setting = _inb(VIDEO_LATCH_ADDR);
- _outb( ((video_latch_setting&0x7F)|0x70)^(color_code<<4),
- VIDEO_LATCH_ADDR );
-
-
-
- /* CASEs for different line directions...
- 8 4
- 7 3
-
- 1 5
- 2 6
- */
- if( delta_y > 0 ) {
- start_addr = pixel2_addr(x1,y1); /* CASEs 3,4,7,8 */
- pixel_bit = 0x0100 >> ((x1 & 7) + 1);
- delta_x = x2-x1;
- }
- else {
- start_addr = pixel2_addr(x2,y2); /* CASEs 1,2,5,6 */
- pixel_bit = 0x0100 >> ((x2 & 7) + 1);
- delta_x = x1-x2;
- }
-
- if(delta_x > 0 ) { /* CASEs 1,2 (3,4) */
-
- delta_x = abs(delta_x);
- delta_y = abs(delta_y);
-
- if( delta_x > delta_y ) { /* CASE 1 (3) */
-
- #asm ; CASE 1
- dcase2_1:
- MOV DI,WORD draw2_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD draw2_delta_y_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD draw2_delta_x_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of interations
- MOV SI,WORD draw2_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- dcase2_10:
- OR DS:[SI],AL ; Set bit in ram (turn pixel on)
- ROR AL,1 ; Next pixel
- ADC SI,0 ; Next byte, if required
- dcase2_11:
- ADD DI,BX ; DEV + DELTA_P
- JL dcase2_13
- ADD SI,80H ; Increment to next line
- SUB DI,DX ; DEV - 2*DELTA_M
- dcase2_13:
- LOOP dcase2_10
- POP DS
- #
- }
- else { /* CASE 2 (4) */
-
- #asm ; CASE 2
- dcase2_2:
- MOV DI,WORD draw2_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD draw2_delta_x_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD draw2_delta_y_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of interations
- MOV SI,WORD draw2_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- dcase2_20:
- OR DS:[SI],AL ; Set bit in ram (turn pixel on)
- ADD SI,80H ; Increment to next line
- ADD DI,BX ; DEV + DELTA_P
- JL dcase2_23
- ROR AL,1
- ADC SI,0
- SUB DI,DX ; DEV - 2*DELTA_M
- dcase2_23:
- LOOP dcase2_20
- POP DS
- #
- }
- }
- else { /* CASEs 5,6 (7,8) */
-
- delta_x = abs(delta_x);
- delta_y = abs(delta_y);
-
- if( delta_x > delta_y ) { /* CASE 5 (7) */
-
- #asm ; CASE 5
- dcase2_5:
- MOV DI,WORD draw2_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD draw2_delta_y_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD draw2_delta_x_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of interations
- MOV SI,WORD draw2_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- dcase2_50:
- OR DS:[SI],AL ; Set bit in ram (turn pixel on)
- ROL AL,1 ; Next pixel
- SBB SI,0 ; Next byte
- dcase2_51:
- ADD DI,BX ; DEV + DELTA_P
- JL dcase2_53
- ADD SI,80H ; Increment to next line
- SUB DI,DX ; DEV - 2*DELTA_M
- dcase2_53:
- LOOP dcase2_50
- POP DS
- #
- }
- else { /* CASE 6 (8) */
-
- #asm ; CASE 6
- dcase2_6:
- MOV DI,WORD draw2_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD draw2_delta_x_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD draw2_delta_y_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of interations
- MOV SI,WORD draw2_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- dcase2_60:
- OR DS:[SI],AL ; Set bit in ram (turn pixel on)
- ADD SI,80H ; Increment to next line
- ADD DI,BX ; DEV + DELTA_P
- JL dcase2_63
- ROL AL,1
- SBB SI,0
- SUB DI,DX ; DEV - 2*DELTA_M
- dcase2_63:
- LOOP dcase2_60
- POP DS
- #
- }
- }
- _outb( video_latch_setting, VIDEO_LATCH_ADDR );
- }
-
-
- /* */
- /* Erase line from Z100 display */
- /* erase2(x1,y1, x2,y2) */
- /* */
-
- static erase2(x1,y1, x2,y2)
-
- int x1,y1; /* Coordinates of first point */
- int x2,y2; /* Coordinates of last point */
-
- {
- static int start_addr; /* Initial display address line (min y) */
- static int delta_x, delta_y;
- static int pixel_bit;
- int video_latch_setting;
-
- delta_y = y2-y1;
-
- video_latch_setting = _inb(VIDEO_LATCH_ADDR);
- _outb( ((video_latch_setting&0x7F)|0x70)^(color_code<<4),
- VIDEO_LATCH_ADDR );
-
- if( delta_y > 0 ) {
- start_addr = pixel2_addr(x1,y1); /* CASEs 3,4,7,8 */
- pixel_bit = ~(0x0100 >> ((x1 & 7) + 1));
- delta_x = x2-x1;
- }
- else {
- start_addr = pixel2_addr(x2,y2); /* CASEs 1,2,5,6 */
- pixel_bit = ~(0x0100 >> ((x2 & 7) + 1));
- delta_x = x1-x2;
- }
-
- if(delta_x > 0 ) { /* CASEs 1,2 (3,4) */
-
- delta_x = abs(delta_x);
- delta_y = abs(delta_y);
-
- if( delta_x > delta_y ) { /* CASE 1 (3) */
-
- #asm ; CASE 1
- ecase2_1:
- MOV DI,WORD erase2_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD erase2_delta_y_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD erase2_delta_x_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of interations
- MOV SI,WORD erase2_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- ecase2_10:
- AND DS:[SI],AL ; Clear bit in ram (turn pixel off)
- ROR AL,1 ; Next pixel
- CMC
- ADC SI,0 ; Next byte, if required
- ecase2_11:
- ADD DI,BX ; DEV + DELTA_P
- JL ecase2_13
- ADD SI,80H ; Increment to next line
- SUB DI,DX ; DEV - 2*DELTA_M
- ecase2_13:
- LOOP ecase2_10
- POP DS
- #
- }
- else { /* CASE 2 (4) */
-
- #asm ; CASE 2
- ecase2_2:
- MOV DI,WORD erase2_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD erase2_delta_x_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD erase2_delta_y_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of interations
- MOV SI,WORD erase2_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- ecase2_20:
- AND DS:[SI],AL ; Clear bit in ram (turn pixel off)
- ADD SI,80H ; Increment to next line
- ADD DI,BX ; DEV + DELTA_P
- JL ecase2_23
- ROR AL,1
- CMC
- ADC SI,0
- SUB DI,DX ; DEV - 2*DELTA_M
- ecase2_23:
- LOOP ecase2_20
- POP DS
- #
- }
- }
- else { /* CASEs 5,6 (7,8) */
-
- delta_x = abs(delta_x);
- delta_y = abs(delta_y);
-
- if( delta_x > delta_y ) { /* CASE 5 (7) */
-
- #asm ; CASE 5
- ecase2_5:
- MOV DI,WORD erase2_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD erase2_delta_y_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD erase2_delta_x_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of interations
- MOV SI,WORD erase2_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- ecase2_50:
- AND DS:[SI],AL ; Clear bit in ram (turn pixel off)
- ROL AL,1 ; Next pixel
- CMC
- SBB SI,0 ; Next byte
- ecase2_51:
- ADD DI,BX ; DEV + DELTA_P
- JL ecase2_53
- ADD SI,80H ; Increment to next line
- SUB DI,DX ; DEV - 2*DELTA_M
- ecase2_53:
- LOOP ecase2_50
- POP DS
- #
- }
- else { /* CASE 6 (8) */
-
- #asm ; CASE 6
- ecase2_6:
- MOV DI,WORD erase2_pixel_bit_ ; AX- Pixel map
- MOV BX,WORD erase2_delta_x_
- ADD BX,BX ; BX- Deviation increment
- MOV DX,WORD erase2_delta_y_ ; DX- Deviation decrement/2
- MOV CX,DX ; CX- Length of line
- INC CX ; number of interations
- MOV SI,WORD erase2_start_addr_ ; SI- RAM pointer
- PUSH DS
- MOV AX,WORD ram_page_
- MOV DS,AX
- MOV AX,DI
- MOV DI,0 ; DI- DEV
- SUB DI,DX
- ADD DX,DX
- ecase2_60:
- AND DS:[SI],AL ; Clear bit in ram (turn pixel off)
- ADD SI,80H ; Increment to next line
- ADD DI,BX ; DEV + DELTA_P
- JL ecase2_63
- ROL AL,1
- CMC
- SBB SI,0
- SUB DI,DX ; DEV - 2*DELTA_M
- ecase2_63:
- LOOP ecase2_60
- POP DS
- #
- }
- }
- _outb( video_latch_setting, VIDEO_LATCH_ADDR );
- }
-
- /* 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 */
- #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
-
- 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
- /* printf("init_graphics...result=%d\n",result); */
- if(not_z100)
- {puts("This version is for the Z-100, not this machine!\007\n");
- exit(1);
- }
- clear_graphics();
- color_ram=(result==24);
- envsearch("GRAPHICS",buf);
- if(buf[0]==0 | strcmp(buf,"1")==0) {} /* leave in 225 * 640 mode */
- else if(strcmp(buf,"2")==0)
- {
- #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=25; /* text parameters */
- char_columns=80;
- char_height=16;
- 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 */
- }
-
-
- /* exported function pointers (initialized at end of listing) */
-
- int (*draw_line)()=draw1, (*erase_line)()=erase1;
-
- /* envsearch - search environment for given string */
-
- envsearch(target,value) char *target,*value;
- { char buf[256],*s,t[25],*env;
- int nt,offset;
-
- s=t;
- while(*target) *s++=toupper(*target++);
- *s++= '='; *s=0;
- nt = strlen(t);
- offset=0;
- _lmove(2,44,_showcs()-0x10,&env,_showds());
- while(1)
- {_lmove(256,offset,env,buf,_showds());
- s=buf;
- if(*s)
- {/* printf("examining entry: %s \n",s); getchar(); */
- if (strncmp(t,s,nt)==0) return (strcpy(value,s+nt));
- }
- else
- {*value=0;
- return;
- }
- offset+=strlen(buf)+1;
- }
- }