1 /* Copyright (C) 1990, 1991, 1993 Aladdin Enterprises. All rights reserved. 2 3 This software is provided AS-IS with no warranty, either express or 4 implied. 5 6 This software is distributed under license and may not be copied, 7 modified or distributed except as expressly authorized under the terms 8 of the license contained in the file LICENSE in this distribution. 9 10 For more information about licensing, please refer to 11 http://www.ghostscript.com/licensing/. For information on 12 commercial licensing, go to http://www.artifex.com/licensing/ or 13 contact Artifex Software, Inc., 101 Lucas Valley Road #110, 14 San Rafael, CA 94903, U.S.A., +1(415)492-9861. 15 */ 16 17 /* $Id: gdevherc.c,v 1.5 2002/06/16 05:48:55 lpd Exp $*/ 18 /* IBM PC-compatible Hercules Graphics display driver */ 19 /* using direct access to frame buffer */ 20 21 #define FB_RASTER 90 22 #define SCREEN_HEIGHT 350 23 #define SCREEN_ASPECT_RATIO (54.0/35.0) 24 #define VIDEO_MODE 0x07 25 #define regen 0xb0000000L 26 27 #define interrupt /* patch ANSI incompatibility */ 28 #include "dos_.h" 29 typedef union REGS registers; 30 #include "gx.h" 31 #include "gsmatrix.h" /* for gxdevice.h */ 32 #include "gxbitmap.h" 33 #include "gxdevice.h" 34 35 /* outportb is defined in dos_.h */ 36 #define outport2(port, index, data)\ 37 (outportb(port, index), outportb((port)+1, data)) 38 /* Define the nominal page height in inches. */ 39 #ifdef A4 40 # define PAGE_HEIGHT_INCHES 11.69 41 #else 42 # define PAGE_HEIGHT_INCHES 11.0 43 #endif 44 45 /* Dimensions of screen */ 46 #define screen_size_x (FB_RASTER * 8) 47 #define screen_size_y SCREEN_HEIGHT 48 /* Other display parameters */ 49 #define raster_x FB_RASTER 50 #define aspect_ratio SCREEN_ASPECT_RATIO 51 #define graphics_video_mode VIDEO_MODE 52 53 /* Procedures */ 54 55 /* See gxdevice.h for the definitions of the procedures. */ 56 57 dev_proc_open_device(herc_open); 58 dev_proc_close_device(herc_close); 59 dev_proc_fill_rectangle(herc_fill_rectangle); 60 dev_proc_copy_mono(herc_copy_mono); 61 dev_proc_copy_color(herc_copy_color); 62 63 /* The device descriptor */ 64 private gx_device_procs herc_procs = { 65 herc_open, 66 gx_default_get_initial_matrix, 67 gx_default_sync_output, 68 gx_default_output_page, 69 herc_close, 70 gx_default_map_rgb_color, 71 gx_default_map_color_rgb, 72 herc_fill_rectangle, 73 gx_default_tile_rectangle, 74 herc_copy_mono, 75 herc_copy_color 76 }; 77 78 gx_device far_data gs_herc_device = { 79 std_device_std_body(gx_device, &herc_procs, "herc", 80 screen_size_x, screen_size_y, 81 /* The following parameters map an appropriate fraction of */ 82 /* the screen to a full-page coordinate space. */ 83 /* This may or may not be what is desired! */ 84 (screen_size_y * aspect_ratio) / PAGE_HEIGHT_INCHES, /* x dpi */ 85 screen_size_y / PAGE_HEIGHT_INCHES /* y dpi */ 86 ) 87 }; 88 89 90 /* Forward declarations */ 91 private int herc_get_mode(void); 92 private void herc_set_mode(int); 93 94 /* Save the HERC mode */ 95 private int herc_save_mode = -1; 96 97 /* Reinitialize the herc for text mode */ 98 int 99 herc_close(gx_device *dev) 100 { if ( herc_save_mode >= 0 ) herc_set_mode(herc_save_mode); 101 return 0; 102 } 103 104 /* ------ Internal routines ------ */ 105 106 /* Read the device mode */ 107 private int 108 herc_get_mode(void) 109 { registers regs; 110 regs.h.ah = 0xf; 111 int86(0x10, ®s, ®s); 112 return regs.h.al; 113 } 114 115 /* Set the device mode */ 116 private void 117 herc_set_mode(int mode) 118 { registers regs; 119 regs.h.ah = 0; 120 regs.h.al = mode; 121 int86(0x10, ®s, ®s); 122 } 123 124 125 /****************************************************************/ 126 /* Hercules graphics card functions */ 127 /* */ 128 /* -- Taken from Jan/Feb 1988 issue of Micro Cornucopia #39 */ 129 /* */ 130 /* --rewritten for MSC 5.1 on 02/18/91 by Phillip Conrad */ 131 /****************************************************************/ 132 133 134 static const char paramg[12] = {0x35, 0x2d, 0x2e, 0x07, 0x5b, 0x02, 135 0x57, 0x57, 0x02, 0x03, 0x00, 0x00}; 136 /* (Never used) 137 static const char paramt[12] = {0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 138 0x19, 0x19, 0x02, 0x0d, 0x0b, 0x0c}; 139 */ 140 141 /* Type and macro for frame buffer pointers. */ 142 /*** Intimately tied to the 80x86 (x<2) addressing architecture. ***/ 143 typedef byte far *fb_ptr; 144 # define mk_fb_ptr(x, y)\ 145 (fb_ptr)((regen) + ((0x2000 * ((y) % 4) + (90 * ((y) >> 2))) + ((int)(x) >> 3))) 146 147 148 /* Structure for operation parameters. */ 149 /* Note that this structure is known to assembly code. */ 150 /* Not all parameters are used for every operation. */ 151 typedef struct rop_params_s { 152 fb_ptr dest; /* pointer to frame buffer */ 153 int draster; /* raster of frame buffer */ 154 const byte far *src; /* pointer to source data */ 155 int sraster; /* source raster */ 156 int width; /* width in bytes */ 157 int height; /* height in scan lines */ 158 int shift; /* amount to right shift source */ 159 int invert; /* 0 or -1 to invert source */ 160 int data; /* data for fill */ 161 int x_pos; /*>>added--2/24/91 */ 162 int y_pos; 163 } rop_params; 164 165 /* Define the device port and register numbers, and the regen map base */ 166 #define seq_addr 0x3b4 /* changed for HERC card (6845 ports)*/ 167 #define graph_mode 0x3b8 168 #define graph_stat 0x3ba 169 #define graph_config 0x3bf 170 171 #ifndef regen 172 #define regen 0xa0000000L 173 #endif 174 175 176 /* Initialize the display for Hercules graphics mode */ 177 int 178 herc_open(gx_device *dev) 179 { int i; 180 if ( herc_save_mode < 0 ) herc_save_mode = herc_get_mode(); 181 /* herc_set_mode(graphics_video_mode); */ 182 outportb(graph_config,3); 183 for(i=0;i<sizeof(paramg);i++) 184 { 185 outport2(seq_addr,i,paramg[i]); 186 187 } 188 outportb(graph_mode,0x0a); /* set page 0 */ 189 for(i=0;i<0x3FFFL;i++) /* clear the screen */ 190 { 191 int far *loc = (int far *)( regen +(2L*i)); 192 *loc = 0; 193 } 194 195 return 0; 196 } 197 198 /* Macro for testing bit-inclusion */ 199 #define bit_included_in(x,y) !((x)&~(y)) 200 201 /* Copy a monochrome bitmap. The colors are given explicitly. */ 202 /* Color = gx_no_color_index means transparent (no effect on the image). */ 203 int 204 herc_copy_mono(gx_device *dev, 205 const byte *base, int sourcex, int raster, gx_bitmap_id id, 206 int x, int y, int w, int h, gx_color_index izero, gx_color_index ione) 207 { rop_params params; 208 #define czero (int)izero 209 #define cone (int)ione 210 int dleft, sleft, count; 211 int invert, zmask, omask; 212 byte mask, rmask; 213 214 if ( cone == czero ) /* vacuous case */ 215 return herc_fill_rectangle(dev, x, y, w, h, izero); 216 217 /* clip */ 218 fit_copy(dev, base, sourcex, raster, id, x, y, w, h); 219 params.dest = mk_fb_ptr(x, y); 220 params.draster = raster_x; 221 params.src = base + (sourcex >> 3); 222 params.sraster = raster; 223 params.height = h; 224 params.shift = (x - sourcex) & 7; 225 params.y_pos = y; 226 params.x_pos = x; 227 params.width = w; 228 229 if(czero > cone) params.invert = -1; 230 231 /* Macros for writing partial bytes. */ 232 /* bits has already been inverted by xor'ing with invert. */ 233 234 #define write_byte_masked(ptr, bits, mask)\ 235 *ptr = ((bits | ~mask | zmask) & (*ptr | (bits & mask & omask))) 236 237 #define write_byte(ptr, bits)\ 238 *ptr = ((bits | zmask) & (*ptr | (bits & omask))) 239 240 invert = (czero == 1 || cone == 0 ? -1 : 0); 241 /* invert = (czero == 1 || cone == 1 ? -1 : 0); */ 242 zmask = (czero == 0 || cone == 0 ? 0 : -1); 243 omask = (czero == 1 || cone == 1 ? -1 : 0); 244 245 #undef czero 246 #undef cone 247 248 /* Actually copy the bits. */ 249 250 sleft = 8 - (sourcex & 7); 251 dleft = 8 - (x & 7); 252 mask = 0xff >> (8 - dleft); 253 count = w; 254 if ( w < dleft ) 255 mask -= mask >> w, 256 rmask = 0; 257 else 258 rmask = 0xff00 >> ((w - dleft) & 7); 259 260 if (sleft == dleft) /* optimize the aligned case */ 261 { 262 w -= dleft; 263 while ( --h >= 0 ) 264 { 265 register const byte *bptr = params.src; 266 register byte *optr = mk_fb_ptr(params.x_pos,params.y_pos); 267 register int bits = *bptr ^ invert; /* first partial byte */ 268 269 count = w; 270 271 write_byte_masked(optr, bits, mask); 272 273 /* Do full bytes. */ 274 275 while ((count -= 8) >= 0) 276 { 277 bits = *++bptr ^ invert; 278 params.x_pos += 8; 279 optr = mk_fb_ptr(params.x_pos,params.y_pos); 280 write_byte(optr, bits); 281 } 282 /* Do last byte */ 283 284 if (count > -8) 285 { 286 bits = *++bptr ^ invert; 287 params.x_pos += 8; 288 optr = mk_fb_ptr(params.x_pos,params.y_pos); 289 write_byte_masked(optr, bits, rmask); 290 } 291 /* dest += BPL; */ 292 params.y_pos++; 293 params.x_pos = x; 294 params.src += raster; 295 } 296 } 297 else 298 { 299 int skew = (sleft - dleft) & 7; 300 int cskew = 8 - skew; 301 302 while (--h >= 0) 303 { 304 const byte *bptr = params.src; 305 byte *optr = mk_fb_ptr(params.x_pos,params.y_pos); 306 register int bits; 307 308 count = w; 309 310 /* Do the first partial byte */ 311 312 if (sleft >= dleft) 313 { 314 bits = *bptr >> skew; 315 } 316 else /* ( sleft < dleft ) */ 317 { 318 bits = *bptr++ << cskew; 319 if (count > sleft) 320 bits += *bptr >> skew; 321 } 322 bits ^= invert; 323 write_byte_masked(optr, bits, mask); 324 count -= dleft; 325 params.x_pos += 8; 326 optr = mk_fb_ptr(params.x_pos,params.y_pos); 327 328 /* Do full bytes. */ 329 330 while ( count >= 8 ) 331 { 332 bits = *bptr++ << cskew; 333 bits += *bptr >> skew; 334 bits ^= invert; 335 write_byte(optr, bits); 336 count -= 8; 337 params.x_pos += 8; 338 optr = mk_fb_ptr(params.x_pos,params.y_pos); 339 } 340 341 /* Do last byte */ 342 343 if (count > 0) 344 { 345 bits = *bptr++ << cskew; 346 if (count > skew) 347 bits += *bptr >> skew; 348 bits ^= invert; 349 write_byte_masked(optr, bits, rmask); 350 } 351 /* dest += BPL; 352 line += raster; 353 */ 354 params.y_pos++; 355 params.x_pos = x; 356 params.src += raster; 357 } 358 } 359 return 0; 360 } 361 362 /* Copy a color pixelmap. This is just like a bitmap, */ 363 int 364 herc_copy_color(gx_device *dev, 365 const byte *base, int sourcex, int raster, gx_bitmap_id id, 366 int x, int y, int w, int h) 367 { return herc_copy_mono(dev, base, sourcex, raster, id, 368 x, y, w, h,(gx_color_index)0, (gx_color_index)1); 369 } 370 371 # define mk_fb_yptr(x, y)\ 372 (fb_ptr)((regen) + ((0x2000 * ((y) % 4) + (90 * ((y) >> 2))) + x)) 373 374 /* Fill a rectangle. */ 375 int 376 herc_fill_rectangle(gx_device *dev, int x, int y, int w, int h, 377 gx_color_index color) 378 { rop_params params; 379 380 int x2, y2, xlen; 381 byte led, red, d; 382 byte far *ptr; 383 int xloc; 384 385 fit_fill(dev, x, y, w, h); 386 387 params.dest = mk_fb_ptr(x, y); 388 params.y_pos = y; 389 params.x_pos = x; 390 391 x2 = x + w - 1; 392 y2 = y + h - 1; 393 394 xlen = (x2 >> 3) - (x >> 3) - 1; 395 led = 0xff >> (x & 7); 396 red = 0xff << (7 - (x2 & 7)); 397 398 ptr = mk_fb_ptr(x,y); 399 400 if (color) 401 { 402 /* here to set pixels */ 403 404 if (xlen == -1) 405 { 406 /* special for rectangles that fit in a byte */ 407 408 d = led & red; 409 for(; h >= 0; h--, ptr = mk_fb_ptr(x,params.y_pos)) 410 { 411 *ptr |= d; 412 params.y_pos++; 413 } 414 return 0; 415 } 416 417 /* normal fill */ 418 419 xloc = params.x_pos >> 3; 420 for(; h >= 0; h--, ptr = mk_fb_ptr(x,params.y_pos)) 421 { register int x_count = xlen; 422 register byte far *p = ptr; 423 *p |= led; 424 /* params.x_pos += 8; */ 425 xloc++; 426 p = mk_fb_yptr(xloc,params.y_pos); 427 while ( x_count-- ) { 428 *p = 0xff; 429 /* params.x_pos += 8; */ 430 xloc++; 431 p = mk_fb_yptr(xloc,params.y_pos); 432 } 433 *p |= red; 434 /* params.x_pos = x; */ 435 xloc = params.x_pos >> 3; 436 params.y_pos++; 437 } 438 } 439 440 /* here to clear pixels */ 441 442 led = ~led; 443 red = ~red; 444 445 if (xlen == -1) 446 { 447 /* special for rectangles that fit in a byte */ 448 449 d = led | red; 450 for(; h >= 0; h--, ptr = mk_fb_ptr(x,params.y_pos)) 451 { 452 *ptr &= d; 453 params.y_pos++; 454 } 455 return 0; 456 } 457 458 /* normal fill */ 459 460 xloc = x >> 3; 461 for(; h >= 0; h--, ptr = mk_fb_ptr(x,params.y_pos)) 462 { register int x_count = xlen; 463 register byte far *p = ptr; 464 *p &= led; 465 /* params.x_pos += 8; */ 466 xloc++; 467 p = mk_fb_yptr(xloc,params.y_pos); 468 while ( x_count-- ) { 469 *p = 0x00; 470 /* params.x_pos += 8; */ 471 xloc++; 472 p = mk_fb_yptr(xloc,params.y_pos); 473 } 474 *p &= red; 475 /* params.x_pos = x; */ 476 xloc = params.x_pos >> 3; 477 params.y_pos++; 478 } 479 return 0; 480 } 481