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