Fastgraph (tm) User's Guide Ted Gruber Software PO Box 13408 Las Vegas, NV 89112 (702) 735-1980 Copyright (c) 1991,1992 by Ted Gruber Software. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted by any means, electronic, mechanical, photocopying, recording, or otherwise, without express written permission from Ted Gruber Software. The software described in this publication is furnished under a license agreement and may be used or copied only in accordance with the terms of that agreement. This publication and its associated software are sold without warranties, either expressed or implied, regarding their merchantability or fitness for any particular application or purpose. The information in this publication is subject to change without notice and does not represent a commitment on the part of Ted Gruber Software. In no event shall Ted Gruber Software be liable for any loss of profit or any other commercial damage, including but not limited to special, incidental, consequential, or other damages resulting from the use of or the inability to use this product, even if Ted Gruber Software has been notified of the possibility of such damages. Second Printing, January 1992 Fastgraph version 2.10 Fastgraph/Light version 1.10 DFI is a registered trademark of Diamond Flower Electric Instrument Co., Inc. Fastgraph and Fastgraph/Light are trademarks of Ted Gruber Software. Hercules is a trademark of Hercules Computer Technology. IBM, IBM PC, IBM PC/XT, IBM PC/AT, PS/2, PCjr, and PC-DOS are registered trademarks of International Business Machines, Inc. Intel is a registered trademark of Intel Corporation. Logitech is a trademark of LOGITECH, Inc. Microsoft, Microsoft Mouse, and MS-DOS are registered trademarks of Microsoft Corporation. PC Paintbrush is a registered trademark of ZSoft, Inc. QuickBASIC and QuickC are trademarks of Microsoft Corporation. Tandy is a registered trademark of Tandy Corporation. Turbo C and Turbo Pascal are registered trademarks of Borland International, Inc. All other brand and product names mentioned in this publication are trademarks or registered trademarks of their respective holders. T a b l e o f C o n t e n t s Chapter 1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 1 What is Fastgraph? . . . . . . . . . . . . . . . . . . . . . . . . . 2 Fastgraph/Light . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Prerequisite Knowledge . . . . . . . . . . . . . . . . . . . . . . . 2 Supported Compilers . . . . . . . . . . . . . . . . . . . . . . . . 3 Memory Models . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Installing Fastgraph . . . . . . . . . . . . . . . . . . . . . . . . 4 Fastgraph Naming Conventions . . . . . . . . . . . . . . . . . . . . 4 Compilation and Linking . . . . . . . . . . . . . . . . . . . . . . 5 Borland C++ . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Microsoft C . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Microsoft FORTRAN . . . . . . . . . . . . . . . . . . . . . . . 9 Microsoft QuickBASIC . . . . . . . . . . . . . . . . . . . . . 10 Microsoft QuickC . . . . . . . . . . . . . . . . . . . . . . . 11 Power C . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Turbo C and Turbo C++ . . . . . . . . . . . . . . . . . . . . . 14 Turbo Pascal . . . . . . . . . . . . . . . . . . . . . . . . . 15 Fastgraph/Light Video Driver . . . . . . . . . . . . . . . . . . . . 16 Chapter 2 PC and PS/2 Video Modes . . . . . . . . . . . . . . . . . . . 17 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Text Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Graphics Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 CGA Graphics Modes . . . . . . . . . . . . . . . . . . . . . . 21 Tandy 1000 and PCjr Graphics Modes . . . . . . . . . . . . . . 22 Hercules Graphics Modes . . . . . . . . . . . . . . . . . . . . 22 EGA Graphics Modes . . . . . . . . . . . . . . . . . . . . . . 23 VGA and MCGA Graphics Modes . . . . . . . . . . . . . . . . . . 24 Chapter 3 Initializing the Video Environment . . . . . . . . . . . . . . 27 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Establishing a Text Mode . . . . . . . . . . . . . . . . . . . . . . 28 43-line and 50-line Text Modes . . . . . . . . . . . . . . . . . . . 31 Establishing a Graphics Mode . . . . . . . . . . . . . . . . . . . . 32 Summary of Video Initialization Routines . . . . . . . . . . . . . . 36 Chapter 4 Coordinate Systems . . . . . . . . . . . . . . . . . . . . . . 39 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Character Space . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Screen Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 World Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Conversion Routines . . . . . . . . . . . . . . . . . . . . . . . . 44 Summary of Coordinate Routines . . . . . . . . . . . . . . . . . . . 44 Chapter 5 The Use of Color . . . . . . . . . . . . . . . . . . . . . . . 47 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Text Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Color Modes . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Monochrome Mode . . . . . . . . . . . . . . . . . . . . . . . . 49 Graphics Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 CGA Color Modes . . . . . . . . . . . . . . . . . . . . . . . . 51 CGA Two-Color Mode . . . . . . . . . . . . . . . . . . . . . . 52 Tandy and PCjr Modes . . . . . . . . . . . . . . . . . . . . . 53 Hercules Mode . . . . . . . . . . . . . . . . . . . . . . . . . 54 iii Hercules Low-Resolution Mode . . . . . . . . . . . . . . . . . 55 EGA 200-Line Modes . . . . . . . . . . . . . . . . . . . . . . 56 EGA Monochrome Mode . . . . . . . . . . . . . . . . . . . . . . 58 EGA Enhanced Mode . . . . . . . . . . . . . . . . . . . . . . . 59 VGA and MCGA Two-Color Mode . . . . . . . . . . . . . . . . . . 61 VGA 16-Color Mode . . . . . . . . . . . . . . . . . . . . . . . 63 VGA and MCGA 256-Color Modes . . . . . . . . . . . . . . . . . 64 RGB Color Mapping . . . . . . . . . . . . . . . . . . . . . . . . . 68 Defining All Palette Registers . . . . . . . . . . . . . . . . . . . 69 Virtual Colors . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 A Multiple-Mode Example . . . . . . . . . . . . . . . . . . . . . . 71 Summary of Color-Related Routines . . . . . . . . . . . . . . . . . 73 Chapter 6 Graphics Fundamentals . . . . . . . . . . . . . . . . . . . . 75 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Clearing the Screen . . . . . . . . . . . . . . . . . . . . . . . . 76 Clipping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 The Graphics Cursor . . . . . . . . . . . . . . . . . . . . . . . . 79 Solid Lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Dashed Lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Polygons, Circles, and Ellipses . . . . . . . . . . . . . . . . . . 83 Solid Rectangles . . . . . . . . . . . . . . . . . . . . . . . . . . 86 Unfilled Rectangles . . . . . . . . . . . . . . . . . . . . . . . . 87 Dithered Rectangles . . . . . . . . . . . . . . . . . . . . . . . . 88 Region Fill . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Summary of Fundamental Graphics Routines . . . . . . . . . . . . . . 96 Chapter 7 Character Display Routines . . . . . . . . . . . . . . . . . . 99 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Character Space . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Hardware Characters . . . . . . . . . . . . . . . . . . . . . . . . 101 Conversion Routines . . . . . . . . . . . . . . . . . . . . . . . . 107 Software Characters . . . . . . . . . . . . . . . . . . . . . . . . 108 Bit-Mapped Characters . . . . . . . . . . . . . . . . . . . . . . . 114 Summary of Character Display Routines . . . . . . . . . . . . . . . 114 Chapter 8 Video Page Management . . . . . . . . . . . . . . . . . . . . 117 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Physical Pages and Virtual Pages . . . . . . . . . . . . . . . . . . 118 Pages With Special Meanings . . . . . . . . . . . . . . . . . . . . 119 Some Simple Examples . . . . . . . . . . . . . . . . . . . . . . . . 119 Text Cursors . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 Obtaining Video Page Information . . . . . . . . . . . . . . . . . . 127 Considerations for Virtual Pages . . . . . . . . . . . . . . . . . . 128 Logical Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 Video Page Resizing . . . . . . . . . . . . . . . . . . . . . . . . 131 Summary of Video Page Management Routines . . . . . . . . . . . . . 132 Chapter 9 Images and Image Management . . . . . . . . . . . . . . . . . . 135 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Mode-Independent Bit-Mapped Images . . . . . . . . . . . . . . . . . 136 Mode-Specific Bit-Mapped Images . . . . . . . . . . . . . . . . . . 140 Regular Images . . . . . . . . . . . . . . . . . . . . . . . . 141 Clipped Images . . . . . . . . . . . . . . . . . . . . . . . . 148 Reversed Images . . . . . . . . . . . . . . . . . . . . . . . . 149 iv Reversed Clipped Images . . . . . . . . . . . . . . . . . . . . 149 Some Examples . . . . . . . . . . . . . . . . . . . . . . . . . 149 Pixel Run Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 Display Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . 158 PCX Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 Masking Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Retrieving Images . . . . . . . . . . . . . . . . . . . . . . . . . 169 Byte Boundaries . . . . . . . . . . . . . . . . . . . . . . . . . . 174 Image Transfer Routines . . . . . . . . . . . . . . . . . . . . . . 175 Summary of Image Display Routines . . . . . . . . . . . . . . . . . 184 Chapter 10 Animation Techniques . . . . . . . . . . . . . . . . . . . . 187 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 Simple Animation . . . . . . . . . . . . . . . . . . . . . . . . . . 188 XOR Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . 190 Static Frame Animation . . . . . . . . . . . . . . . . . . . . . . . 192 Dynamic Frame Animation . . . . . . . . . . . . . . . . . . . . . . 194 Page Flipping . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 Summary of Animation Techniques . . . . . . . . . . . . . . . . . . 198 Chapter 11 Special Effects . . . . . . . . . . . . . . . . . . . . . . . 199 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 Screen Dissolving . . . . . . . . . . . . . . . . . . . . . . . . . 200 Scrolling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Changing the Screen Origin . . . . . . . . . . . . . . . . . . . . . 205 Summary of Special Effects Routines . . . . . . . . . . . . . . . . 208 Chapter 12 Input Device Support . . . . . . . . . . . . . . . . . . . . 209 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 Keyboard Support . . . . . . . . . . . . . . . . . . . . . . . . . . 210 Reading Keystrokes . . . . . . . . . . . . . . . . . . . . . . 212 Testing and Setting Key States . . . . . . . . . . . . . . . . 213 Mouse Support . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 Initializing the Mouse . . . . . . . . . . . . . . . . . . . . 215 Controlling the Mouse Cursor . . . . . . . . . . . . . . . . . 216 Reporting the Mouse Status . . . . . . . . . . . . . . . . . . 218 Defining the Mouse Cursor . . . . . . . . . . . . . . . . . . . 220 Joystick Support . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Initializing Joysticks . . . . . . . . . . . . . . . . . . . . 227 Reporting Joystick Status . . . . . . . . . . . . . . . . . . . 227 Keyboard Emulation . . . . . . . . . . . . . . . . . . . . . . 229 Special Joystick Considerations . . . . . . . . . . . . . . . . 230 Summary of Input Routines . . . . . . . . . . . . . . . . . . . . . 231 Chapter 13 Sound Effects . . . . . . . . . . . . . . . . . . . . . . . . 233 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 Sound Sources . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 Synchronous Sound . . . . . . . . . . . . . . . . . . . . . . . . . 234 Asynchronous Sound . . . . . . . . . . . . . . . . . . . . . . . . . 239 Summary of Sound Routines . . . . . . . . . . . . . . . . . . . . . 244 Chapter 14 Program Timing . . . . . . . . . . . . . . . . . . . . . . . 247 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 Real-Time Routines . . . . . . . . . . . . . . . . . . . . . . . . . 248 Routines Dependent on the System Speed . . . . . . . . . . . . . . . 249 Summary of Timing Routines . . . . . . . . . . . . . . . . . . . . . 251 v Chapter 15 Miscellaneous Routines . . . . . . . . . . . . . . . . . . . 253 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 Determining Available Memory . . . . . . . . . . . . . . . . . . . . 254 Choosing the Video Memory Update Function . . . . . . . . . . . . . 255 Summary of Miscellaneous Routines . . . . . . . . . . . . . . . . . 256 Appendix A Fastgraph Utilities . . . . . . . . . . . . . . . . . . . . . 257 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 SNAPSHOT Utility . . . . . . . . . . . . . . . . . . . . . . . . . . 258 CLIP Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 CONVERT Utility . . . . . . . . . . . . . . . . . . . . . . . . . . 261 EDITSPR Utility . . . . . . . . . . . . . . . . . . . . . . . . . . 261 GrabRGB Utility . . . . . . . . . . . . . . . . . . . . . . . . . . 262 HERCFIX Utility . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Appendix B Using Fastgraph from Assembly Language . . . . . . . . . . . 265 Appendix C Interrupts and Fastgraph . . . . . . . . . . . . . . . . . . 269 Interrupts Used by Fastgraph . . . . . . . . . . . . . . . . . . . . 270 Extending the Time-of-Day Interrupt . . . . . . . . . . . . . . . . 270 Appendix D Contents of the Compiler-Specific Libraries . . . . . . . . . 277 vi Chapter 1 Introduction 2 Fastgraph User's Guide What is Fastgraph? Fastgraph is a library of more than 170 highly-optimized routines that are callable from high-level and assembly language programs running under the MS-DOS or PC-DOS operating systems. This collection of routines provides a programmer with proven, powerful tools to take command of the PC and PS/2 video environment. In addition to its video support, Fastgraph also contains routines to perform keyboard, mouse, and joystick control, as well as music and sound capabilities. Fastgraph is an ideal development tool for entertainment and educational software, presentation graphics products, scientific and engineering applications, CAD/CAM, animation, or any application that demands robust graphics. As its name implies, the most notable feature of Fastgraph is its speed. Virtually all of Fastgraph is written in 8086 assembly language, and each routine has been optimized by hand to provide maximum performance. Fastgraph supports all the standard text and graphics video modes used by the IBM PC (PC, PC/XT, and PC/AT) and PS/2 families and compatible systems. In addition, Fastgraph provides support for four extended VGA graphics modes and a 16-color graphics mode unique to Tandy 1000 series computers and the PCjr. Even though the graphics mode of the Hercules Graphics Card is not an IBM standard, its popularity has made it a de facto standard, and for this reason Fastgraph also supports it. A complete discussion of all of Fastgraph's supported video modes appears in the next chapter. Fastgraph/Light Fastgraph/Light is a subset of Fastgraph. It includes all of Fastgraph's features except the redefinable world space coordinate system and the routines pertaining to software characters. Programs created using Fastgraph/Light are 100% source code compatible with Fastgraph. The most important difference between Fastgraph/Light and Fastgraph is the method of running a program created with the two products. With Fastgraph, any of its routines used in your program are linked directly into the resulting .EXE file. With Fastgraph/Light, however, this is not the case. Instead, the Fastgraph/Light routines provide an interface to an external driver, called the Fastgraph/Light Video Driver, which must be loaded separately before running programs that call any Fastgraph/Light routines. A further discussion of this driver begins on page 16. In this document, and in the accompanying Fastgraph Reference Manual, references to Fastgraph also apply to Fastgraph/Light unless stated otherwise. Prerequisite Knowledge Fastgraph is a programming tool, which means programmers are its intended audience. For this reason, the Fastgraph User's Guide and the accompanying Fastgraph Reference Manual assume you have a knowledge of programming. Additionally, a knowledge of converting numbers between binary, decimal, and hexadecimal is assumed. Chapter 1: Introduction 3 Virtually all the examples in this manual are written in the C programming language, so a knowledge of C would be especially helpful. The examples intentionally avoid using any of C's features and idioms that might not be readily apparent to a programmer unfamiliar with C. Finally, we'd like to point out that the examples are intended to be read not by themselves, but as part of the surrounding text. Supported Compilers You can use Fastgraph with any compilers or assemblers that use the same calling and naming conventions as the small, medium, or large memory models of the supported compilers. Mixed language programming is allowed where supported by the language translators and linker being used. Fastgraph supports the following compilers: Borland C++ (version 2.0 or later) Microsoft C (version 5.0 or later) Microsoft FORTRAN (version 4.0 or later) Microsoft QuickBASIC (version 4.0 or later) Microsoft QuickC (version 2.0 or later) Power C (version 2.0 or later) Turbo C or Turbo C++ (version 2.0 or later) Turbo Pascal (version 6.0 or later) The listed version numbers are the compiler versions under which Fastgraph was developed and tested. Fastgraph may or may not work with earlier versions of these compilers. The use of Fastgraph from assembly language programs is addressed in Appendix B. Memory Models All of Fastgraph's supported compilers except QuickBASIC and Turbo Pascal offer several memory models. A memory model defines how memory is set up for a program's code and data segments. Fastgraph includes libraries for the small, medium, and large memory models. The small memory model allows for one code segment and one data segment. Programs that use the small model can thus have a maximum of 64K bytes of code and 64K bytes of data. Because the small model implements call instructions and data references through near pointers, it produces the most efficient code of the three supported memory models. The medium memory model allows for multiple code segments and one data segment. Programs that use the medium model thus have no compiler-imposed limit to the code size (although no one segment can exceed 64K bytes) and a maximum of 64K bytes of data. Like the small model, the medium model implements data references through near pointers, but it implements call instructions through far pointers. The use of far pointers adds two bytes of code and 13 clock cycles for each subprogram call. The medium model is a popular choice among programmers. The large memory model supports multiple code and data segments. Programs that use the large model do not have any compiler-imposed limits for code and data sizes. However, no single code or data segment can exceed 64K bytes. Because the large model implements call instructions and data 4 Fastgraph User's Guide references through far pointers, it produces the least efficient code of the three supported memory models. For more information about memory models, please refer to the user's guide or reference manual for the compilers you'll be using with Fastgraph. Installing Fastgraph This section explains how to use the INSTALL program to load Fastgraph (or Fastgraph/Light) and its related files on a hard disk. The installation program lets you select the compilers and memory models you wish to use with Fastgraph. It also gives you the opportunity to load many example Fastgraph programs specific to the compilers you choose. Before you start the installation, you should use the DOS commands COPY or DISKCOPY to make working copies of the Fastgraph distribution disks (refer to your DOS reference manual if you are unfamiliar with these commands). Once you have created the working copies, store the original disks in a safe place. Install Fastgraph from the working copies you just created. For simplicity, we'll assume you are installing Fastgraph from the diskette drive A: to the hard drive C:, but you can of course use any available drives. The Fastgraph distribution disk labeled Installation and Utilities contains Fastgraph's INSTALL program. Place this disk in the A: drive, make A: your current drive, and enter the command INSTALL, as shown below. C> A: A> INSTALL From this point, just follow the directions on each screen. At any time, you can press the Esc key to abort the installation. The INSTALL program will ask you for the compilers and memory models you'll use with Fastgraph, as well as the directory names for the Fastgraph utilities, libraries, and include files. For the utilities, the default directory is C:\FG. For the include files and libraries, we recommend using directories where the compiler you've chosen normally searches for such files. INSTALL will automatically try to determine these directories and propose them as defaults. You can install support for additional compilers or memory models at any time. If you choose to do this, you should use the command INSTALL /L to avoid copying the files common to all compilers and memory models. Fastgraph Naming Conventions The names of all Fastgraph routines begin with the three characters "fg_". This prefix helps identify Fastgraph routines within a program, and it also reduces the chance of name conflicts that might otherwise occur between Fastgraph and other third party libraries. Because QuickBASIC does not permit underscores in identifiers, the QuickBASIC versions of Fastgraph routines begin with the two characters "FG". Chapter 1: Introduction 5 For example, the fg_version routine is named FGversion in the QuickBASIC libraries. All subsequent references to Fastgraph routines in this manual and the accompanying Fastgraph Reference Manual will use the fg_ naming convention instead of the QuickBASIC names. Compilation and Linking To build an executable (.EXE) file for a program that uses Fastgraph routines, first compile or assemble the program using the small, medium, or large memory model. This step produces an object file, which is then linked with Fastgraph and any other object libraries to produce an executable file. Examples 1-1 through 1-4 use the Fastgraph routine fg_version to display the version number for your copy of Fastgraph. These examples are respectively written in the four high-level languages Fastgraph supports: C/C++, BASIC, FORTRAN, and Pascal. If you loaded the example programs when you installed Fastgraph, the files \FG\EXAMPLES\01-01.C, 01-02.BAS, 01-03.FOR, and 01-04.PAS contain the source code for these examples. You can use them to test the compilation and linking process for the memory models and compilers you'll be using with Fastgraph. Example 1-1. #include #include void main(void); void main() { int major; int minor; fg_version(&major,&minor); printf("This is version %d.%2.2d of Fastgraph.\n",major,minor); } The file FASTGRAF.H contains the C function prototypes for each Fastgraph routine. It should reside in a directory where the compiler normally searches for other .H files. For Microsoft C and QuickC, FASTGRAF.H can reside in any of the directories specified by the INCLUDE environment variable. For Power C, it can reside in any of the directories specified by the /i switch in the PCOPTION environment variable. Example 1-2. REM $INCLUDE: 'fastgraf.bi' DEFINT A-Z FGversion Major, Minor Version! = Major + Minor*0.01 PRINT USING "This is version #.## of Fastgraph."; Version! END 6 Fastgraph User's Guide You must include the DECLARE commands in the file FASTGRAF.BI at the beginning of each QuickBASIC module. This file should reside in the directory where the compiler normally searches for other .BI files, or in any of the directories specified by the INCLUDE environment variable. The DECLARE commands in this file automatically provide the calling convention and naming convention for each Fastgraph routine. In addition, they relieve the QuickBASIC programmer of distinguishing arguments passed by value from those passed by reference. Example 1-3. $INCLUDE: '\FG\INTRFACE.FOR' PROGRAM MAIN INTEGER*2 MAJOR INTEGER*2 MINOR CALL FG_VERSION (MAJOR, MINOR) WRITE (6,10) MAJOR, MINOR 10 FORMAT (' This is version ', I1, '.', I2.2, ' of Fastgraph.') STOP ' ' END You must include the INTERFACE statements in the file INTRFACE.FOR at the beginning of your program (this file should reside in the \FG directory). The INTERFACE statements in this file automatically provide the calling convention and naming convention for each Fastgraph routine. In addition, they relieve the FORTRAN programmer of distinguishing arguments passed by value from those passed by reference. Example 1-4. program main; uses fgtp; var Major : integer; Minor : integer; begin fg_version(Major,Minor); writeln('This is version ',Major,'.',Minor:2,' of Fastgraph.'); end. Turbo Pascal programs that use Fastgraph or Fastgraph/Light must include a uses statement specifying the name of the Fastgraph unit, FGTP. In addition, if the program calls any of the compiler-specific Fastgraph routines listed in Appendix D, the uses statement also must include the name of the extended Fastgraph unit, FGTPX. The unit files must reside in a directory where Turbo Pascal normally searches for units. Chapter 1: Introduction 7 The following sections show the simplest compilation and linking procedures for the supported compilers. In what follows, items enclosed in angle brackets, such as , are placeholders for parameters you must supply (the name of a file in this case). Items enclosed in square brackets, such as [/E], are optional. Borland C++ Borland C++ allows you to compile and link a program directly from the DOS command line, or from within its integrated development environment (IDE). To use Fastgraph from the IDE, you must make sure the compiler options match one of Fastgraph's available memory models (small, medium, or large) and then create a project file that links with the corresponding Fastgraph libraries (as listed below). You also can compile and link a Borland C++ program from the DOS command line using the BCC command. The format of the BCC command for compiling a program and linking it with Fastgraph is BCC [] where: specifies the compiler memory model you'll be using. It must be either -ms (for the small model), -mm (for the medium model), or -ml (for the large model). is the name of the file containing your program. It may include a path specification. is the name of a standard Fastgraph/Light or Fastgraph library. For Fastgraph/Light, the library name is FGLS.LIB (for the small model), FGLM.LIB (for the medium model), or FGLL.LIB (for the large model). For Fastgraph, the library name is FGS.LIB (for the small model), FGM.LIB (for the medium model), or FGL.LIB (for the large model). is the name of an optional compiler-specific extended Fastgraph library. You need to specify an extended library name only if your program calls any of the Fastgraph routines listed in Appendix D. The extended library name is FGTCS.LIB (for the small model), FGTCM.LIB (for the medium model), or FGTCL.LIB (for the large model). Fastgraph/Light does not use extended libraries. For example, to compile the program 01-01.C under the medium memory model and then link it with Fastgraph, you could use the following BCC command: BCC -mm 01-01.C FGM.LIB FGTCM.LIB 8 Fastgraph User's Guide Although we specified the extended library name FGTCM.LIB on the command line, we didn't need to in this example because the program doesn't call any of the compiler-specific Fastgraph routines listed in Appendix D. If you were using Fastgraph/Light instead of Fastgraph, the BCC command would be: BCC -mm 01-01.C FGLM.LIB For more information about memory models or other compilation and linking options, please refer to the Borland C++ User's Guide, published by Borland International. Microsoft C Microsoft C programs are compiled and linked by entering a CL command at the DOS command prompt. The format of the CL command for compiling a program and linking it with Fastgraph is CL /link [] [/E] where: specifies the compiler memory model you'll be using. It must be either /AS (for the small model), /AM (for the medium model), or /AL (for the large model). is the name of the file containing your program. It must include the file extension (typically .C) and may include a path specification. is the name of a standard Fastgraph/Light or Fastgraph library. For Fastgraph/Light, the library name is FGLS (for the small model), FGLM (for the medium model), or FGLL (for the large model). For Fastgraph, the library name is FGS (for the small model), FGM (for the medium model), or FGL (for the large model). is the name of an optional compiler-specific extended Fastgraph library. You need to specify an extended library name only if your program calls any of the Fastgraph routines listed in Appendix D. The extended library name is FGMSCS (for the small model), FGMSCM (for the medium model), or FGMSCL (for the large model). Fastgraph/Light does not use extended libraries. The /E linker option is not required but will produce a smaller .EXE file if specified. Chapter 1: Introduction 9 For example, to compile the program 01-01.C under the medium memory model and then link it with Fastgraph, you could use the following CL command: CL /AM 01-01.C /link FGM FGMSCM /E Although we specified the extended library name FGMSCM on the command line, we didn't need to in this example because the program doesn't call any of the compiler-specific Fastgraph routines listed in Appendix D. If you were using Fastgraph/Light instead of Fastgraph, the CL command would be: CL /AM 01-01.C /link FGLM /E For more information about memory models or other compilation and linking options, please refer to the Microsoft C Optimizing Compiler User's Guide, published by Microsoft Corporation. Microsoft FORTRAN Microsoft FORTRAN programs are compiled and linked by entering an FL command at the DOS command prompt. The format of the FL command for compiling a program and linking it with Fastgraph is FL /FPi /4I2 /4Nt /link [] [/E] where: specifies the compiler memory model you'll be using. It must be either /AM (for the medium model) or /AL (for the large model). Microsoft FORTRAN does not support the small model. is the name of the file containing your program. It may include a path specification. is the name of a standard Fastgraph/Light or Fastgraph library. For Fastgraph/Light, the library name is FGLM (for the medium model) or FGLL (for the large model). For Fastgraph, the library name is FGM (for the medium model) or FGL (for the large model). is the name of an optional compiler-specific extended Fastgraph library. You need to specify an extended library name only if your program calls any of the Fastgraph routines listed in Appendix D. The extended library name is FGMSFM (for the medium 10 Fastgraph User's Guide model) or FGMSFL (for the large model). Fastgraph/Light does not use extended libraries. The /E linker option is not required but will produce a smaller .EXE file if specified. For example, to compile the program 01-03.FOR under the medium memory model and then link it with Fastgraph, you could use the following FL command: FL /FPi /4I2 /4Nt /AM 01-03.FOR /link FGM FGMSFM /E Although we specified the extended library name FGMSFM on the command line, we didn't need to in this example because the program doesn't call any of the compiler-specific Fastgraph routines listed in Appendix D. If you were using Fastgraph/Light instead of Fastgraph, the FL command would be: FL /FPi /4I2 /4Nt /AM 01-03.FOR /link FGLM /E For more information about memory models or other compilation and linking options, please refer to the Microsoft FORTRAN Optimizing Compiler User's Guide, published by Microsoft Corporation. All the remaining example programs in the Fastgraph User's Guide are written in the C programming language. However, when you install Fastgraph for the Microsoft FORTRAN compiler, the installation procedure copies FORTRAN versions of the example programs to the \FG\EXAMPLES directory. Microsoft QuickBASIC Microsoft QuickBASIC allows you to compile and link a program directly from the DOS command line, or from within its programming environment. To use Fastgraph from QuickBASIC's programming environment, just specify the quick library name FGQB when starting QuickBASIC, as shown below. QB /lFGQB If you are using Fastgraph/Light, use the library name FGLQB instead of FGQB. You also can compile and link a QuickBASIC program from the DOS command line using the BC and LINK commands. The format of these commands for compiling a program and linking it with Fastgraph is BC ; LINK [/E] ,,NUL, where: Chapter 1: Introduction 11 is the name of the file containing your program. It may include a path specification. is the name of the object file produced by the BC command. By default, this will be the same as , but with an extension of .OBJ rather than .BAS. is the name of the standard Fastgraph/Light or Fastgraph library. For Fastgraph/Light, the library name is FGLQB. For Fastgraph, the library name is FGQB. QuickBASIC does not use extended Fastgraph libraries. The /E linker option is not required but will produce a smaller .EXE file if specified. For example, to compile the program 01-02.BAS and then link it with Fastgraph, you could use the following commands: BC 01-02.BAS; LINK /E 01-02.OBJ,,NUL,FGQB If you were using Fastgraph/Light instead of Fastgraph, the commands would be: BC 01-02.BAS; LINK /E 01-02.OBJ,,NUL,FGLQB For more information about other compilation and linking options, please refer to the Microsoft QuickBASIC: Programming in BASIC manual, published by Microsoft Corporation. All the remaining example programs in the Fastgraph User's Guide are written in the C programming language. However, when you install Fastgraph for Microsoft QuickBASIC, the installation procedure copies QuickBASIC versions of the example programs to the \FG\EXAMPLES directory. Microsoft QuickC Microsoft QuickC allows you to compile and link a program directly from the DOS command line, or from within its programming environment. To use Fastgraph from the QuickC programming environment, you must make sure the compiler options match one of Fastgraph's available memory models (small, medium, or large) and then create a make file that includes one or more of the corresponding Fastgraph libraries (as listed below). You also can compile and link a QuickC program from the DOS command line using the QCL command. The format of the QCL command for compiling a program and linking it with Fastgraph is QCL /link [] [/E] 12 Fastgraph User's Guide where: specifies the compiler memory model you'll be using. It must be either /AS (for the small model), /AM (for the medium model), or /AL (for the large model). is the name of the file containing your program. It must include the file extension (typically .C) and may include a path specification. is the name of a standard Fastgraph/Light or Fastgraph library. For Fastgraph/Light, the library name is FGLS (for the small model), FGLM (for the medium model), or FGLL (for the large model). For Fastgraph, the library name is FGS (for the small model), FGM (for the medium model), or FGL (for the large model). is the name of an optional compiler-specific extended Fastgraph library. You need to specify an extended library name only if your program calls any of the Fastgraph routines listed in Appendix D. The extended library name is FGMSCS (for the small model), FGMSCM (for the medium model), or FGMSCL (for the large model). Fastgraph/Light does not use extended libraries. The /E linker option is not required but will produce a smaller .EXE file if specified. For example, to compile the program 01-01.C under the medium memory model and then link it with Fastgraph, you could use the following QCL command: QCL /AM 01-01.C /link FGM FGMSCM /E Although we specified the extended library name FGMSCM on the command line, we didn't need to in this example because the program doesn't call any of the compiler-specific Fastgraph routines listed in Appendix D. If you were using Fastgraph/Light instead of Fastgraph, the QCL command would be: QCL /AM 01-01.C /link FGLM /E For more information about memory models or other compilation and linking options, please refer to the Microsoft QuickC Tool Kit manual, published by Microsoft Corporation. Chapter 1: Introduction 13 Power C Power C programs are compiled and linked from the DOS command line using the PC and PCL commands. The format of these commands for compiling a program and linking it with Fastgraph is PC PCL ; [;] where: specifies the compiler memory model you'll be using. It must be either /ms (for the small model), /mm (for the medium model), or /ml (for the large model). is the name of the file containing your program. It may include a path specification. is the name of the object file produced by the PC command. By default, this will be the same as , but with an extension of .MIX rather than .C. is the name of a standard Fastgraph/Light or Fastgraph library. For Fastgraph/Light, the library name is FGLS (for the small model), FGLM (for the medium model), or FGLL (for the large model). For Fastgraph, the library name is FGS (for the small model), FGM (for the medium model), or FGL (for the large model). is the name of an optional compiler-specific extended Fastgraph library. You need to specify an extended library name only if your program calls any of the Fastgraph routines listed in Appendix D. The extended library name is FGPCS (for the small model), FGPCM (for the medium model), or FGPCL (for the large model). Fastgraph/Light does not use extended libraries. For example, to compile the program 01-01.C under the medium memory model and then link it with Fastgraph, you could use the following commands: PC /mm 01-01.C PCL 01-01.MIX ;FGM ;FGPCM Although we specified the extended library name FGPCM on the command line, we didn't need to in this example because the program doesn't call any of the compiler-specific Fastgraph routines listed in Appendix D. If you were using Fastgraph/Light instead of Fastgraph, the commands would be: 14 Fastgraph User's Guide PC /mm 01-01.C PCL 01-01.MIX ;FGPCM For more information about memory models or other compilation and linking options, please refer to the Power C manual, published by Mix Software, Inc. Turbo C and Turbo C++ Turbo C and Turbo C++ allow you to compile and link a program directly from the DOS command line, or from within their integrated development environment (IDE). To use Fastgraph from the IDE, you must make sure the compiler options match one of Fastgraph's available memory models (small, medium, or large) and then create a project file that links with the corresponding Fastgraph libraries (as listed below). You also can compile and link a Turbo C or Turbo C++ program from the DOS command line using the TCC command. The format of the TCC command for compiling a program and linking it with Fastgraph is TCC [] where: specifies the compiler memory model you'll be using. It must be either -ms (for the small model), -mm (for the medium model), or -ml (for the large model). is the name of the file containing your program. It may include a path specification. is the name of a standard Fastgraph/Light or Fastgraph library. For Fastgraph/Light, the library name is FGLS.LIB (for the small model), FGLM.LIB (for the medium model), or FGLL.LIB (for the large model). For Fastgraph, the library name is FGS.LIB (for the small model), FGM.LIB (for the medium model), or FGL.LIB (for the large model). is the name of an optional compiler-specific extended Fastgraph library. You need to specify an extended library name only if your program calls any of the Fastgraph routines listed in Appendix D. The extended library name is FGTCS.LIB (for the small model), FGTCM.LIB (for the medium model), or FGTCL.LIB (for the large model). Fastgraph/Light does not use extended libraries. For example, to compile the program 01-01.C under the medium memory model and then link it with Fastgraph, you could use the following TCC command: TCC -mm 01-01.C FGM.LIB FGTCM.LIB Chapter 1: Introduction 15 Although we specified the extended library name FGTCM.LIB on the command line, we didn't need to in this example because the program doesn't call any of the compiler-specific Fastgraph routines listed in Appendix D. If you were using Fastgraph/Light instead of Fastgraph, the TCC command would be: TCC -mm 01-01.C FGLM.LIB For more information about memory models or other compilation and linking options, please refer to the Turbo C User's Guide and the Turbo C Reference Guide, both published by Borland International. Turbo Pascal Turbo Pascal allows you to compile and link a program directly from the DOS command line with the TPC command, or from within its integrated development environment (IDE) with the TURBO command. To use Fastgraph from the IDE, just start the IDE as you would for any other Pascal program, making sure the standard unit (FGTP.TPU) and extended unit (FGTPX.TPU) reside in one of the directories listed in the Unit Directories option. You also can compile and link a Turbo Pascal program from the DOS command line using the TPC command. The format of the TPC command for compiling a program and linking it with Fastgraph is TPC where: is the name of the file containing your program. It may include a path specification. For example, to compile the program 01-04.PAS and then link it with Fastgraph, you could use the following command: TPC 01-04.PAS For more information about other compilation and linking options, please refer to the Turbo Pascal User's Guide, published by Borland International. All the remaining example programs in the Fastgraph User's Guide are written in the C programming language. However, when you install Fastgraph for Turbo Pascal, the installation procedure copies Pascal versions of the example programs to the \FG\EXAMPLES directory. 16 Fastgraph User's Guide Fastgraph/Light Video Driver As mentioned earlier, running any program created with Fastgraph/Light requires an external program called the Fastgraph/Light Video Driver. The video driver is a terminate and stay resident program (TSR) that provides an interface between your program and Fastgraph. Once loaded, the video driver uses about 60,000 bytes of conventional memory. To load the video driver, enter the command FGDRIVER at the DOS command prompt (assuming FGDRIVER.EXE is in the current directory, or the \FG directory is in your DOS path specification). The driver will display a message indicating whether or not it loaded successfully. After you load the driver, just run a program created with Fastgraph/Light as you would any other program. If you try running a program that uses Fastgraph/Light without first loading the video driver, the message "Fastgraph/Light video driver not installed" will appear. You don't need to load the driver before running each program, just once per system boot (in fact, the driver will display an "already loaded" message if you try to load it more than once). If you want to unload the video driver, just enter FGDRIVER /U at the DOS command prompt. The unload operation will work completely only if the video driver was the last TSR loaded. If it wasn't the last TSR, the driver will still unload, but the memory it uses will not be released back to DOS. Chapter 2 PC and PS/2 Video Modes 18 Fastgraph User's Guide Overview In the PC and PS/2 worlds, the method by which information appears on the computer's display screen is determined by the video mode currently in effect. The video modes have different resolutions, different character or pixel attributes, different video memory structures, and other inherent hardware differences. However, you do not need an in-depth knowledge of these video internals, because Fastgraph handles the necessary details. The PC and PS/2 video modes may be separated into two major classes: text modes and graphics modes. In text modes, the display screen is divided into character cells. There are 25 rows and either 40 or 80 columns of cells, and in each cell we can store any of the 256 characters in the IBM PC character set. Each character has an associated attribute that determines such things as its foreground color, its background color, and whether or not the character blinks. In graphics modes, the display screen is divided into picture elements, or pixels. Depending on the video mode, the number of pixel rows ranges between 200 and 480, while the number of columns ranges between 320 and 720. Each pixel has an associated value that determines the color of the pixel. The number of character cells or pixels available is called the resolution of the screen. The display adapter (graphics card) and the video display (monitor) connected to it determine the video modes available on a given system. The following table summarizes the characteristics of the PC and PS/2 video modes that Fastgraph supports. Mode No. of Supported Supported Number Type Resolution Colors Adapters Displays 0 Text 40 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 1 Text 40 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 2 Text 80 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 3 Text 80 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 4 Graphics 320 x 200 4 CGA,EGA,VGA,MCGA RGB,ECD,VGA 5 Graphics 320 x 200 4 CGA,EGA,VGA,MCGA RGB,ECD,VGA 6 Graphics 640 x 200 2/16 CGA,EGA,VGA,MCGA RGB,ECD,VGA 7 Text 80 x 25 b/w MDA,HGC,EGA,VGA Mono,ECD,VGA 9 Graphics 320 x 200 16 Tandy 1000,PCjr RGB 11 Graphics 720 x 348 b/w HGC Monochrome 12 Graphics 320 x 200 b/w HGC Monochrome 13 Graphics 320 x 200 16 EGA,VGA RGB,ECD,VGA 14 Graphics 640 x 200 16 EGA,VGA RGB,ECD,VGA 15 Graphics 640 x 350 b/w EGA,VGA Mono,VGA 16 Graphics 640 x 350 16/64 EGA,VGA ECD,VGA 17 Graphics 640 x 480 2/256K VGA,MCGA VGA 18 Graphics 640 x 480 16/256K VGA VGA 19 Graphics 320 x 200 256/256K VGA,MCGA VGA 20 Graphics 320 x 200 256/256K VGA VGA 21 Graphics 320 x 400 256/256K VGA VGA 22 Graphics 320 x 240 256/256K VGA VGA 23 Graphics 320 x 480 256/256K VGA VGA Some notes about the format and abbreviations used in this table are in order. A single value in the "number of colors" column refers to the number Chapter 2: PC and PS/2 Video Modes 19 of colors available in that video mode. In text modes, a pair of numbers such as 16/8 means each displayed character can have one of 16 foreground colors and one of 8 background colors. In graphics modes, a pair of numbers such as 16/64 means 16 colors can be displayed simultaneously from a collection, or palette, of 64. The "b/w" listed in the monochrome modes stands for "black and white". Characters or pixels in these video modes do not really have associated colors but instead have display attributes such as blinking or different intensities. The meanings of the abbreviations in the "supported adapters" and "supported displays" columns are: CGA Color Graphics Adapter ECD Enhanced Color Display EGA Enhanced Graphics Adapter HGC Hercules Graphics Card MCGA Multi-Color Graphics Array MDA Monochrome Display Adapter RGB Red-Green-Blue Color Display VGA Video Graphics Array The use of the term "VGA" in the "supported display" column refers to any analog display, such as a VGA, Super VGA (SVGA), or Multisync monitor. The IBM PS/2 family does not have an adapter and display combination per se. Instead, the video hardware used in these systems is called the video subsystem. The Model 25 and Model 30 have an MCGA-based video subsystem, while other models have a VGA-based video subsystem. This rest of this chapter will provide an overview of the most important features and restrictions of each video mode. The first section will discuss the text modes, while the following section will discuss the graphics modes. Text Modes There are five text video modes in the IBM PC and PS/2 family. Four of these modes (0, 1, 2, and 3) are designed for color displays, while the remaining mode (7) is designed for monochrome displays. All text modes were introduced with the original IBM PC. In text modes, the screen is divided into character cells. There are two bytes of video memory associated with each character cell -- one byte for the character's ASCII value, and another for the character's display attribute. The amount of video memory required to store one screen of information (called a video page) is thus number_of_columns x number_of_rows x 2 All text modes use 25 rows, so for the 40-column modes (0 and 1) the size of a video page is 2,000 bytes, and for the 80-column modes (2, 3, and 7) the size of a video page is 4,000 bytes. 20 Fastgraph User's Guide Mode No. of Supported Supported Number Resolution Colors Adapters Displays 0 40 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 1 40 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 2 80 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 3 80 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 7 80 x 25 b/w MDA,HGC,EGA,VGA Monochrome,ECD,VGA The remainder of this section will describe the text video modes in more detail. Mode 0 Mode 0 is a 40-column by 25-row color text mode. It is often called a colorless mode since it was designed to be used with composite or television monitors (as opposed to RGB monitors). When used with these types of monitors, the available 16 "colors" appear as distinct shades of gray. When used with an RGB monitor, mode 0 is identical in all respects to mode 1. The use of composite or television monitors as PC video displays has virtually disappeared today. As a result, mode 0 is used infrequently. Mode 1 Mode 1 is a 40-column by 25-row color text mode. It is supported across all video adapter and color display combinations in the PC and PS/2 families. Characters displayed in mode 1 have an associated display attribute that defines the character's foreground color, its background color, and whether or not it blinks. Sixteen foreground colors and eight background colors are available. Mode 2 Mode 2 is an 80-column by 25-row color text mode. Like mode 0, it is often called a colorless mode since it was designed to be used with composite or television monitors (as opposed to RGB monitors). When used with these types of monitors, the available 16 "colors" appear as distinct shades of gray. When used with an RGB monitor, mode 2 is identical in all respects to mode 3. The use of composite or television monitors as PC video displays has virtually disappeared today. As a result, mode 2 is used infrequently. Mode 3 Mode 3 is an 80-column by 25-row color text mode. It is the default video mode for systems that use any type of color display. This mode is supported across all video adapter and color display combinations in the PC and PS/2 families. Characters displayed in mode 3 have an associated display attribute that defines the character's foreground color, its background color, and whether or not it blinks. Sixteen foreground colors and eight background colors are available. Mode 7 Mode 7 is the 80-column by 25-row monochrome text mode. It is the default video mode for systems that use a monochrome display. To use this mode, you must have a Monochrome Display Adapter (MDA), Hercules Graphics Card (HGC), or an Enhanced Graphics Adapter (EGA) connected to a monochrome Chapter 2: PC and PS/2 Video Modes 21 display. Most VGA display adapters also provide an emulation mode that allows you to use mode 7 with analog displays. Characters displayed in mode 7 have an associated display attribute that defines whether the character is invisible, normal, bold, underlined, reversed, blinking, or a combination of these. Graphics Modes There are 13 standard graphics video modes available in the IBM PC and PS/2 family. Fastgraph provides support for 11 of the 13 modes (modes 8 and 10, which are specific to the PCjr and Tandy 1000 systems, are not supported). In addition to these 13 modes, Fastgraph supports two video modes for the Hercules Graphics Card (modes 11 and 12) and four extended VGA modes (modes 20 through 23). The following sections discuss the graphics modes in more detail. The discussions include an overview of video memory organization in each mode, but you don't need a knowledge of this subject to use Fastgraph. CGA Graphics Modes Modes 4, 5, and 6 are designed to be used with the Color Graphics Adapter (CGA) and for this reason are called the native CGA modes. They were the only graphics modes available with the original IBM PC. Newer graphics adapters (EGA, VGA, and MCGA) can emulate the CGA, which means that the CGA graphics modes are available on any PC or PS/2 system equipped with a color display. Mode No. of Supported Supported Number Resolution Colors Adapters Displays 4 320 x 200 4 CGA,EGA,VGA,MCGA RGB,ECD,VGA 5 320 x 200 4 CGA,EGA,VGA,MCGA RGB,ECD,VGA 6 640 x 200 2/16 CGA,EGA,VGA,MCGA RGB,ECD,VGA Mode 4 Mode 4 is a CGA graphics mode with a resolution of 320 horizontal pixels by 200 vertical pixels. Each pixel can assume one of four colors (the available colors are determined by which one of six palettes has been selected), so each pixel requires two bits of video memory. This means that each byte of video memory represents four pixels. Mode 5 Mode 5 is the colorless analog of mode 4. It was designed to be used with composite or television monitors (as opposed to RGB monitors). When used with these types of monitors, the four colors appear as distinct shades of gray. When used with an RGB monitor, mode 5 is essentially identical to mode 4. The use of composite or television monitors as PC video displays has virtually disappeared today. As a result, mode 5 is used infrequently. 22 Fastgraph User's Guide Mode 6 Mode 6 is a CGA graphics mode with a resolution of 640 horizontal pixels by 200 vertical pixels. Each pixel can assume two states -- on or off. The color in which the "on" pixels appear can be selected from a palette of 16 available colors. Each pixel thus requires one bit of video memory, which means that each byte of video memory represents eight pixels. Tandy 1000 and PCjr Graphics Modes Modes 8, 9, and 10 are only available on the PCjr and Tandy 1000 series computers (these systems also support modes 4, 5, and 6). Modes 8 and 10 are not widely used, and for this reason Fastgraph does not support them. Mode No. of Supported Supported Number Resolution Colors Adapters Displays 8 160 x 200 16 Tandy 1000,PCjr RGB 9 320 x 200 16 Tandy 1000,PCjr RGB 10 640 x 200 4 Tandy 1000,PCjr RGB Mode 9 Mode 9 is a Tandy 1000 and PCjr graphics mode with a resolution of 320 horizontal pixels by 200 vertical pixels. Each pixel can assume one of 16 colors, so each pixel requires four bits of video memory. This means that each byte of video memory represents two pixels. The Tandy 1000 and PCjr use standard random-access memory (RAM) as video memory. Hercules Graphics Modes Modes 11 and 12 are used with the Hercules Graphics Card (HGC) and a monochrome display. As such, they are not true IBM video modes, but because of the popularity of the HGC, Fastgraph provides support for this adapter. IBM has not defined video modes with numbers 11 and 12. Should they choose to do so in the future, Fastgraph's Hercules video mode numbers would likely change. Mode No. of Supported Supported Number Resolution Colors Adapters Displays 11 720 x 348 b/w HGC Monochrome 12 320 x 200 b/w HGC Monochrome Chapter 2: PC and PS/2 Video Modes 23 Mode 11 Mode 11 is a true Hercules graphics mode with a resolution of 720 horizontal pixels by 348 vertical pixels. Each pixel can assume two states -- on or off. Each pixel thus requires one bit of video memory, which means that each byte of video memory represents eight pixels. Mode 12 Mode 12 is a software-simulated Hercules graphics mode with an effective resolution of 320 horizontal pixels by 200 vertical pixels. Its purpose is to provide a resolution that is available with all other graphics display adapters. This mode converts all coordinates from the 320 by 200 space (called virtual coordinates) into the 720 by 348 coordinate system (called physical coordinates). It does this by using two physical pixels for each virtual pixel and scan doubling the odd-numbered virtual rows. Finally, offsets are added to the resulting physical coordinates to center the image area on the display. This creates an image area bounded horizontally by the physical coordinates 40 and 679 and vertically by the physical coordinates 24 and 323. EGA Graphics Modes Modes 13 through 16 were introduced with the Enhanced Graphics Adapter (EGA) and for this reason are called the native EGA modes. The VGA also provides support for these modes, but the MCGA does not. The original IBM EGA only contained 64K bytes of video memory, but memory could be added in 64K increments to fully populate the adapter with 256K bytes of video memory. As other manufacturers developed EGA cards, they generally included 256K bytes of video memory as a standard feature. Mode No. of Supported Supported Number Resolution Colors Adapters Displays 13 320 x 200 16 EGA,VGA RGB,ECD,VGA 14 640 x 200 16 EGA,VGA RGB,ECD,VGA 15 640 x 350 b/w EGA,VGA Monochrome,VGA 16 640 x 350 16/64 EGA,VGA ECD,VGA Mode 13 Mode 13 is an EGA graphics mode with a resolution of 320 horizontal pixels by 200 vertical pixels. Each pixel can assume one of 16 colors, so each pixel requires four bits of video memory. In this mode, video memory is organized as four bit planes. Each video memory address actually references four bytes, one in each plane. Put another way, each video memory byte references eight pixels, stored one bit per plane. 24 Fastgraph User's Guide Mode 14 Mode 14 is an EGA graphics mode with a resolution of 640 horizontal pixels by 200 vertical pixels. Each pixel can assume one of 16 colors, so each pixel requires four bits of video memory. In this mode, video memory is organized as four bit planes. Each video memory address actually references four bytes, one in each plane. Put another way, each video memory byte references eight pixels, stored one bit per plane. Mode 15 Mode 15 is an EGA monochrome graphics mode with a resolution of 640 horizontal pixels by 350 vertical pixels. Each pixel can assume one of 4 display attributes, so each pixel requires two bits of video memory. In this mode, video memory is organized as four bit planes, two of which are disabled. Each video memory address actually references two bytes, one in each enabled plane. Put another way, each video memory byte references eight pixels, stored one bit per plane. Mode 16 Mode 16 is an EGA graphics mode with a resolution of 640 horizontal pixels by 350 vertical pixels.(1) Each pixel can assume one of 16 colors (the 16 colors can be selected from a palette of 64 colors), so each pixel requires four bits of video memory. In this mode, video memory is organized as four bit planes. Each video memory address actually references four bytes, one in each plane. Put another way, each video memory byte references eight pixels, stored one bit per plane. VGA and MCGA Graphics Modes Modes 17, 18, and 19 were introduced with the MCGA and VGA video subsystems of the IBM PS/2 computers. Since the introduction of the PS/2, other manufacturers have developed VGA cards that can be used with the PC family. The VGA supports all three of these modes, but the MCGA does not support mode 18. Modes 17 and 18 are called native VGA modes. Modes 20 through 23 are the extended VGA graphics modes. Although these video modes are not standard VGA modes, they will work on any VGA system. Mode 20 is a special VGA version of mode 19, while mode 21 uses scan doubling to achieve a 400-line display. Mode 22 is the so-called "mode X" and is appealing because it has a 1:1 aspect ratio. Mode 23 is identical to mode 22, but it uses scan doubling to achieve a 480-line display. Should IBM define video modes numbered 20 through 23 in the future, Fastgraph's numbers for these video modes would likely change. ____________________ (1) In mode 16, the video page size actually is 640 x 400 pixels, though the screen resolution is 640 x 350. The final 50 pixel rows are not displayed but are available for off-screen storage. Chapter 2: PC and PS/2 Video Modes 25 Mode No. of Supported Supported Number Resolution Colors Adapters Displays 17 640 x 480 2/256K VGA,MCGA VGA 18 640 x 480 16/256K VGA VGA 19 320 x 200 256/256K VGA,MCGA VGA 20 320 x 200 256/256K VGA VGA 21 320 x 400 256/256K VGA VGA 22 320 x 240 256/256K VGA VGA 23 320 x 480 256/256K VGA VGA Mode 17 Mode 17 is a VGA and MCGA graphics mode with a resolution of 640 horizontal pixels by 480 vertical pixels. Each pixel can assume two states -- on or off. The color in which the "on" and "off" pixels appear can be selected from a palette of 262,144 available colors. Each pixel thus requires one bit of video memory, which means that each byte of video memory represents eight pixels. On VGA systems, video memory is organized as four bit planes, and mode 17 is implemented by enabling one of these planes. Mode 18 Mode 18 is a native VGA graphics mode with a resolution of 640 horizontal pixels by 480 vertical pixels. Each pixel can assume one of 16 colors (the 16 colors can be selected from a palette of 262,144 colors), so each pixel requires four bits of video memory. In this mode, video memory is organized as four bit planes. Each video memory address actually references four bytes, one in each plane. Put another way, each video memory byte references eight pixels, stored one bit per plane. Mode 19 Mode 19 is a VGA and MCGA graphics mode with a resolution of 320 horizontal pixels by 200 vertical pixels. Each pixel can assume one of 256 colors (the 256 colors can be selected from a palette of 262,144 colors), so each pixel requires eight bits of video memory. This means that each byte of video memory represents one pixel. Mode 20 Mode 20 is a VGA graphics mode with a resolution of 320 horizontal pixels by 200 vertical pixels. Each pixel can assume one of 256 colors (the 256 colors can be selected from a palette of 262,144 colors), so each pixel requires eight bits of video memory. This means that each byte of video memory represents one pixel. This mode offers the same resolution and number of colors as mode 19, but its video memory is organized as a series of four bit planes. Every fourth pixel is stored in the same plane (that is, a pixel whose horizontal coordinate is x resides in plane x mod 4). Mode 21 Mode 21 is a VGA color graphics mode with a resolution of 320 horizontal pixels by 400 vertical pixels. Except for the resolution, its video memory organization is identical to mode 20. 26 Fastgraph User's Guide Mode 22 Mode 22 is a VGA color graphics mode with a resolution of 320 horizontal pixels by 240 vertical pixels. This is the so-called "mode X" described by Michael Abrash in Dr. Dobb's Journal. Except for the resolution, its video memory organization is identical to mode 20. Mode 23 Mode 23 is a VGA color graphics mode with a resolution of 320 horizontal pixels by 480 vertical pixels. Except for the resolution, its video memory organization is identical to mode 20. Chapter 3 Initializing the Video Environment 28 Fastgraph User's Guide Overview Before Fastgraph can perform any text or graphics video operations, you must select a video mode in which your program will run. An important part of this selection depends on whether your program will run in a text mode, a graphics mode, or both. This chapter discusses the necessary video initialization for each case. Establishing a Text Mode When you write a program that only uses text modes, you must determine if the program will run on monochrome systems, color systems, or both. In general, there is no reason to exclude one type of system, because the additional programming required to support both is rather trivial. The Fastgraph routine fg_setmode establishes a video mode and initializes Fastgraph's internal parameters for that mode. This routine has a single integer argument whose value is a video mode number between 0 and 23. Its value can also be -1, which tells Fastgraph to use the current video mode. Specifying an fg_setmode argument of -1 is often useful in programs that only use text video modes. When you establish a text video mode, the ROM BIOS text cursor is made visible, and this is often undesirable. The Fastgraph routine fg_cursor controls the visibility of the text cursor. The fg_cursor routine has a single integer argument that specifies the cursor visibility. If its value is 0, the cursor is made invisible; if its value is 1, the cursor is made visible. At this point, an example may help to clarify things. The following program shows how to initialize Fastgraph for the 80-column color text mode (mode 3) and turn off the text mode cursor. It uses two Fastgraph routines that we have not yet discussed, fg_setcolor and fg_text. These routines will be discussed in later sections of this document. For now, it should suffice to know the call to fg_setcolor makes subsequent text appear in bright white, and the call to fg_text displays the characters passed to it. Example 3-1. #include void main(void); void main() { fg_setmode(3); fg_cursor(0); fg_setcolor(15); fg_text("Hello, world.",13); } If you run example 3-1, notice the text displayed by the program appears in the upper left corner of the screen. On the line below this, the DOS prompt appears, waiting for your next DOS command. Furthermore, if your system uses the ANSI.SYS driver to set screen attributes (such as with Chapter 3: Initializing the Video Environment 29 Norton's SA program), you should also notice only the DOS prompt appears in the colors defined by the screen attributes -- the rest of the screen is blank. A more graceful return to DOS is needed. In example 3-2, we'll use the Fastgraph routine fg_reset. This routine erases the screen, and if the ANSI.SYS driver is loaded, fg_reset also restores any previously set screen attributes. We've also included a call to the Fastgraph routine fg_waitkey to wait for a keystroke before exiting. If we didn't do this, we would never see the program's output. Example 3-2. #include void main(void); void main() { fg_setmode(3); fg_cursor(0); fg_setcolor(15); fg_text("Hello, world.",13); fg_waitkey(); fg_reset(); } Since examples 3-1 and 3-2 specifically used video mode 3, they would not work on a monochrome system. Ideally, we would like to use fg_setmode(3) for color systems and fg_setmode(7) for monochrome systems. To do this, we need a way to determine whether the program is being run on a color system or on a monochrome system. The next example illustrates an easy way to accomplish this. Example 3-3 uses the Fastgraph routine fg_testmode to determine if the user's system will support the video mode number specified as its first argument (the second argument is the number of video pages required, which will be 1 for all examples in this section). The fg_testmode routine returns a value of 1 (as its function value) if the requested video mode can be used, and it returns 0 if not. The program first sees if an 80-column color text mode is available (mode 3), and if so, it selects that mode. If the color mode is not available, it checks if the monochrome text mode is available (mode 7), and if so, it chooses the monochrome mode. If neither mode is available, then the program assumes the user's system has a 40-column display, issues a message indicating the program requires an 80-column display, and then exits. Example 3-3. #include #include #include void main(void); void main() 30 Fastgraph User's Guide { int old_mode; old_mode = fg_getmode(); if (fg_testmode(3,1)) fg_setmode(3); else if (fg_testmode(7,1)) fg_setmode(7); else { printf("This program requires\n"); printf("an 80-column display.\n"); exit(1); } fg_cursor(0); fg_setcolor(15); fg_text("Hello, world.",13); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Example 3-3 also illustrates another useful procedure. It is recommended, especially in graphics modes, to restore the original video mode and screen attributes before a program returns to DOS. We've already seen how the fg_reset routine restores the screen attributes, but how do we restore the original video mode? The Fastgraph routine fg_getmode returns the current video mode as its function value. If we call fg_getmode before calling fg_setmode, we can use the return value from fg_getmode and again call fg_setmode before the program exits. You also can use another Fastgraph routine, fg_bestmode, to determine if a video mode with a specific resolution is available on the user's system. The fg_bestmode routine requires three integer arguments: a horizontal resolution, a vertical resolution, and the number of video pages required. As its function value, fg_bestmode returns the video mode number that offers the most capabilities for the resolution and number of pages requested. It returns a value of -1 if no available video mode offers the requested criteria. For example, if we require an 80 by 25 text mode, we can use the function call fg_bestmode(80,25,1) to pick the "best" video mode available that offers this capability. In text modes, the term best means to give preference to a color text mode over a monochrome text mode. Example 3-4 performs the same function as example 3-3, but it uses fg_bestmode rather than fg_testmode. Example 3-4. #include #include #include Chapter 3: Initializing the Video Environment 31 void main(void); void main() { int old_mode; int new_mode; old_mode = fg_getmode(); new_mode = fg_bestmode(80,25,1); if (new_mode < 0) { printf("This program requires\n"); printf("an 80-column display.\n"); exit(1); } fg_setmode(new_mode); fg_cursor(0); fg_setcolor(15); fg_text("Hello, world.",13); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } 43-line and 50-line Text Modes When using an 80-column text mode on a system equipped with an EGA, VGA, or MCGA video display and adapter, you can extend the screen size from 25 lines to 43 or 50 lines. While all systems offer 25-line text modes, EGA systems also offer 43-line modes, MCGA systems also offer 50-line modes, and VGA systems offer both 43-line and 50-line modes. The 43-line mode is not available on EGA systems equipped with an RGB display. If you extend the screen size to 43 or 50 lines, the physical character size is reduced proportionally so all lines appear on the screen. The fg_setlines routine defines the number of text rows per screen. It has a single integer argument whose value must be 25, 43, or 50. If you pass any other value to fg_setlines, or pass a value not supported by the host system's video configuration, fg_setlines does nothing. In addition, calling fg_setlines makes the text cursor visible. Another Fastgraph routine, fg_getlines, returns as its function value the number of text rows currently in effect. You also can use fg_getlines in graphics video modes. Example 3-5 illustrates the use of the fg_setlines and fg_getlines routines. The program first establishes the 80-column color text mode (this sets the screen size to its 25-line default) and makes the text cursor invisible. It then displays the words "first line" in the upper left corner of the screen. Next, the program checks if an EGA with enhanced display is available, and if so, changes the screen to 43 lines (video mode 16 is only available on EGA systems equipped with an enhanced display). Next, the program checks if a VGA or MCGA is available, and if so changes the screen to 50 lines (video mode 17 is only available on VGA and MCGA systems). Finally, the program restores the original video mode, restores the number of lines per screen to its original setting, and restores the original screen attributes before exiting. 32 Fastgraph User's Guide Example 3-5. #include void main(void); void main() { int lines; int old_lines; int old_mode; old_lines = fg_getlines(); old_mode = fg_getmode(); fg_setmode(3); fg_cursor(0); fg_setcolor(15); fg_text("first line",10); fg_waitkey(); if (fg_testmode(16,0)) { fg_setlines(43); fg_cursor(0); fg_waitkey(); } if (fg_testmode(17,0)) { fg_setlines(50); fg_cursor(0); fg_waitkey(); } fg_setmode(old_mode); fg_setlines(old_lines); fg_reset(); } Establishing a Graphics Mode The steps for establishing a graphics mode are similar to establishing a text mode. However, there are more restrictions since some systems may not support all the graphics video modes. For example, a program could not run in mode 13 on a CGA system, nor could a program run in mode 9 on anything except a Tandy 1000 or PCjr system. Example 3-6 shows one way to write an EGA-specific program. The program in this example uses mode 16, the 640 x 350 EGA mode that requires an Enhanced Color Display (ECD). It uses the Fastgraph routine fg_egacheck to determine if an EGA and ECD are present. The fg_egacheck routine returns a value of 0 if an EGA is not found, or if there is an EGA but no ECD. If an EGA and ECD are found, it returns a positive integer indicating the number of 64K-byte increments of video memory on the EGA. Since mode 16 requires 112,000 bytes of video memory for a single video page, there must be at least 128K bytes of video memory on the EGA to run this program. Hence, we must be sure that fg_egacheck returns a value of at least 2. Chapter 3: Initializing the Video Environment 33 Example 3-6. #include #include #include void main(void); void main() { int mode; if (fg_egacheck() < 2) { printf("This program requires an Enhanced Graphics Adapter\n"); printf("(EGA) and an Enhanced Color Display (ECD).\n"); exit(1); } mode = fg_getmode(); fg_setmode(16); fg_setcolor(15); fg_text("Hello, world.",13); fg_waitkey(); fg_setmode(mode); fg_reset(); } For graphics programs, it may suffice to write a program to run in a specific video mode, but it is often more desirable to write a program that will run in any of several video modes. This is especially true for commercial products, since they should run on as many different video configurations as possible. Fastgraph includes a routine named fg_automode that determines the graphics video mode that offers the most functionality for the user's video hardware configuration. For example, the Tandy 1000 series computers support all three CGA modes (4, 5, and 6) and the 320 by 200 16-color Tandy 1000 mode (9). Of these modes, mode 9 offers the most features from a graphics standpoint, so fg_automode will return a value of 9 when run on a Tandy 1000 computer. The following table summarizes the video mode numbers returned by fg_automode for given adapter-display combinations. ------- display ------- adapter mono RGB ECD VGA MDA 7 0 7 7 HGC 11 0 0 11 CGA 0 4 0 0 EGA 15 13 16 0 VGA 17 17 17 18 MCGA 17 17 17 19 Tandy 7 9 0 0 PCjr 7 9 0 0 34 Fastgraph User's Guide Example 3-7 shows how to use fg_automode to determine the "best" graphics mode for the user's video hardware. In graphics modes, the term best means the highest resolution, followed by the number of available colors. The program displays a message that includes the selected video mode number. Example 3-7. #include #include void main(void); void main() { int old_mode; int new_mode; char string[4]; old_mode = fg_getmode(); new_mode = fg_automode(); fg_setmode(new_mode); fg_setcolor(15); fg_text("I'm running in mode ",20); sprintf(string,"%d.",new_mode); fg_text(string,3); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } For simple programs such as example 3-7, different screen resolutions may not be an issue. However, in more complex graphics programs it is often desirable to write a program for a fixed screen resolution. A common practice is to develop graphics programs to run in modes 4 (for CGA), 9 (Tandy 1000 or PCjr), 12 (Hercules), 13 (EGA or VGA), and 19 or 20 (MCGA or VGA). The reason for selecting these five modes is they all use the same 320 by 200 resolution and will run on any IBM PC or PS/2 with graphics capabilities. Example 3-8 performs the same function as example 3-7, but it uses the fg_bestmode routine instead of fg_automode to restrict the program to 320 by 200 graphics modes. For this resolution, the fg_bestmode routine will first check the availability of mode 19, followed by modes 13, 9, 4, and 12. If fg_bestmode determines no 320 by 200 graphics mode is available (indicated by a return value of -1), the program prints an informational message and exits. Otherwise it selects the video mode fg_bestmode proposes and continues. Example 3-8. #include #include #include void main(void); Chapter 3: Initializing the Video Environment 35 void main() { int old_mode; int new_mode; char string[4]; old_mode = fg_getmode(); new_mode = fg_bestmode(320,200,1); if (new_mode < 0) { printf("This program requires a 320 by 200 graphics mode.\n"); exit(1); } fg_setmode(new_mode); fg_setcolor(15); fg_text("I'm running in mode ",20); sprintf(string,"%d.",new_mode); fg_text(string,3); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } If your program will not support all PC and PS/2 video modes with the same resolution (for example, it will run in some but not all 320 by 200 graphics modes), you may want to consider using the fg_testmode routine instead of fg_bestmode to check for available video modes. You also may want to use fg_testmode to change the video mode precedence used by fg_bestmode. For example, mode 13 (EGA) is faster than mode 19 (MCGA), so you may want to consider giving EGA precedence over MCGA, especially if your program does not use more than 16 colors. Example 3-9 is similar to example 3-8, but it will only run in the 320 by 200 EGA, MCGA, and CGA graphics modes (video modes 13, 19, and 4 respectively). The program uses fg_testmode to select its video mode. Note the order of calls to fg_testmode gives EGA precedence over MCGA, and MCGA precedence over CGA. Example 3-9. #include #include #include void main(void); void main() { int old_mode; char string[4]; old_mode = fg_getmode(); if (fg_testmode(13,1)) 36 Fastgraph User's Guide fg_setmode(13); else if (fg_testmode(19,1)) fg_setmode(19); else if (fg_testmode(4,1)) fg_setmode(4); else { printf("This program requires an EGA, MCGA, or CGA.\n"); exit(1); } fg_setcolor(15); fg_text("I'm running in mode ",20); sprintf(string,"%d.",getmode()); fg_text(string,3); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Summary of Video Initialization Routines This section summarizes the functional descriptions of the Fastgraph routines presented in this chapter. More detailed information about these routines, including their arguments and return values, may be found in the Fastgraph Reference Manual. FG_AUTOMODE determines the graphics video mode that offers the most features for the user's display and adapter configuration. The value it returns helps determine a suitable value to pass to the fg_setmode routine. FG_BESTMODE is similar to fg_automode, but it excludes video modes that do not offer the specified resolution and video page requirements. FG_CURSOR makes the text mode cursor visible or invisible. This routine has no effect when used in a graphics mode. FG_EGACHECK returns information about the active EGA or VGA adapter and display. It is useful in checking if the adapter has enough memory to run an EGA-specific program. FG_GETLINES returns the number of text rows per screen for the current video mode. FG_GETMODE returns the current video mode. It is typically one of the first Fastgraph routines called in a program. The value returned by fg_getmode can be retained to restore the original video mode when a program transfers control back to DOS. FG_RESET is generally the last Fastgraph routine called in a program. It only functions in text video modes. When the ANSI.SYS driver is not loaded, fg_reset merely erases the screen. When ANSI.SYS is loaded, fg_reset also restores any previously set screen attributes. Chapter 3: Initializing the Video Environment 37 FG_SETLINES extends an 80-column text mode to 25, 43, or 50 lines per screen. This routine is only meaningful when running in 80-column text modes on EGA, VGA, or MCGA systems (in other cases it does nothing). FG_SETMODE establishes a video mode and initializes Fastgraph's internal parameters for that video mode. It must be called before any Fastgraph routine that performs video output. A program can call fg_setmode as many times as needed to switch between different video modes. FG_TESTMODE determines whether or not a specified video mode (with a given number of video pages) is available on the user's system. 38 Fastgraph User's Guide Chapter 4 Coordinate Systems 40 Fastgraph User's Guide Overview Fastgraph uses three coordinate systems to perform text and graphics output. These coordinate systems are character space, screen space, and world space. The world space coordinate system is not available with Fastgraph/Light. Character Space The coordinate system used for displaying characters is called character space. Fastgraph uses character space for displaying characters in both text and graphics video modes. It can be thought of as a grid of rows and columns, with each cell in the grid holding one character. Each cell is identified by its unique (row,column) integer coordinates. The rows and columns are numbered starting at zero; the origin is always the upper left corner of the screen. For example, in the 80-column by 25-row text modes (2, 3, and 7), the (row,column) coordinates of the screen corners are shown in the following diagram. (0,0) (0,79) (24,0) (24,79) The number of rows and columns depends on the video mode, as shown in the following table. For graphics modes, the table also includes the width and height in pixels of a character cell. Mode No. of No. of Char. Char. Number Columns Rows Width Height 0 40 25 1 40 25 2 80 25 3 80 25 4 40 25 8 8 5 40 25 8 8 6 80 25 8 8 7 80 25 9 40 25 8 8 11 80 25 9 14 12 40 25 8 8 13 40 25 8 8 14 80 25 8 8 15 80 25 8 14 16 80 25 8 14 17 80 30 8 16 18 80 30 8 16 19 40 25 8 8 20 40 25 8 8 21 40 50 8 8 22 40 30 8 8 23 40 60 8 8 Chapter 4: Coordinate Systems 41 Fastgraph includes two routines, fg_getmaxx and fg_getmaxy, that respectively return the maximum column and row numbers in text modes. Example 4-1 demonstrates these two routines in a text mode. The program uses fg_getmaxx and fg_getmaxy to obtain the maximum column and row numbers in mode 3. It then displays these values (79 and 24). Example 4-1. #include #include void main(void); void main() { int max_col; int max_row; int mode; mode = fg_getmode(); fg_setmode(3); max_col = fg_getmaxx(); max_row = fg_getmaxy(); fg_setmode(mode); fg_reset(); printf("Last col = %d\n",max_col); printf("Last row = %d\n",max_row); } Screen Space Screen space is one of two available coordinate systems in graphics modes. It uses the physical device coordinates. Screen space can be thought of as a grid of rows and columns, with each unit in the grid holding one pixel. Each pixel is identified by its unique (x,y) integer coordinates. The rows and columns are numbered starting at zero; the origin is always the upper left corner of the screen. For example, in the 320 by 200 graphics modes, the (x,y) coordinates of the screen corners are shown in the following diagram. (0,0) (319,0) (0,199) (319,199) The Fastgraph routines fg_getmaxx and fg_getmaxy return the maximum x and y screen coordinates when used in graphics modes, as shown in example 42 Fastgraph User's Guide 4-2. The program uses fg_getmaxx and fg_getmaxy to obtain the maximum x and y coordinates in the standard CGA four-color graphics mode (mode 4). It then displays these values (319 and 199). Example 4-2. #include #include void main(void); void main() { int maxx; int maxy; int mode; mode = fg_getmode(); fg_setmode(4); maxx = fg_getmaxx(); maxy = fg_getmaxy(); fg_setmode(mode); fg_reset(); printf("(%d,%d)\n",maxx,maxy); } World Space World space is the other available coordinate system in graphics modes. It utilizes user-defined floating point coordinates. Fastgraph translates world space coordinates into physical device coordinates (screen space), and because of this it is somewhat slower than using screen space. World space can be thought of as a standard cartesian plane extending from the lower left corner of the screen. Any program that uses world space coordinates must first initialize Fastgraph's internal world space parameters. The Fastgraph routine fg_initw is provided for this purpose. The fg_initw routine has no arguments and must be called before any other routine that uses world space coordinates. The next step in using world space is to use the Fastgraph routine fg_setworld to define the world space coordinates of the screen edges. The fg_setworld routine has four floating-point arguments -- the minimum x coordinate (left edge), the maximum x coordinate (right edge), the minimum y coordinate (bottom edge), and the maximum y coordinate (top edge). For example, if you define the world space coordinates with the statement fg_setworld(-10.0,10.0,0.0,2.5); the (x,y) coordinates of the screen corners would be defined as shown in the following diagram. (-10.0,2.5) (10.0,2.5) (-10.0,0.0) (10.0,0.0) Chapter 4: Coordinate Systems 43 Fastgraph includes a routine fg_getworld that returns the world space extremes as defined in the most recent call to fg_setworld. Example 4-3 uses fg_setworld and fg_getworld to illustrate an interesting application of world space. This program calls another routine named redraw (not shown) that erases the screen and draws a certain image using world space coordinates. The program draws the image, waits for a keystroke, reduces the world space by a factor of two in each direction, and then draws the image again. This produces a zoom effect in which the image appears twice as large as it was originally. Example 4-3. #include #include #include void main(void); void redraw(void); void main() { int new_mode, old_mode; double xmin, xmax, ymin, ymax; old_mode = fg_getmode(); new_mode = fg_automode(); if (new_mode == 0) { printf("This program requires graphics.\n"); exit(1); } fg_setmode(new_mode); fg_initw(); fg_setworld(0.0,40.0,0.0,30.0); redraw(); fg_waitkey(); fg_getworld(&xmin,&xmax,&ymin,&ymax); fg_setworld(0.0,xmax*0.5,0.0,ymax*0.5); redraw(); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } 44 Fastgraph User's Guide Conversion Routines It is often necessary to convert coordinates between character space, screen space, and world space. Fastgraph includes eight conversion routines, four for x coordinates and four for y coordinates, to perform such conversions. These routines return the translated coordinate as their function value. The fg_xalpha and fg_yalpha routines convert screen space coordinates to character space. The fg_xalpha routine converts a screen space x coordinate to the character space column that contains the coordinate. Similarly, the fg_yalpha routine converts a screen space y coordinate to the character space row that contains the coordinate. The fg_xconvert and fg_yconvert routines convert character space coordinates to screen space. The fg_xconvert routine converts a character space column to the screen space coordinate of its leftmost pixel. Similarly, the fg_yconvert routine converts a character space row to the screen space coordinate of its top (lowest-numbered) pixel. The fg_xscreen and fg_yscreen routines convert world space coordinates to screen space. The fg_xscreen routine translates x coordinates, while the fg_yscreen routine translates y coordinates. Conversely, the fg_xworld and fg_yworld routines convert screen space coordinates to world space. The fg_xworld routine translates x coordinates, while the fg_yworld routine translates y coordinates. Summary of Coordinate Routines This section summarizes the functional descriptions of the Fastgraph routines presented in this chapter. More detailed information about these routines, including their arguments and return values, may be found in the Fastgraph Reference Manual. FG_GETMAXX returns the maximum x coordinate in screen space when used in a graphics mode. It returns the maximum column number in character space when used in a text mode. FG_GETMAXY returns the maximum y coordinate in screen space when used in a graphics mode. It returns the maximum row number in character space when used in a text mode. FG_GETWORLD returns the current world space limits, as defined in the most recent call to fg_setworld. FG_INITW initializes Fastgraph's internal parameters for world space. This routine must be called once, before any other routine that uses world coordinates. FG_SETWORLD defines the world space coordinates that correspond to the physical edges of the screen. FG_XALPHA and FG_YALPHA convert screen space coordinates to character space. Chapter 4: Coordinate Systems 45 FG_XCONVERT and FG_YCONVERT convert character space coordinates to screen space. FG_XSCREEN and FG_YSCREEN convert world space coordinates to screen space. FG_XWORLD and FG_YWORLD convert screen space coordinates to world space. 46 Fastgraph User's Guide Chapter 5 The Use of Color 48 Fastgraph User's Guide Overview The use of color is an important part of any text or graphics application. This chapter explains color as it applies to text and graphics modes. It also describes palettes and video DAC registers for the graphics video modes that offer this functionality. Finally, an explanation of Fastgraph's virtual colors is provided. Text Modes The term color is not really correct in text modes because each character cell has an associated attribute that controls the character's appearance in that cell. The meaning of the attribute differs for color and monochrome text modes. Color Modes In color text modes (modes 0, 1, 2, and 3), the attribute determines a character's foreground color (the color of the character itself), its background color (the color of that part of the character cell not covered by the character), and whether or not it blinks. Sixteen foreground colors (numbered 0 to 15) are available, but only eight background colors (numbered 0 to 7) are available. The colors assigned to these values are listed in the following table. number color number color 0 black 8 gray 1 blue 9 light blue 2 green 10 light green 3 cyan 11 light cyan 4 red 12 light red 5 magenta 13 light magenta 6 brown 14 yellow 7 white 15 bright white At first it may seem the numbers have been arbitrarily assigned to the colors. Upon further inspection, however, it becomes apparent this is not the case. Each color number is a four bit quantity of the form IRGB, with I representing the intensity, R the red component, G the green component, and B the blue component. If the corresponding bit is 1, it means the intensity or color component is set. For example, normal red would be represented by the IRGB bit pattern 0100, which is 4 decimal, the color number for red. The fg_setattr routine defines the current text attribute. Once fg_setattr is called, Fastgraph displays all subsequent text using that attribute. The first argument of fg_setattr defines the foreground color, which must be an integer between 0 and 15. Its second argument defines the Chapter 5: The Use of Color 49 background color, which must be between 0 and 7. Its third argument determines if the foreground color blinks (1 means it blinks, 0 means it does not). For example, the statement fg_setattr(14,1,0); specifies subsequent text will be displayed with a yellow foreground (14) on a blue background (1) and will not blink (0). Another Fastgraph routine, fg_setcolor, also can be used to define text attributes. The fg_setcolor routine packs the three values passed to fg_setattr into a single argument, as shown below. bits attribute 0-3 foreground color 4-6 background color 7 blinking For example, calling fg_setcolor with an argument of 30 (1E hex) is equivalent to calling fg_setattr with arguments of 14, 1, and 0. The Fastgraph routine fg_getcolor returns the current text attribute, as defined in the most recent call to fg_setattr or fg_setcolor. The fg_getcolor routine has no arguments and returns the attribute as its function value. The returned value is encoded using the same scheme for passing a text attribute to the fg_setcolor routine. Monochrome Mode In the monochrome text mode (mode 7), colors are obviously not available. The attribute instead determines whether a character is invisible, normal, bold, reversed, or certain combinations of these. The following table shows the values assigned to the available display characteristics. foreground background characteristic 0 0 invisible 0 7 reversed 1 0 underlined 7 0 normal 9 0 underlined bold 15 0 bold Additionally, you can turn blinking on or off for each of these combinations. Any combination of foreground and background values not listed in the above table produces a normal display characteristic. 50 Fastgraph User's Guide As in the color modes, the Fastgraph routines fg_setattr and fg_setcolor define the current text attribute. For example, the statement fg_setattr(0,7,1); specifies subsequent text will be displayed in reverse video (0,7) and will blink (1). The same attribute could be defined by calling fg_setcolor with an argument of 240 (F0 hex). The fg_getcolor routine is also available and works as it does in the color text modes. Graphics Modes In graphics modes, each pixel has an associated color value that determines the color in which the pixel is displayed. The number of available colors depends on the video mode. Some of the graphics modes also have palette registers or video DAC registers to provide additional color capabilities. The example programs presented in this section show the use of color in specific graphics video modes. The following subsections will discuss the use of color in each graphics video mode. In these discussions, there will be several references to a group of colors called the standard color set. This is a set of 16 colors common to many of the graphics video modes (and to the color text modes). The colors in the standard color set are listed in the following table. number color number color 0 black 8 gray 1 blue 9 light blue 2 green 10 light green 3 cyan 11 light cyan 4 red 12 light red 5 magenta 13 light magenta 6 brown 14 yellow 7 white 15 bright white At this point it is important to understand the difference between the terms color number and color value. Color number refers to the number that defines a color in the standard color set (for example, green is color number 2). Color value refers to the actual value of a pixel in video memory, which ultimately determines the color in which that pixel is displayed. The color value is sometimes just called the color. In each graphics mode, video memory is zeroed when the fg_setmode routine is called. This means all pixels are initially set to color value 0, which by default is black. For this reason, color value 0 is often called the background color in graphics video modes. The Fastgraph routine fg_setcolor defines the color in which subsequent graphics operations are performed. This color is called the current color. Chapter 5: The Use of Color 51 Depending on the video mode, the current color can reference a color value (in CGA and Hercules graphics modes), a palette register (in Tandy, EGA, and VGA graphics modes), or a video DAC register (in 256-color modes). The fg_setcolor routine takes a single integer argument that specifies the color. When fg_setmode is called, it sets the current color to 0. The Fastgraph routine fg_getcolor returns the current color, as defined in the most recent call to fg_setcolor. The fg_getcolor routine has no arguments and returns the current color as its function value. CGA Color Modes The CGA color modes (modes 4 and 5) have six sets of available colors, called palettes, numbered 0 to 5. Each palette consists of four colors, numbered 0 to 3. In each palette, the background color (color value 0) can be selected from the standard color set, but the other 3 colors are fixed. The following table shows the fixed colors assigned to each palette. palette 0 palette 1 palette 2 color 1 light green light cyan light cyan color 2 light red light magenta light red color 3 yellow bright white bright white palette 3 palette 4 palette 5 color 1 green cyan cyan color 2 red magenta red color 3 brown white white Palette 1, with a black background, is the default palette when you select mode 4. Palette 2, with a black background, is the default palette when you select mode 5. The CGA color modes have a border area called the overscan between the addressable pixel space and the physical edges of the screen. The overscan area is always displayed in the background color, regardless of which CGA palette is used. In CGA color modes, the fg_setcolor routine defines the current color by referencing one of the four color values. The fg_palette routine selects one of the six palettes and defines the background color for that palette. The first argument of the fg_palette routine is an integer between 0 and 5 that specifies the palette number. The second argument is an integer between 0 and 15 that defines the background color, using the color numbers in the standard color set. Example 5-1 demonstrates the use of the fg_palette and fg_setcolor routines in mode 4. After establishing the video mode, the program selects palette 0 and makes the background color blue (color number 1). It then makes color 3 in palette 0 (yellow) the current color and displays the word "Hello". Finally, it restores the original video mode and screen attributes before returning to DOS. 52 Fastgraph User's Guide Example 5-1. #include void main(void); void main() { int mode; mode = fg_getmode(); fg_setmode(4); fg_palette(0,1); fg_setcolor(3); fg_text("Hello",5); fg_waitkey(); fg_setmode(mode); fg_reset(); } CGA Two-Color Mode The CGA two-color mode (mode 6) has a fixed background color (color value 0) and a user-definable foreground color (color value 1). The background color is always black. The foreground color is bright white by default, but it can be changed to any of the colors in the standard color set. It should be mentioned that changing the foreground color works on true CGA adapters, but there are very few EGA and VGA adapters that correctly implement changing the foreground color in their mode 6 emulation. In mode 6, the fg_setcolor routine defines the current color by referencing one of the two color values. The fg_palette routine defines the actual foreground color (that is, the color of pixels whose color value is 1). To be consistent with the other graphics modes, the fg_palette routine has two arguments, but the first one is not used. The second argument is an integer between 0 and 15 that defines the foreground color, using the color numbers in the standard color set. Example 5-2 demonstrates the use of the fg_palette and fg_setcolor routines in mode 6. After establishing the video mode, the program makes the foreground color yellow (color number 14). It then makes color 1 the current color and displays the word "Hello". Finally, it restores the original video mode and screen attributes before returning to DOS. Example 5-2. #include void main(void); void main() { int mode; mode = fg_getmode(); fg_setmode(6); Chapter 5: The Use of Color 53 fg_palette(0,14); fg_setcolor(1); fg_text("Hello",5); fg_waitkey(); fg_setmode(mode); fg_reset(); } Tandy and PCjr Modes The supported Tandy 1000 or PCjr graphics mode (mode 9) has 16 color values, numbered 0 to 15. Each color value references one of 16 user- definable palette registers, often simply called palettes, also numbered 0 to 15. The values assigned to the palette registers determine the colors in which pixels are displayed. For example, if you assign palette register 2 the value for red, then pixels whose color value is 2 will be red. Each palette can assume one of the 16 colors in the standard color set. By default, the values assigned to the 16 palettes correspond to the identically numbered colors in the standard color set. In other words, palette 0 is assigned the value for black, palette 1 is assigned the value for blue, and so forth. In mode 9, the fg_setcolor routine defines the current color by referencing one of the 16 palette registers. The fg_palette routine defines the actual color assigned to a specific palette register. The first argument of the fg_palette routine is an integer between 0 and 15 that specifies the palette number. The second argument is an integer between 0 and 15 that defines the palette value (the color assigned to the palette), using the IRGB color numbers in the standard color set. You also can use the Fastgraph routine fg_setrgb to define the color assigned to a specific palette register. Whereas the fg_palette routine does this using a color number from the standard color set, fg_setrgb defines a palette register using red, green, and blue color components plus an intensity component. The first argument of the fg_setrgb routine is an integer between 0 and 15 that specifies the palette register number. The remaining three arguments are each integer values between -1 and 1 that respectively specify the red, green, and blue color components for that palette register. The meanings of the color components are: -1 = color bit and intensity bit are set 0 = color bit is reset 1 = color bit is set Since there is only one intensity bit in mode 9 color values, specifying -1 for any of the RGB color components produces an intense color. For example, the color light cyan is color number 11 in the standard color set, and it is produced by combining green and blue and setting the intensity bit. This means any of these four statements fg_palette(1,11); fg_setrgb(1,0,-1,1); fg_setrgb(1,0,1,-1); fg_setrgb(1,0,-1,-1); 54 Fastgraph User's Guide could be used to define palette register 1 as light cyan in mode 9. Example 5-3 demonstrates the use of the fg_palette and fg_setcolor routines in mode 9. After establishing the video mode, the program defines palette 0 to be blue (1) and palette 1 to be yellow (14). Note that defining palette 0 changes the background color. It then makes color 1 the current color and displays the word "Hello". After waiting for a keystroke, the program changes the color of "Hello" by changing palette 1 to bright white (15). Finally, it restores the original video mode and screen attributes before returning to DOS. Example 5-3. #include void main(void); void main() { int mode; mode = fg_getmode(); fg_setmode(9); fg_palette(0,1); fg_palette(1,14); fg_setcolor(1); fg_text("Hello",5); fg_waitkey(); fg_palette(1,15); fg_waitkey(); fg_setmode(mode); fg_reset(); } Hercules Mode The Hercules graphics mode (mode 11) has a fixed background color (color value 0) and a fixed foreground color (color value 1). The background color is always black, and the foreground color is dependent on the monochrome display being used (typically, it is green, amber, or white). The fg_setcolor routine defines the current color value by referencing one of the two color values. The fg_palette routine has no effect in mode 11. Example 5-4 demonstrates the use of the fg_setcolor routine in mode 11. After establishing the video mode, the program makes color 1 the current color and displays the word "Hello". It then restores the original video mode and screen attributes before returning to DOS. Chapter 5: The Use of Color 55 Example 5-4. #include void main(void); void main() { int mode; mode = fg_getmode(); fg_setmode(11); fg_setcolor(1); fg_text("Hello",5); fg_waitkey(); fg_setmode(mode); fg_reset(); } Hercules Low-Resolution Mode The Hercules low-resolution graphics mode (mode 12) has four color values, numbered 0 to 3. The background color is always black, colors 1 and 2 are half intensity, and color 3 is full intensity. Colors 1 and 2 both produce normal intensity colors, but they do so with different pixel patterns -- color 1 turns on the odd-numbered physical pixels, while color 2 turns on the even-numbered physical pixels. The appearance of colors 1 to 3 is dependent on the monochrome display being used (typically, it is green, amber, or white). The fg_setcolor routine defines the current color value by referencing one of the four color values. The fg_palette routine has no effect in mode 12. Example 5-5 demonstrates the use of the fg_setcolor routine in mode 12. After establishing the video mode, the program makes color 3 the current color and displays the word "Hello". It then restores the original video mode and screen attributes before returning to DOS. Example 5-5. #include void main(void); void main() { int mode; mode = fg_getmode(); fg_setmode(12); fg_setcolor(3); fg_text("Hello",5); fg_waitkey(); 56 Fastgraph User's Guide fg_setmode(mode); fg_reset(); } EGA 200-Line Modes The 200-line EGA graphics modes (modes 13 and 14) have 16 color values, numbered 0 to 15. Each color value references one of 16 user-definable palette registers, often simply called palettes, also numbered 0 to 15. The values assigned to the palette registers determine the colors in which pixels are displayed. For example, if you assign palette register 2 the value for red, then pixels whose color value is 2 will be red. Each palette can assume one of the 16 colors in the standard color set. By default, the values assigned to the 16 palettes correspond to the identically numbered colors in the standard color set. In other words, palette 0 is assigned the value for black, palette 1 is assigned the value for blue, and so forth. In modes 13 and 14, the fg_setcolor routine defines the current color by referencing one of 16 available palette registers. The fg_palette routine defines the actual color assigned to a specific palette register. The first argument of the fg_palette routine is an integer between 0 and 15 that specifies the palette number. The second argument is an integer that defines the palette value (the color assigned to the palette). Although the actual colors are taken from the standard color set, the binary structure of a palette value is different from the IRGB format used in the standard color set. In modes 13 and 14, the binary structure of a palette value is IxRGB; bit 3 is ignored. The mode 13 and mode 14 palette values that correspond to the standard color set are thus: value color value color 0 black 16 gray 1 blue 17 light blue 2 green 18 light green 3 cyan 19 light cyan 4 red 20 light red 5 magenta 21 light magenta 6 brown 22 yellow 7 white 23 bright white You also can use the Fastgraph routine fg_setrgb to define the color assigned to a specific palette register. Whereas the fg_palette routine does this using a color number from the standard color set, fg_setrgb defines a palette register using red, green, and blue color components, plus an intensity component. The first argument of the fg_setrgb routine is an integer between 0 and 15 that specifies the palette register number. The remaining three arguments are each integer values between -1 and 1 that Chapter 5: The Use of Color 57 respectively specify the red, green, and blue color components for that palette register. The meanings of the color components are: -1 = color bit and intensity bit are set 0 = color bit is reset 1 = color bit is set Since there is only one intensity bit in mode 13 and 14 color values, specifying -1 for any of the RGB color components produces an intense color. For example, the color light cyan is represented by the color value 19, and it is produced by combining green and blue and setting the intensity bit. This means any of these four statements fg_palette(1,19); fg_setrgb(1,0,-1,1); fg_setrgb(1,0,1,-1); fg_setrgb(1,0,-1,-1); could be used to define palette register 1 as light cyan in modes 13 and 14. The Fastgraph routine fg_setcolor defines the color value (that is, the palette number) in which subsequent graphics operations are performed. The fg_setcolor routine takes a single integer argument that specifies this color. When fg_setmode is called, it sets the color value to 0. The Fastgraph routine fg_getcolor returns the current color value, as defined in the most recent call to fg_setcolor. The fg_getcolor routine has no arguments and returns the current color as the function value. Example 5-6 demonstrates the use of the fg_palette and fg_setcolor routines in mode 13. After establishing the video mode, the program defines palette 0 to be blue (1) and palette 1 to be yellow (22). Note that defining palette 0 changes the background color. It then makes color 1 the current color and displays the word "Hello". After waiting for a keystroke, the program changes the color of "Hello" by changing palette 1 to bright white (23). Finally, it restores the original video mode and screen attributes before returning to DOS. Example 5-6. #include void main(void); void main() { int mode; mode = fg_getmode(); fg_setmode(13); fg_palette(0,1); fg_palette(1,22); fg_setcolor(1); fg_text("Hello",5); fg_waitkey(); 58 Fastgraph User's Guide fg_palette(1,23); fg_waitkey(); fg_setmode(mode); fg_reset(); } EGA Monochrome Mode The EGA monochrome graphics mode (mode 15) assigns display attributes to its four color values, numbered 0 to 3. Each color value references one of four user-definable palette registers, often simply called palettes, numbered 0, 1, 4, and 5. This numbering scheme might seem rather strange at first, but it results from the disabling of two of the four video memory bit planes in mode 15. The values assigned to the palette registers determine the pixel display attribute. For example, if you assign palette register 1 the value for bold, then pixels whose value is 1 will be bold. In mode 15, the fg_setcolor routine defines the current color (actually, a display attribute) by referencing one of the four palette registers. The fg_palette routine defines the actual display attribute assigned to a specific palette register. The first argument of the fg_palette routine is an integer that specifies the palette number. The second argument is an integer that defines the palette value (the display attribute assigned to the palette). For each palette register, the following table shows the default palette value and its associated display attribute. palette palette display number value attribute 0 0 invisible 1 8 normal 4 24 bold 5 24 bold Example 5-7 demonstrates the use of the fg_palette and fg_setcolor routines in mode 15. After establishing the video mode, the program makes color 4 (actually, palette 4, which is bold by default) the current color and displays the word "Hello". After waiting for a keystroke, the program changes the display attribute of "Hello" by changing palette 4 to normal intensity (palette value 8). Finally, it restores the original video mode and screen attributes before returning to DOS. Example 5-7. #include void main(void); void main() { int mode; Chapter 5: The Use of Color 59 mode = fg_getmode(); fg_setmode(15); fg_setcolor(4); fg_text("Hello",5); fg_waitkey(); fg_palette(4,8); fg_waitkey(); fg_setmode(mode); fg_reset(); } EGA Enhanced Mode The EGA enhanced graphics mode (mode 16) has 16 color values, numbered 0 to 15. Each color value references one of 16 user-definable palette registers, often simply called palettes, also numbered 0 to 15. The values assigned to the palette registers determine the colors in which pixels are displayed. For example, if you assign palette register 2 the value for red, then pixels whose color value is 2 will be red. Each palette can assume one of 64 available colors. By default, the values assigned to the 16 palettes correspond to the identically numbered colors in the standard color set. In other words, palette 0 is assigned the value for black, palette 1 is assigned the value for blue, and so forth. There are a few EGA-compatible adapters that do not properly assign the default colors to the 16 palette registers, so it is a good practice to do this explicitly in mode 16. In mode 16, the fg_setcolor routine defines the current color value by referencing one of the 16 palette registers. The fg_palette routine defines the actual color assigned to a specific palette register. The first argument of the fg_palette routine is an integer between 0 and 15 that specifies the palette number. The second argument is an integer that defines the palette value (the color assigned to the palette). The binary structure of a palette value is different from the IRGB format used in the standard color set. In mode 16, the binary structure of a palette value is a 6-bit quantity of the form rgbRGB, where the lower case letters represent the low intensity (1/3 intensity) color components, and the upper case letters represent the normal intensity (2/3 intensity) color components. The mode 16 palette values that correspond to the standard color set are: value color value color 0 black 56 gray 1 blue 57 light blue 2 green 58 light green 3 cyan 59 light cyan 4 red 60 light red 5 magenta 61 light magenta 20 brown 62 yellow 7 white 63 bright white 60 Fastgraph User's Guide The normal intensity components in mode 16 produce the same normal intensity colors as in other 16-color graphics modes. Similarly, combining the low and normal intensities in mode 16 produces the high intensity colors of the other modes. The only exception to this is for the default brown, formed from the bit pattern 010100 (20 decimal). This value produces a more true brown than the value 6 decimal, which is really an olive green. The palette values used in mode 16 are 6-bit quantities, which means there are 64 different colors available in mode 16. This group of 64 colors consists of the 16 colors in the standard color set plus 48 additional colors that are not available in any of the other EGA modes. However, because the EGA palette registers hold 4-bit quantities, only 16 of these colors can be displayed at the same time. In other words, the EGA enhanced mode provides the capability of displaying 16 simultaneous colors from a group of 64. You also can use the Fastgraph routine fg_setrgb to define the color assigned to a specific palette register. Whereas the fg_palette routine does this using a value between 0 and 63, fg_setrgb defines a palette register using red, green, and blue color components. The first argument of the fg_setrgb routine is an integer between 0 and 15 that specifies the palette register number. The remaining three arguments are each integer values between 0 and 3 that respectively specify the intensities in thirds of the red, green, and blue color components for that palette register. For example, the color cyan is represented by the value 3 in the above table, and it is produced by combining normal intensity (2/3 intensity) green and blue. This means either of the statements fg_palette(1,3); fg_setrgb(1,0,2,2); could be used to define palette register 1 as cyan. Example 5-8 demonstrates the use of the fg_palette and fg_setcolor routines in mode 16. It uses the Fastgraph routine fg_rect (discussed in the next chapter) to draw rectangles of a specified size. After establishing the video mode, the program uses a for loop to draw 16 equal-size rectangles, one in each of the 16 color values. In the same loop, the program uses the fg_palette routine to change each palette to black. The while loop that follows performs four iterations. The first iteration changes palette 0 to 0, palette 1 to 1, and so forth. Hence, the 16 rectangles appear in the palette values 0 to 15. The rectangles remain in these colors until is key is pressed to begin the next iteration. The second iteration changes palette 0 to 16, palette 1 to 17, and so forth. This makes the 16 rectangles appear in the palette values 16 to 31. Iterations three and four are similar, so the overall effect of the program is to display all 64 colors, 16 at a time. Finally, the program restores the original video mode and screen attributes before returning to DOS. Chapter 5: The Use of Color 61 Example 5-8. #include void main(void); #define COLORS 16 #define WIDTH 40 void main() { int base; int color; int minx, maxx; int mode; mode = fg_getmode(); fg_setmode(16); base = 0; minx = 0; maxx = WIDTH - 1; for (color = 0; color < COLORS; color++) { fg_palette(color,0); fg_setcolor(color); fg_rect(minx,maxx,0,349); minx = maxx + 1; maxx = maxx + WIDTH; } while (base < COLORS*4) { for (color = 0; color < COLORS; color++) fg_palette(color,base+color); base += COLORS; fg_waitkey(); } fg_setmode(mode); fg_reset(); } VGA and MCGA Two-Color Mode The VGA and MCGA high-resolution two-color mode (mode 17) has a background color (color value 0) and a foreground color (color value 1). Each color value references one of two user-definable palette registers, often simply called palettes, also numbered 0 and 1. Each palette register in turn references one of 16 user-definable 18-bit video DAC registers, numbered 0 to 15. The values assigned to the palette registers and video DAC registers determine the colors in which pixels are displayed. For example, if palette register 1 contains the value 3, and video DAC register 3 contains the color value for red, then pixels whose color value is 1 (that is, the foreground pixels) will be red. By default, palette register 0 references video DAC register 0, and palette register 1 references video DAC register 1. In addition, video DAC register 0 initially contains the color value for black, while the other 15 62 Fastgraph User's Guide video DAC registers (1 through 15) contain the color value for bright white. This means background pixels (color value 0) are black by default, while foreground pixels (color value 1) are bright white. The 18-bit video DAC values consist of three 6-bit red, green, and blue color components. Hence, each color component is an integer between 0 and 63; increasing values produce more intense colors. The default color components for DAC register 0 are red=0, blue=0, and green=0, which produces black. The default values for the other DAC registers are red=63, blue=63, and green=63, which produces bright white. Because the video DAC registers are 18 bits long, each DAC can specify one of 262,144 (218) colors. However, because the palette registers hold 1-bit quantities, only two of these colors can be displayed at the same time. In other words, mode 17 provides the capability of displaying two simultaneous colors from a group of 262,144. In mode 17, the fg_setcolor routine defines the current color by referencing one of the two palette registers. The fg_palette routine defines the value of a palette register by referencing one of the 16 video DAC registers. That is, the fg_palette routine specifies the video DAC register that a palette register references. The first argument of the fg_palette routine is either 0 or 1 and specifies the palette number. The second argument is an integer between 0 and 15 that specifies the video DAC register for that palette. The Fastgraph routine fg_setrgb defines the value of a video DAC register in mode 17. The first argument of the fg_setrgb routine is an integer between 0 and 15 that specifies the DAC register number. The remaining three arguments are each integer values between 0 and 63 that respectively specify the red, green, and blue color components for that DAC register. Example 5-9 demonstrates the use of the fg_palette, fg_setrgb, and fg_setcolor routines in mode 17. After establishing the video mode, the program defines DAC register 0 to be blue (red=0, green=0, blue=42) and DAC register 1 to be yellow (red=63, green=63, blue=21). Note that defining DAC register 0 changes the background color because palette 0 references DAC register 0. The program then makes color 1 the current color (palette 1 still references DAC register 1) and displays the word "Hello" in yellow. After waiting for a keystroke, the program changes the color of "Hello" by making palette 1 reference DAC register 15 (which still contains its default value, bright white). Finally, it restores the original video mode and screen attributes before returning to DOS. Example 5-9. #include void main(void); void main() { int mode; mode = fg_getmode(); fg_setmode(17); fg_setrgb(0,0,0,42); fg_setrgb(1,63,63,21); Chapter 5: The Use of Color 63 fg_setcolor(1); fg_text("Hello",5); fg_waitkey(); fg_palette(1,15); fg_waitkey(); fg_setmode(mode); fg_reset(); } VGA 16-Color Mode The VGA high-resolution two-color mode (mode 18) has 16 color values, numbered 0 to 15. Each color value references one of 16 user-definable palette registers, often simply called palettes, also numbered 0 to 15. Each palette register in turn references one of 16 user-definable 18-bit video DAC registers, also numbered 0 to 15. The values assigned to the palette registers and video DAC registers determine the colors in which pixels are displayed. For example, if palette register 1 contains the value 3, and video DAC register 3 contains the color value for red, then pixels whose color value is 1 will be red. By default, each of the 16 palette registers references the video DAC register of the same number. In addition, the 16 video DAC registers respectively contain the color values for the 16 colors in the standard color set. The 18-bit video DAC values consist of three 6-bit red, green, and blue color components. Hence, each color component is an integer between 0 and 63; increasing values produce more intense colors. The default RGB color components for the 16 video DAC registers are: DAC R G B color DAC R G B color 0 0 0 0 black 8 21 21 21 gray 1 0 0 42 blue 9 21 21 63 light blue 2 0 42 0 green 10 21 63 21 light green 3 0 42 42 cyan 11 21 63 63 light cyan 4 42 0 0 red 12 63 21 21 light red 5 42 0 42 magenta 13 63 21 63 light magenta 6 42 21 0 brown 14 63 63 21 yellow 7 42 42 42 white 15 63 63 63 bright white Because the video DAC registers are 18 bits long, each DAC can specify one of 262,144 (218) colors. However, because the palette registers hold 4-bit quantities, only 16 of these colors can be displayed at the same time. In other words, mode 18 provides the capability of displaying 16 simultaneous colors from a group of 262,144. 64 Fastgraph User's Guide In mode 18, the fg_setcolor, fg_palette, and fg_setrgb routines function exactly as in mode 17 with one exception: there are 16 palette registers instead of just two. Example 5-9 on page 62 demonstrates the use of these routines in mode 17, but it also would work in mode 18 if that video mode number were specified in the call to fg_setmode. VGA and MCGA 256-Color Modes The VGA and MCGA 256-color modes (modes 19 through 23) have 256 color values, numbered 0 to 255. Each color value directly references one of 256 user-definable 18-bit video DAC registers, also numbered 0 to 255. The values assigned to the video DAC registers determine the colors in which pixels are displayed. For example, if video DAC register 3 contains the color value for red, then pixels whose color value is 3 will be red. By default, the first 16 video DAC registers (0 to 15) contain the color values for the standard color set. The next 16 DAC registers (16 to 31) contain the color values for a gray scale of gradually increasing intensity. The next 216 DAC registers (32 to 247) contain three groups of 72 colors each, with the first group (32 to 103) at high intensity, the second group (104 to 175) at moderate intensity, and the third group (176 to 247) at low intensity. Each group consists of three ranges of decreasing saturation (increasing whiteness), with each range varying in hue from blue to red to green. Finally, the last 8 DAC registers (248 to 255) alternate between black and bright white. This information is summarized in the following table. DACs default color values 0 to 15 standard color set 16 to 31 gray scale of gradually increasing intensity 32 to 55 high saturation, high intensity colors 56 to 79 moderate saturation, high intensity colors 80 to 103 low saturation, high intensity colors 104 to 127 high saturation, moderate intensity colors 128 to 151 moderate saturation, moderate intensity colors 152 to 175 low saturation, moderateintensity colors 176 to 199 high saturation, low intensity colors 200 to 223 moderate saturation, low intensity colors 224 to 247 low saturation, low intensity colors 248 to 255 alternate between black and bright white Chapter 5: The Use of Color 65 The 18-bit video DAC values consist of three 6-bit red, green, and blue color components. Hence, each color component is an integer between 0 and 63; increasing values produce more intense colors. Because the video DAC registers are 18 bits long, each DAC can specify one of 262,144 (218) colors. However, because the color values are 8-bit quantities, only 256 of these colors can be displayed at the same time. In other words, modes 19 through 23 provide the capability of displaying 256 simultaneous colors from a group of 262,144. In the VGA and MCGA 256-color video modes, the fg_setcolor routine defines the current color by referencing on of the 256 video DAC registers. The fg_setrgb routine defines the actual color of a video DAC register. The first argument of the fg_setrgb routine is an integer between 0 and 255 that specifies the DAC register number. The remaining three arguments are each integer values between 0 and 63 that respectively specify the red, green, and blue color components for that DAC register. Another Fastgraph routine, fg_getrgb, returns the color components for a specified DAC register. Its arguments are the same as for fg_setrgb, except the last three arguments (the return values) are passed by reference rather than by value. You also can use the Fastgraph routine fg_palette to define the value of a video DAC register in modes 19 through 23. The first argument of the fg_palette routine is an integer between 0 and 255 that specifies the DAC register number. The second argument is an integer between 0 and 63 that specifies the color value for that video DAC register, using the same 64 values as in the EGA enhanced mode (mode 16). Example 5-10 demonstrates the use of the fg_setcolor routine in mode 19. The program uses the Fastgraph routine fg_rect to draw vertical lines. After establishing the video mode, the program uses a for loop to draw 256 vertical lines, one in each of the 256 colors (using the default DAC values). Finally, the program restores the original video mode and screen attributes before returning to DOS. Example 5-10. Example 5-11. #include #include void main(void); void main(void); #define COLORS 256 void main() { void main() int old_mode; { int red,green, blue; int base; int color; old_mode = fg_getmode(); int mode; fg_setmode(19); 66 Fastgraph User's Guide int x; fg_setcolor(103); mode = fg_getmode(); fg_text("Hello",5); fg_setmode(19); fg_waitfor(18); x = 32; fg_getrgb(103,&red,&green,&blue); for (color=0; color 0){ fg_setcolor(color); if (red > 0) red--; fg_rect(x,x,0,199); if (green > 0) green--; x++; if (blue > 0) blue--; } fg_setrgb(103,red,green,blue); fg_waitkey(); fg_waitfor(1); } fg_setmode(mode); fg_reset(); fg_setmode(old_mode); } fg_reset(); } Example 5-11 shows an interesting effect available in VGA and MCGA modes. The program uses the Fastgraph routine fg_waitfor (discussed in Chapter 14) to delay the program's execution. After establishing the video mode, the program displays the word "Hello" in color 103, which by default is a pastel blue. It then uses the Fastgraph routine fg_getrgb to retrieve the color components for this color. The while loop gradually decreases the color components until all three components are zero, which makes the word "Hello" smoothly fade to black. Finally, the program restores the original video mode and screen attributes before returning to DOS. The fg_setrgb and fg_getrgb routines work with individual DAC registers. If you want to define or retrieve a block of consecutive DAC registers, using the fg_setdacs and fg_getdacs routines is more efficient. The fg_setdacs routine defines the values of a block of contiguous DAC registers. Its first argument is the index of the first DAC register to define (between 0 and 255), and its second argument is the number of DAC registers to define (between 1 and 256). The third argument is a byte array containing the RGB color components for the DAC registers being defined. The array's first three bytes contain the red, green, and blue components for the first DAC, Chapter 5: The Use of Color 67 the next three for the second DAC, and so forth. The size of this array must be at least three times the value of the second argument. The fg_getdacs arguments are the same as those for fg_setdacs, but the RGB array instead receives the current values of the specified DAC registers. Both routines treat the DAC register numbers in a circular fashion (for example, defining four DACs starting with number 254 will define DACs 254, 255, 0, and 1). Example 5-12 is similar to example 5-11, but it fades many colors simultaneously. The program displays seven asterisks, one each in colors 9 through 15. It uses fg_getdacs to obtain the current settings of the corresponding DAC registers; these values are stored in the array RGBvalues. The while loop gradually fades the RGB components to zero, using fg_setdacs to update their values, similar to the method of example 5-11. This illustrates an attractive way of turning an image into a blank screen. Example 5-12. #include void main(void); void main() { int decreasing; int i; int old_mode; char RGBvalues[21]; old_mode = fg_getmode(); fg_setmode(19); for (i = 9; i <= 15; i++) { fg_setcolor(i); fg_text("*",1); } fg_getdacs(9,7,RGBvalues); fg_waitfor(18); do { decreasing = 0; for (i = 0; i < 21; i++) if (RGBvalues[i] > 0) { RGBvalues[i]--; decreasing = 1; } fg_setdacs(9,7,RGBvalues); fg_waitfor(1); } while (decreasing); fg_setmode(old_mode); fg_reset(); } Note that examples 5-11 and 5-12 also would work in video modes 17 and 18 as long as you just use the first 16 video DAC registers. 68 Fastgraph User's Guide RGB Color Mapping If you're developing an application that runs in 256-color and 16-color graphics modes, you've probably noticed the inherent differences in defining color values. In fact, the palette register values even use different structures within the various 16-color modes. The Fastgraph routine fg_maprgb helps simplify these differences. It maps three RGB color components (each between 0 and 63) into a 16-color palette value suitable for the current video mode. Of course, the range of available colors is much more restricted in the 16-color modes than in the 256-color modes, so fg_maprgb must map the RGB components into the closest available color. Example 5-13 runs in any 16-color or 256-color graphics mode and demonstrates the use of the fg_maprgb routine. In 256-color modes, the program simply uses fg_setrgb to define DAC register 1 to a pastel blue (red=45, green=49, blue=63). In 16-color modes, however, the program calls fg_maprgb to convert the color components into a palette value in IRGB, IxRGB, or rgbRGB format (depending on the current video mode). The fg_maprgb return value is passed to fg_palette to set palette register 1 to the closest available color defined by the specified RGB components. Example 5-13. #include #include #include void main(void); void main() { int new_mode, old_mode; new_mode = fg_bestmode(320,200,1); if (new_mode < 0 || new_mode == 4 || new_mode == 12) { printf("This program requires a 320 x 200 "); printf("16-color or 256-color graphics mode.\n"); exit(1); } old_mode = fg_getmode(); fg_setmode(new_mode); fg_setcolor(1); if (new_mode <= 16) fg_palette(1,fg_maprgb(45,49,63)); else fg_setrgb(1,45,49,63); fg_text("Hello",5); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Chapter 5: The Use of Color 69 Defining All Palette Registers Fastgraph includes a routine fg_palettes that defines all 16 palette registers in modes 9, 13, 14, 16, and 18. You also can use the fg_palettes routine to define the first 16 video DAC registers in modes 19 through 23. It has no effect in other video modes. Using fg_palettes is much faster than calling the fg_palette routine 16 times. The argument to the fg_palettes routine is a 16-element integer array that contains the color values assigned respectively to palette registers (or video DAC registers) 0 to 15. Example 5-14 demonstrates how to zero the palette registers (that is, change them all to black) in mode 13. Example 5-14. #include void main(void); int zeroes[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; void main() { int mode; mode = fg_getmode(); fg_setmode(13); fg_palettes(zeroes); fg_setmode(mode); fg_reset(); } Of course, as this example is written, it appears to do nothing more than blank the screen. Its purpose is to show an example of the fg_palettes routine. Virtual Colors By this time it should be clear the use of color is rather specific to each graphics video mode. One of the most obvious differences is the number of available colors in each mode; it ranges from 2 to 256. By available colors, we mean the number of colors that can be displayed simultaneously. To simplify programming in graphics modes, Fastgraph provides 256 virtual colors. The virtual colors are used in the graphics video modes having fewer than 256 available colors. Virtual colors allow you to use 256 color indices in all graphics modes, even if a particular mode does not have 256 available colors. When you establish a video mode with the fg_setmode routine, Fastgraph initializes all the virtual color indices. It does this by replicating the video mode's color values through the 256 virtual color indices. For example, the CGA color modes (4 and 5) have four color values, numbered 0 through 3. In these modes, the fg_setmode routine initializes color indices 70 Fastgraph User's Guide 0, 4, 8, ... , 252 to 0; color indices 1, 5, 9, ... , 253 to 1; color indices 2, 6, 10, ... , 254 to 2; and color indices 3, 7, 11, ... , 255 to 3. Similarly, in 16-color graphics modes the color indices 0, 16, 32, ... , 240 are set to 0, and so forth. In the monochrome EGA graphics video mode (mode 15), the color values are numbered 0, 1, 4, and 5, so fg_setmode replicates the color indices in groups of eight, even though there are only four available colors. An analysis of the color value sequences reveals an often useful feature: by default, virtual color 0 is black and virtual color 15 is white or bright white in all graphics video modes. It is thus possible to write a multiple-mode program using the same color indices for each graphics mode. For example, a program that contains the statement fg_setcolor(5) would produce subsequent graphics in color 5 (magenta by default) when running in a 16-color graphics mode. It would produce subsequent graphics in color 1 (light cyan by default) when running in a CGA color mode. This is because 1 is the default value assigned to virtual color index 5 in the CGA color modes. The fg_setmode routine establishes default values for the 256 virtual color indices, but it might be desirable to assign other available colors to them. Going back to the discussion in the previous paragraph, color number 2 is light magenta in the default CGA mode 4 palette. It might make more sense if the color value 2 were assigned to virtual color index 5, as this would make the graphics drawn in color 5 the same color in mode 4 as in other color modes. The Fastgraph routine fg_defcolor is provided for this purpose. The fg_defcolor routine assigns a color value to a virtual color index. It has two arguments: the first specifies the virtual color index (between 0 and 255), and the second specifies the color value (between 0 and the number of available colors in the current video mode). For example, the statement fg_defcolor(5,2); would assign the color value 2 to the color index 5. Another Fastgraph routine, fg_getindex, returns the current value assigned to a specified color index. After executing the above call to fg_defcolor, the statement color = fg_getindex(5); would store the value 2 (the current value of color index 5) in the integer variable color. It is important to understand the difference between virtual colors and palette registers. Modifying the value of a palette register changes the color of all pixels already drawn using that palette. Modifying a virtual color index does not do this; it only specifies any graphics drawn in that color from this point on will appear in the new color. Example 5-15 demonstrates the use of virtual colors in mode 4. After establishing the video mode, the program uses the fg_defcolor routine to define virtual color indices 0 and 255 to be 1, which by default is light cyan in mode 4. It then draws characters using color indices 0, 1, and 255, and in each case the characters appear in light cyan. Finally, the program restores the original video mode and screen attributes before returning to DOS. Chapter 5: The Use of Color 71 Example 5-15. #include void main(void); void main() { int mode; mode = fg_getmode(); fg_setmode(4); fg_defcolor(0,1); fg_defcolor(255,1); fg_setcolor(0); fg_text("0",1); fg_setcolor(1); fg_text(" 1",2); fg_setcolor(255); fg_text(" 255",4); fg_waitkey(); fg_setmode(mode); fg_reset(); } A Multiple-Mode Example Even though the color capabilities differ between the supported video modes, Fastgraph makes it easy to write a program that runs in many video modes. This section will present an example of such a program. Example 5-16 illustrates a program that will run in any of Fastgraph's supported video modes. The program first asks for the video mode number, checks if the mode number is valid, and then checks if the requested mode is available on the user's system. After doing this, the program establishes the video mode and performs its mode-specific code. It then displays a brief message that includes the video mode number in which the program is running. This information remains on the screen until a key is pressed, at which time the program restores the original video mode and screen attributes before returning to DOS. Example 5-16. #include #include #include void main(void); void main() { int mode, old_mode; char string[5]; 72 Fastgraph User's Guide /* Ask for the video mode number */ printf("Which video mode? "); scanf("%d",&mode); /* Make sure the entered value is valid */ if (mode < 0 || mode > 23) { printf("%d is not a valid video mode number.\n",mode); exit(1); } /* Make sure the requested video mode is available */ if (fg_testmode(mode,1) == 0) { printf("Mode %d is not available on this system.\n",mode); exit(1); } /* Establish the video mode */ old_mode = fg_getmode(); fg_setmode(mode); /* Perform mode-specific initializations */ if (mode <= 3 || mode == 7) /* text modes */ fg_cursor(0); else if (mode == 4 || mode == 5) { /* CGA color modes */ fg_palette(0,0); fg_defcolor(14,3); } else if (mode == 6) { /* CGA two-color mode */ fg_palette(0,14); fg_defcolor(14,1); } else if (mode == 11) /* Hercules mode */ fg_defcolor(14,1); else if (mode == 12) /* Hercules low-res mode */ fg_defcolor(14,3); else if (mode == 17) { /* VGA two-color mode */ fg_palette(1,14); fg_setrgb(14,63,63,21); fg_defcolor(14,1); } /* Display a message that includes the video mode number */ fg_setcolor(14); fg_text("I'm running in mode ",20); sprintf(string,"%d. ",mode); fg_text(string,3); /* Wait for a keystroke */ fg_waitkey(); Chapter 5: The Use of Color 73 /* Restore the original video mode and screen attributes */ fg_setmode(old_mode); fg_reset(); } Example 5-16 displays its message in yellow for those video modes that offer color. In monochrome video modes, it displays the message in normal intensity. The program uses virtual color 14, which by default is yellow in many video modes; the mode-specific code in example 5-16 makes color 14 yellow in other video modes. In text video modes (modes 0 to 3 and 7), the program uses the fg_cursor routine to make the cursor invisible. In CGA color modes (modes 4 and 5), the program uses the fg_palette routine to select a CGA palette that contains yellow as color 3 and then uses fg_defcolor to assign color 3 to virtual color 14. In CGA two-color mode (mode 6), the program uses the fg_palette routine to make color 1 yellow and then uses fg_defcolor to assign color 1 to virtual color 14. In the Hercules modes (modes 11 and 12), the program uses the fg_defcolor routine to assign the value for normal intensity pixels to color 14. In VGA two-color mode (mode 17), the program uses the fg_palette routine to assign video DAC register 14 to palette register 1. It then defines video DAC register 14 to be yellow with the fg_setrgb routine and finally uses fg_defcolor to assign color 1 (that is, palette register 1) to virtual color 14. In all other video modes, color 14 is yellow by default. Summary of Color-Related Routines This section summarizes the functional descriptions of the Fastgraph routines presented in this chapter. More detailed information about these routines, including their arguments and return values, may be found in the Fastgraph Reference Manual. FG_DEFCOLOR assigns a color value to a virtual color index. This routine is only meaningful in the graphics video modes that have fewer than 256 available colors. FG_GETCOLOR returns the current text attribute (in text modes) or color index (in graphics modes), as specified in the most recent call to fg_setattr or fg_setcolor. FG_GETDACS retrieves the red, green, and blue color components for a block of consecutively numbered video DAC registers. This routine is only meaningful in VGA and MCGA graphics modes. FG_GETINDEX returns the color value assigned to a specified virtual color index. In text modes and in graphics modes that have 256 available colors, this routine returns the value passed to it. FG_GETRGB returns the red, green, and blue color components for a specified video DAC register. This routine is only meaningful in VGA and MCGA graphics modes. FG_MAPRGB maps six-bit red, green, and blue color components into a suitable palette value for the current video mode. You can then pass this value to the fg_palette routine. This routine is meaningful only in 16-color graphics video modes. 74 Fastgraph User's Guide FG_PALETTE has different functions depending on the current graphics video mode. For the CGA four-color modes, it establishes the current palette (of six available) and defines the background color for that palette. In the CGA two-color mode, it defines the foreground color. For the Tandy/PCjr, EGA, and VGA graphics modes, it defines the value of a single palette register. For the 256-color MCGA and VGA graphics modes, it defines the value of a single video DAC register. The fg_palette routine has no effect in text modes or Hercules graphics modes. FG_PALETTES defines all 16 palette registers (in Tandy/PCjr, EGA, and VGA graphics modes), or the first 16 video DAC registers (in 256-color MCGA and VGA graphics modes). The fg_palettes routine has no effect in text modes, CGA graphics modes, or Hercules graphics modes. FG_SETATTR establishes the current text attribute in text video modes. This routine has no effect in graphics modes. FG_SETCOLOR establishes the current color index (which may be a virtual color index in graphics modes). In text modes, the fg_setcolor routine provides an alternate method of establishing the current text attribute. FG_SETDACS defines the values of a block of consecutively numbered video DAC registers by specifying their red, green, and blue color components. This routine is only meaningful in VGA and MCGA graphics modes. FG_SETRGB defines the value of a single palette register (in Tandy/PCjr and EGA graphics modes) or video DAC register (in VGA and MCGA modes) by specifying its red, green, and blue color components. The fg_setrgb routine has no effect in text modes, CGA graphics modes, or Hercules graphics modes. Chapter 6 Graphics Fundamentals 76 Fastgraph User's Guide Overview This chapter describes Fastgraph's fundamental graphics routines, sometimes called graphics primitives. These routines perform such functions as clearing the screen, drawing points, drawing solid and dashed lines, drawing closed shapes (polygons, circles, and ellipses), drawing rectangles (solid and dithered), and filling arbitrary regions. Most of these routines have no effect in text video modes, but there are a few exceptions, and they will be noted in the descriptions of those routines. Clearing the Screen The Fastgraph routine fg_erase clears the entire screen in any video mode. In text modes, fg_erase clears the screen by storing a space character (ASCII 32) with a gray foreground attribute in each character cell. In graphics modes, fg_erase clears the screen by setting each pixel to zero. This of course causes each pixel to be displayed its background color. The fg_erase routine has no arguments. Clipping The suppression of graphics outside a pre-defined area is called clipping. Many of Fastgraph's graphics-oriented routines provide clipping, either automatically or through a special version of the routine. Fastgraph includes two routines, fg_setclip and fg_setclipw, to define a rectangular clipping region. The fg_setclip routine defines the clipping region in screen space, while the fg_setclipw routine performs the same function in world space. Each routine takes four arguments: the minimum x, the maximum x, the minimum y, and the maximum y coordinate of the clipping region. The arguments are integer quantities for fg_setclip and floating point quantities for fg_setclipw. For example, the statement fg_setclip(0,159,0,99); would define the upper left quadrant of the screen as the clipping region in a 320 by 200 graphics mode. An implicit clipping region equal to the entire screen is defined as part of the fg_setmode routine's initializations. Clipping is not supported for text modes. Points The Fastgraph routine fg_point provides the most basic graphics operation -- setting a pixel to a specified color. The fg_point routine has two integer arguments. The first specifies the pixel's x coordinate, and the second its y coordinate. The pixel is drawn using the current color value, as specified in the most recent call to fg_setcolor. There is also a world space version of this routine, fg_pointw, that uses floating point arguments. Another Fastgraph routine is available for reading a pixel's color value. The fg_getpixel routine has two integer arguments that specify the (x,y) coordinates for the pixel of interest. There is no world space version Chapter 6: Graphics Fundamentals 77 of the fg_getpixel routine, but you can obtain a pixel's color value in world space by applying the fg_xscreen and fg_yscreen functions to the world space coordinates and passing the resulting values to fg_getpixel. Example 6-1 uses the fg_point routine to draw 100 random points in random colors. It also uses the fg_getpixel routine to insure no two points are adjacent. The program establishes a graphics video mode with the fg_automode and fg_setmode routines. Next, it determines the maximum color value for the selected video mode; note if we used virtual colors (color indices above the maximum color value), some of the colors would be the background color and would thus produce invisible points. The main part of the program is a while loop that first generates a random pair of (x,y) screen coordinates. It then calls the fg_getpixel routine to check the pixels at (x,y) and the eight adjacent positions. If none of these pixels are set, the program generates a random color value and draws a point in that color. After doing this 100 times, the program waits for a keystroke, restores the original video mode and screen attributes, and then returns to DOS. Example 6-1. #include #include void main(void); void main() { int area; int color, old_color; int left; int max_color, max_x, max_y; int new_mode, old_mode; int x, y; old_mode = fg_getmode(); new_mode = fg_automode(); fg_setmode(new_mode); 78 Fastgraph User's Guide if (new_mode == 4) max_color = 3; else if (new_mode == 11 || new_mode == 17) max_color = 1; else if (new_mode == 19) max_color = 255; else max_color = 15; left = 100; max_x = fg_getmaxx() - 1; max_y = fg_getmaxy() - 1; while (left > 0) { x = rand() % max_x + 1; y = rand() % max_y + 1; area = fg_getpixel(x-1,y-1) + fg_getpixel(x,y-1) + fg_getpixel(x+1,y-1) + fg_getpixel(x-1,y) + fg_getpixel(x,y) + fg_getpixel(x+1,y) + fg_getpixel(x-1,y+1) + fg_getpixel(x,y+1) + fg_getpixel(x+1,y+1); if (area == 0) { color = rand() % max_color + 1; fg_setcolor(color); fg_point(x,y); left--; } } fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Chapter 6: Graphics Fundamentals 79 The Graphics Cursor Many of Fastgraph's graphics routines depend on the position of the graphics cursor as a reference point. For example, Fastgraph includes routines to draw lines from the graphics cursor position to a specified position, and the image display routines discussed in Chapter 9 display or retrieve an image relative to the graphics cursor position. The graphics cursor is not a cursor in the true sense; it is simply a pair of (x,y) coordinates with a special meaning. The fg_setmode routine sets the graphics cursor position to the screen space coordinates (0,0), and the fg_initw routine sets it to the world space coordinates (0.0,0.0). Fastgraph includes four routines for changing the graphics cursor position. The fg_move routine sets it to an absolute screen space position, while the fg_movew routine sets it to an absolute world space position. The fg_moverel routine sets the graphics cursor position to a screen space position relative to its current position. The fg_moverw routine does the same in world space. Each of these routines has two arguments that specify the (x,y) coordinates of the new position. For the screen space routines, the arguments are integer quantities. For the world space routines, the arguments are floating point quantities. You can obtain the screen space coordinates of the graphics cursor position with the fg_getxpos and fg_getypos routines. These routines have no arguments and respectively return the x and y coordinates of the graphics cursor position as the function value. To obtain the world space coordinates of the graphics cursor position, you can apply the fg_xworld and fg_yworld functions to the return values of fg_getxpos and fg_getypos. Solid Lines Fastgraph includes four routines for drawing solid lines. All four routines draw lines in the current color value (as determined by the most recent call to fg_setcolor) and observe the clipping limits. The fg_draw routine draws a line from the current graphics cursor position to an absolute screen space position, while the fg_draww routine draws a line to an absolute world space position. The fg_drawrel routine draws a line from the current graphics cursor position to a screen space position relative to it. The fg_drawrw routine does the same in world space. 80 Fastgraph User's Guide Each of these routines has two arguments that specify the (x,y) coordinates of the destination position. For the screen space routines, the arguments are integer quantities. For the world space routines, the arguments are floating point quantities. In either case the destination position becomes the new graphics cursor position. This makes it possible to draw connected lines without calling a graphics cursor movement routine between successive calls to a line drawing routine. Examples 6-2 and 6-3 each draw a pair of crossed lines that divide the screen into quadrants. Example 6-2 does this using the fg_move and fg_draw routines, while example 6-3 uses the fg_moverel and fg_drawrel routines. Both examples draw the lines in bright white, the default for color 15 in all graphics video modes. Example 6-2. Example 6-3. #include #include void main(void); void main(void); void main() void main() { { int max_x, max_y; int max_x, max_y; int mid_x, mid_y; int mid_x, mid_y; int new_mode, old_mode; int new_mode, old_mode; old_mode = fg_getmode(); old_mode = fg_getmode(); new_mode = fg_automode(); new_mode = fg_automode(); fg_setmode(new_mode); fg_setmode(new_mode); max_x = fg_getmaxx(); max_x = fg_getmaxx(); max_y = fg_getmaxy(); max_y = fg_getmaxy(); mid_x = max_x / 2; mid_x = max_x / 2; mid_y = max_y / 2; mid_y = max_y / 2; fg_setcolor(15); fg_setcolor(15); fg_move(mid_x,0); fg_move(mid_x,0); fg_draw(mid_x,max_y); fg_drawrel(0,max_y); fg_move(0,mid_y); fg_moverel(-mid_x,-mid_y); fg_draw(max_x,mid_y); fg_drawrel(max_x,0); fg_waitkey(); fg_waitkey(); fg_setmode(old_mode); fg_setmode(old_mode); fg_reset(); fg_reset(); } } Examples 6-4 and 6-5 are variations of example 6-2. Example 6-4 uses world space rather than screen space to draw the crossed lines. Example 6-5 is the same as example 6-2 except it defines a clipping area to restrict drawing to the upper left quadrant of the screen. The clipping suppresses the right half of the horizontal line and the lower half of the vertical line. Chapter 6: Graphics Fundamentals 81 Example 6-4. Example 6-5. #include #include void main(void); void main(void); void main() void main() { { int new_mode, old_mode; int max_x, max_y; int mid_x, mid_y; old_mode = fg_getmode(); int new_mode, old_mode; new_mode = fg_automode(); fg_setmode(new_mode); old_mode = fg_getmode(); fg_initw(); new_mode = fg_automode(); fg_setworld(-10.0,10.0,-10.0,10.0); fg_setmode(new_mode); fg_setcolor(15); max_x = fg_getmaxx(); fg_movew(0.0,10.0); max_y = fg_getmaxy(); fg_draww(0.0,-10.0); mid_x = max_x / 2; fg_movew(-10.0,0.0); mid_y = max_y / 2; fg_draww(10.0,0.0); fg_waitkey(); fg_setclip(0,mid_x,0,mid_y); fg_setmode(old_mode); fg_setcolor(15); fg_reset(); fg_move(mid_x,0); } fg_draw(mid_x,max_y); fg_move(0,mid_y); fg_draw(max_x,mid_y); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } 82 Fastgraph User's Guide Dashed Lines Fastgraph includes four routines for drawing dashed lines. All four routines draw lines in the current color value (as determined by the most recent call to fg_setcolor) and observe the clipping limits. The fg_dash routine draws a dashed line from the current graphics cursor position to an absolute screen space position, while the fg_dashw routine draws a dashed line to an absolute world space position. The fg_dashrel routine draws a dashed line from the current graphics cursor position to a screen space position relative to it. The fg_dashrw routine does the same in world space. Each of these routines has three arguments. The first two specify the (x,y) coordinates of the destination position. For the screen space routines, these arguments are integer quantities. For the world space routines, these arguments are floating point quantities. The third argument is a 16-bit pattern that defines the appearance of the dashed line. Bits that are set in the pattern produce the visible part of the line, while bits that are reset produce the invisible part. This pattern is repeated as necessary to draw the entire line. For example, the pattern value 3333 hex would produce a dashed line with the first two pixels off, the next two on, the next two off, and so forth. Similarly, the pattern value FFFF hex would produce a solid line. The destination position passed to any of the dashed line routines becomes the new graphics cursor position. This makes it possible to draw connected dashed lines without calling a graphics cursor movement routine between successive calls to a line drawing routine. Example 6-6 draws a pair of crossed dashed lines that divide the screen into quadrants. It does this using the fg_move and fg_dash routines and draws the lines in bright white, the default for color 15 in all graphics video modes. The dash pattern for each line is 3333 hex, which alternates two pixels off and on. Example 6-6. #include void main(void); void main() { int max_x, max_y; int mid_x, mid_y; int new_mode, old_mode; old_mode = fg_getmode(); new_mode = fg_automode(); fg_setmode(new_mode); max_x = fg_getmaxx(); max_y = fg_getmaxy(); mid_x = max_x / 2; Chapter 6: Graphics Fundamentals 83 mid_y = max_y / 2; fg_setcolor(15); fg_move(mid_x,0); fg_dash(mid_x,max_y,0x3333); fg_move(0,mid_y); fg_dash(max_x,mid_y,0x3333); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Polygons, Circles, and Ellipses Fastgraph includes routines for drawing three types of closed shapes: polygons, circles, and ellipses. Both screen space and world space versions of these routines are available. All the routines for drawing closed shapes observe the clipping limits. The fg_polygon routine draws an unfilled polygon in screen space. Fg_polygon requires an array of integer x coordinates as its first argument, and an array of integer y coordinates as its second argument. Each (x,y) coordinate pair from the two arrays is treated as a polygon vertex. In other words, the x coordinate of the first polygon vertex is the first element of the x coordinate array, and the y coordinate of the first vertex is the first element of the y coordinate array. Similarly, the second elements of each array define the second vertex, and so forth. The third argument for fg_polygon is an integer quantity that specifies the number of elements in the two coordinate arrays. Another routine, fg_polygonw, draws an unfilled polygon in world space. The fg_polygonw routine is the same as the fg_polygon routine, except its x and y coordinate arrays must contain floating point values instead of integers. The drawing of the polygon begins at the graphics cursor position. The routine then draws a solid line in the current color to the first vertex, then to the second vertex, and continues in this manner up to the last vertex. If necessary, fg_polygon and fg_polygonw draw a line connecting the last vertex and the original graphics cursor position. This last operation closes the polygon and effectively leaves the graphics cursor position unchanged. Example 6-7 illustrates the use of the fg_polygon routine in the EGA monochrome or enhanced modes (modes 15 and 16). The program exits if neither of these video modes are available. Example 6-7. #include #include #include void main(void); #define VERTICES 10 84 Fastgraph User's Guide int x[] = {200,300,400,400,300,240,160,160,200,200}; int y[] = {100, 80,100,220,320,320,240,200,160,160}; void main() { int old_mode; old_mode = fg_getmode(); if (fg_testmode(16,1)) fg_setmode(16); else if (fg_testmode(15,1)) fg_setmode(15); else { printf("This program requires a 640 x 350 "); printf("EGA graphics mode.\n"); exit(1); } fg_setcolor(1); fg_polygon(x,y,VERTICES); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } The fg_circle routine draws an unfilled circle in screen space, centered at the graphics cursor position, using the current color. The routine's only argument specifies the circle's radius in horizontal screen space units. Another routine, fg_circlew, draws an unfilled circle where the radius is measured in horizontal world space units. Both routines leave the graphics cursor position unchanged. The fg_ellipse routine draws an unfilled ellipse in screen space, centered at the graphics cursor position, using the current color. The routine requires two arguments that respectively specify the length of its horizontal and vertical semi-axes. In other words, the first argument is the absolute distance from the center of the ellipse to its horizontal extremity, and the second argument is the absolute distance from the center of the ellipse to its vertical extremity. Another routine, fg_ellipsew, draws an unfilled ellipse in world space. Both routines leave the graphics cursor position unchanged. Example 6-8 illustrates the use of the fg_circlew and fg_ellipsew routines. The program first uses the fg_automode routine to propose a graphics video mode and then uses the fg_setmode routine to select that video mode. It then makes color 15 the current color, which by default is bright white in all color graphics modes and "on" in the monochrome graphics modes. Next, it establishes a 200-unit by 200-unit world space coordinate system. The program then uses fg_ellipsew to draw an ellipse and fg_circlew to draw a circle, both centered at the middle of the screen (which is the origin of our world space coordinate system). The circle has a radius of 1/16 the width of the screen (12.5 horizontal world space units), and the ellipse is horizontally inscribed within the circle. Chapter 6: Graphics Fundamentals 85 Example 6-9 illustrates the use of the fg_circle and fg_ellipse routines. It is functionally identical to the program of example 6-8, but it uses screen space rather than world space coordinates to draw the circle and ellipse. Note the arguments to the fg_circle and fg_ellipse routines are dependent on the maximum x and y coordinates of the selected video mode. If we didn't compute these arguments in this manner, the actual size of the circle and ellipse would be proportional to the pixel resolution of the video mode. No such dependency exists when using world space, but we pay a price for this feature in slightly slower execution speed. Example 6-8. Example 6-9. #include #include void main(void); void main(void); void main() void main() { { int old_mode; int mid_x, mid_y; int old_mode; old_mode = fg_getmode(); int x,y; fg_setmode(fg_automode()); fg_setcolor(15); old_mode = fg_getmode(); fg_setmode(fg_automode()); fg_initw(); fg_setcolor(15); fg_setworld(-100.0,100.0,-100.0,100.0); mid_x = fg_getmaxx() / 2; fg_movew(0.0,0.0); mid_y = fg_getmaxy() / 2; fg_ellipsew(12.5,12.5); x = mid_x / 8; fg_circlew(12.5); y = mid_y / 8; fg_waitkey(); fg_move(mid_x,mid_y); fg_setmode(old_mode); fg_ellipse(x,y); fg_reset(); fg_circle(x); } fg_waitkey(); fg_setmode(old_mode); fg_reset(); } 86 Fastgraph User's Guide Solid Rectangles Fastgraph includes four routines for drawing solid rectangles, two for screen space and two for world space, with and without clipping. None of these routines affect the graphics cursor position. The fg_rect routine draws a solid rectangle in screen space, without regard to the clipping limits, using the current color. Fg_rect requires four integer arguments that respectively define the minimum x, maximum x, minimum y, and maximum y screen space coordinates of the rectangle. The minimum coordinates must be less than or equal to the maximum coordinates, or else the results are unpredictable. The fg_clprect routine is identical in all respects to the fg_rect routine, except it observes the clipping limits. The world space versions of the solid rectangle drawing routines are fg_rectw and fg_clprectw. Like fg_rect and fg_clprect, they require four arguments that define the extremes of the rectangle, but the arguments are floating point world space coordinates. You also can use the fg_rect routine in text modes. When used in a text mode, fg_rect expects its four arguments to be expressed in character space (that is, rows and columns) rather than screen space. This means the four arguments respectively specify the minimum column, maximum column, minimum row, and maximum row of the rectangle. Fastgraph constructs the rectangle by storing the solid block character (ASCII decimal value 219) in each character cell comprising the rectangle. The rectangle is drawn using the current character attribute, but because the solid block character occupies the entire character cell, the background component of the attribute is essentially meaningless. Example 6-10 demonstrates the use of the fg_rect routine by drawing 200 random-size rectangles in random colors. The program first uses the fg_automode routine to propose a graphics video mode and then uses the fg_setmode routine to select that video mode. Next, it determines the horizontal and vertical screen resolution for the selected video mode, using the fg_getmaxx and fg_getmaxy routines. The main part of the program is a for loop that generates a random rectangle in each iteration. Inside the loop, the C library function rand is used to generate the extremes of the rectangle. If necessary, the program then exchanges the coordinates to make the minimum coordinates less than or equal to the maximum coordinates. Finally, it again uses rand to generate a random color number between 0 and 15, and then draws the rectangle in that color. After drawing all 200 rectangles, the program restores the original video mode and screen attributes before returning to DOS. Chapter 6: Graphics Fundamentals 87 Example 6-10. #include void main(void); #define RECTANGLES 200 #define SWAP(a,b,temp) { temp = a; a = b; b = temp; } void main() { int i; int minx, maxx, miny, maxy; int old_mode; int temp; int xres, yres; old_mode = fg_getmode(); fg_setmode(fg_automode()); xres = fg_getmaxx() + 1; yres = fg_getmaxy() + 1; for (i = 0; i < RECTANGLES; i++) { minx = rand() % xres; maxx = rand() % xres; miny = rand() % yres; maxy = rand() % yres; if (minx > maxx) SWAP(minx,maxx,temp); if (miny > maxy) SWAP(miny,maxy,temp); fg_setcolor(rand()%16); fg_rect(minx,maxx,miny,maxy); } fg_setmode(old_mode); fg_reset(); } Unfilled Rectangles Fastgraph includes a routine for drawing unfilled rectangles. The fg_box routine draws an unfilled rectangle in screen space, with regard to the clipping limits, using the current color. The arguments to fg_box are the same as those for fg_rect. The depth of the rectangle's edges is one pixel by default, but you can change the depth by calling fg_boxdepth. The fg_boxdepth routine expects two arguments. The first argument is the width of the rectangle's left and right sides, while the second is the height of its top and bottom sides. Once you call fg_boxdepth, fg_box draws all unfilled rectangles using the depth values specified in the most recent call to fg_boxdepth. Unlike fg_rect, the fg_box routine has no effect in text video modes. Example 6-11 is the same as example 6-10, but it draws unfilled instead of solid rectangles. The program uses fg_box to draw the each rectangle and fg_boxdepth to define the rectangle depth at three pixels in each direction. 88 Fastgraph User's Guide Note that you don't need to call fg_boxdepth for each rectangle if you want all of them to have the same depth. Example 6-11. #include void main(void); #define RECTANGLES 200 #define SWAP(a,b,temp) { temp = a; a = b; b = temp; } void main() { int i; int minx, maxx, miny, maxy; int old_mode; int temp; int xres, yres; old_mode = fg_getmode(); fg_setmode(fg_automode()); fg_boxdepth(3,3); xres = fg_getmaxx() + 1; yres = fg_getmaxy() + 1; for (i = 0; i < RECTANGLES; i++) { minx = rand() % xres; maxx = rand() % xres; miny = rand() % yres; maxy = rand() % yres; if (minx > maxx) SWAP(minx,maxx,temp); if (miny > maxy) SWAP(miny,maxy,temp); fg_setcolor(rand()%16); fg_box(minx,maxx,miny,maxy); } fg_setmode(old_mode); fg_reset(); } Dithered Rectangles The process of alternating different color pixels across a region of the display area is called dithering. This technique is especially useful in the graphics modes with few colors, such as CGA and Hercules modes, because you can simulate additional colors through effective uses of dithering. Fastgraph includes two routines for drawing dithered rectangles, one for screen space and one for world space. Neither routine observes the clipping limits, nor do they affect the graphics cursor position. The fg_drect routine draws a dithered rectangle in screen space. Like the fg_rect routine, fg_drect requires four integer arguments that respectively define the minimum x, maximum x, minimum y, and maximum y screen Chapter 6: Graphics Fundamentals 89 space coordinates of the rectangle. The minimum coordinates must be less than or equal to the maximum coordinates, or else the results are unpredictable. However, fg_drect also requires a fifth argument that defines the dithering matrix, which in turn determines the pixel pattern used to build the dithered rectangle. The size and format of the dithering matrix are dependent on the video mode. The world space version of the dithered rectangle drawing routine is fg_drectw. Like fg_drect, it requires four arguments that define the extremes of the rectangle, and a fifth argument that defines the dithering matrix. As mentioned earlier, the size and format of the dithering matrix are dependent on the video mode. The dithering matrix is a four byte array in all video modes except the 256 color graphics modes (modes 19 through 23), where it is an eight byte array. This array contains a pixel pattern that fg_drect or fg_drectw replicates across the rectangle's area. The structure of the dithering matrix closely mimics the structure of video memory in each graphics mode. The remainder of this section will present some simple mode-specific examples to illustrate the structure of the dithering matrix in the different graphics modes. Suppose we would like to produce a "checkerboard" of light blue and bright white pixels. That is, in a given row of a rectangle, consecutive pixels will alternate between these two colors. Additionally, the pattern for adjacent rows will be shifted such that there will always be a bright white pixel above and below a light blue pixel, and vice versa. Hence this pixel pattern would look something like B W B W W B W B B W B W W B W B where each B represents a light blue pixel, and each W represents a bright white pixel. The following examples describe the dithering matrix that could be used to produce such a pixel pattern in each graphics mode. CGA Four-Color Graphics Modes The CGA four-color graphics modes (modes 4 and 5) use a four-byte dithering matrix that Fastgraph treats as a four-row by one-column array. Since each pixel in these modes requires two bits of video memory, each byte of the dithering matrix holds four pixels. Thus, the pixel representation of the dithering matrix would appear as shown below on the left; its translation to numeric values appears on the right. [3] B W B W [3] 01 11 01 11 [2] W B W B [2] 11 01 11 01 [1] B W B W [1] 01 11 01 11 [0] W B W B [0] 11 01 11 01 90 Fastgraph User's Guide Because these modes do not offer a light blue color, we've used light cyan (color value 1 in palette 1) to approximate light blue. The B pixels thus translate to color value 1, or 01 binary. Bright white is available as color value 3 in palette 1, so the W pixels translate to color value 3, or 11 binary. The hexadecimal equivalent of the binary value 11011101 (for array elements [0] and [2]) is DD, and the hexadecimal equivalent of the binary value 01110111 (for array elements [1] and [3]) is 77. As shown in example 6-12, these are precisely the values assigned to the elements of the dithering matrix. Example 6-12 uses mode 4 to display a 50-pixel by 50-pixel dithered rectangle in the upper left corner of the screen. The dithering matrix represents the blue and white checkerboard pattern discussed in the preceding paragraph. Example 6-12. #include void main(void); void main() { char matrix[4]; int old_mode; old_mode = fg_getmode(); fg_setmode(4); matrix[0] = matrix[2] = 0xDD; matrix[1] = matrix[3] = 0x77; fg_drect(0,49,0,49,matrix); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } CGA Two-Color Graphics Mode The CGA two-color graphics mode (mode 6) uses a four-byte dithering matrix that Fastgraph treats as a four-row by one-column array, as in the other four-color CGA modes. However, each pixel in this mode only requires one bit of video memory, so each byte of the dithering matrix holds eight pixels. Thus, the pixel representation of the dithering matrix would appear as shown below on the left; its translation to numeric values appears on the right. [3] B W B W B W B W [3] 0 1 0 1 0 1 0 1 [2] W B W B W B W B [2] 1 0 1 0 1 0 1 0 [1] B W B W B W B W [1] 0 1 0 1 0 1 0 1 [0] W B W B W B W B [0] 1 0 1 0 1 0 1 0 Chapter 6: Graphics Fundamentals 91 Mode 6 obviously does not offer a light blue color, so we've used black (color value 0) in its place. The B pixels thus translate to color value 0. Bright white is available as color value 1, so the W pixels translate to color value 1. The hexadecimal equivalent of the binary value 10101010 (for array elements [0] and [2]) is AA, and the hexadecimal equivalent of the binary value 01010101 (for array elements [1] and [3]) is 55. Thus, to make example 6-12 run in mode 6, we only need to change the fg_setmode argument from 4 to 6 and change the dithering matrix values as shown below. matrix[0] = matrix[2] = 0xAA; matrix[1] = matrix[3] = 0x55; Tandy/PCjr 16-Color Graphics Mode The Tandy/PCjr 16-color graphics mode (mode 9) also uses a four-byte dithering matrix that Fastgraph treats as a four-row by one-column array. Each pixel in this mode requires four bits of video memory, so each byte of the dithering matrix only holds two pixels. Thus, the pixel representation of the dithering matrix would appear as shown below on the left; its translation to numeric values appears on the right. [3] B W [3] 1001 1111 [2] W B [2] 1111 1001 [1] B W [1] 1001 1111 [0] W B [0] 1111 1001 The B pixels translate to color value 9 (light blue), or 1001 binary, and the W pixels translate to color value 15 (bright white), or 1111 binary. The hexadecimal equivalent of the binary value 11111001 (for array elements [0] and [2]) is F9, and the hexadecimal equivalent of the binary value 10011111 (for array elements [1] and [3]) is 9F. Thus, to make example 6-12 run in mode 9, we only need to change the fg_setmode argument from 4 to 9 and change the dithering matrix values as shown below. matrix[0] = matrix[2] = 0xF9; matrix[1] = matrix[3] = 0x9F; Hercules Graphics Mode The size and format of the dithering matrix in the Hercules graphics mode (mode 11) are the same as in the CGA two-color mode (mode 6). Please refer to page 90 for a discussion of mode 6 dithering. Hercules Low-Resolution Graphics Mode The size and format of the dithering matrix in the Hercules low- resolution graphics mode (mode 12) are the same as in the CGA four-color modes (modes 4 and 5). As far as our checkerboard example goes, we'll use black (color value 0) in place of light blue, and bold (color value 3) 92 Fastgraph User's Guide instead of bright white. Thus, the B pixels translate to 00 binary, while the W pixels translate to 11 binary. The hexadecimal equivalent of the binary value 11001100 (for array elements [0] and [2]) is CC, and the hexadecimal equivalent of the binary value 00110011 (for array elements [1] and [3]) is 33. Thus, to make example 6-12 run in mode 12, we only need to change the fg_setmode argument from 4 to 12 and change the dithering matrix values as shown below. matrix[0] = matrix[2] = 0xCC; matrix[1] = matrix[3] = 0x33; EGA and VGA Graphics Modes The native EGA and VGA graphics modes (modes 13 through 18) use a four- byte dithering matrix that Fastgraph treats as a four-row by one-column array. Unlike the other graphics modes, which allow you to store pixels of several colors in the dithering matrix, the EGA and VGA modes treat the dithering matrix as a bit map for a specific color. Since each color in the dither pattern must be stored in a separate bit map (that is, in a separate dithering matrix), you must call fg_drect once for each color. Furthermore, you must use the fg_setcolor routine before each call to fg_drect to define the color used with the dithering matrix. In all EGA and VGA graphics modes, each byte of the dithering matrix is a bit map that represents eight pixels. Using our familiar checkerboard example, the pixel representation of the dithering matrix would appear as shown below. [3] B W B W B W B W [2] W B W B W B W B [1] B W B W B W B W [0] W B W B W B W B Translating this pattern to numeric values is simple. Just construct one dithering matrix for each color in the pattern (there are two colors in this example), where pixels of the current color translate to 1, and other pixels translate to 0. Following our example, the translation for the B pixels appears below on the left, while the translation for the W pixels appears on the right. [3] 1 0 1 0 1 0 1 0 [3] 0 1 0 1 0 1 0 1 [2] 0 1 0 1 0 1 0 1 [2] 1 0 1 0 1 0 1 0 [1] 1 0 1 0 1 0 1 0 [1] 0 1 0 1 0 1 0 1 [0] 0 1 0 1 0 1 0 1 [0] 1 0 1 0 1 0 1 0 Chapter 6: Graphics Fundamentals 93 The hexadecimal equivalent of the binary value 01010101 is 55, and the hexadecimal equivalent of the binary value 10101010 is AA. As shown in example 6-13, these are precisely the values assigned to the elements of the dithering matrices. Example 6-13 uses mode 13 to display our light blue and bright white checkerboard pattern. Note you must call fg_drect twice -- once for the light blue pixels (color value 9), and again for the bright white pixels (color value 15). Note also how fg_setcolor is used before each call to fg_drect to define the color of the pixels fg_drect will display. Example 6-13. #include void main(void); void main() { char matrix[4]; int old_mode; old_mode = fg_getmode(); fg_setmode(13); matrix[0] = matrix[2] = 0x55; matrix[1] = matrix[3] = 0xAA; fg_setcolor(9); fg_drect(0,49,0,49,matrix); matrix[0] = matrix[2] = 0xAA; matrix[1] = matrix[3] = 0x55; fg_setcolor(15); fg_drect(0,49,0,49,matrix); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } MCGA and VGA 256-Color Graphics Modes The MCGA and VGA 256-color graphics modes (modes 19 through 23) use an eight-byte dithering matrix that Fastgraph treats as a four-row by two-column array. Each pixel in these modes requires eight bits of video memory, so each byte of the dithering matrix only holds a single pixel. We therefore need the two column dithering matrix to produce any type of dither pattern. The pixel representation of the dithering matrix would appear as shown below on the left; its translation to numeric values appears on the right. [6] B W [7] [6] 9 15 [7] [4] W B [5] [4] 15 9 [5] [2] B W [3] [2] 9 15 [3] [0] W B [1] [0] 15 9 [1] 94 Fastgraph User's Guide The B pixels translate to color value 9 (light blue), and the W pixels translate to color value 15 (bright white). Example 6-14 uses mode 19 to draw our light blue and bright white checkerboard pattern. Example 6-14. #include void main(void); void main() { char matrix[8]; int old_mode; old_mode = fg_getmode(); fg_setmode(19); matrix[0] = matrix[3] = matrix[4] = matrix[7] = 15; matrix[1] = matrix[2] = matrix[5] = matrix[6] = 9; fg_drect(0,49,0,49,matrix); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Closing Remarks There are two other important items pertaining to the fg_drect and fg_drectw routines. These items apply regardless of which graphics video mode is being used. First, the dithering matrix may not contain virtual color values. That is, the pixel color values stored in the dithering matrix must be between 0 and the maximum color value for the current video mode. If any color value is redefined using the fg_defcolor routine, Fastgraph always ignores the redefinition and instead uses the actual color value. Note this does not apply to palette registers or video DAC registers, because in these cases we are redefining the color associated with a color value and not the color value itself. Second, Fastgraph aligns the dithering matrix to specific pixel rows. Fastgraph draws the dithered rectangle starting with the pixel row specified by the rectangle's lower limit (the maximum y coordinate for fg_drect, or the minimum y coordinate for fg_drectw) and proceeds upward until reaching the rectangle's upper limit. In all cases the dithering matrix used by fg_drect and fg_drectw contains four rows. If we let r represent the pixel row corresponding to the rectangle's lower limit, then the first row used in the dithering matrix is r modulo 4 (assuming the dithering matrix rows are numbered 0 to 3). This alignment enables you to use the same dithering matrix in multiple calls to fg_drect and fg_drectw for building an object of adjacent dithered rectangles (for example, an L-shaped area) and still have the dither pattern match where the rectangles intersect. Chapter 6: Graphics Fundamentals 95 Region Fill Fastgraph includes routines for filling arbitrary regions. The fg_paint routine fills a region with the current color value by specifying a screen space point in the region's interior. The fg_paintw routine also fills a region, but it requires the interior point to be expressed in world space. Neither routine changes the graphics cursor position. Each of these routines has two arguments that specify the (x,y) coordinates of the interior point. For the fg_paint routine, the arguments are integer quantities. For the fg_paintw routine, they are floating point quantities. The region being filled must be a closed polygon whose boundary color is different from that of the specified interior point. The region may contain holes (interior areas that will not be filled). Fastgraph fills the region by changing every interior pixel whose color is the same as the specified interior point, to the current color. If the interior point is already the current color, the region fill routines do nothing. It is important to note the screen edges are not considered polygon boundaries, and filling an open polygon will cause the fg_paint and fg_paintw routines to behave unpredictably. Example 6-15 illustrates a simple use of the fg_paint routine in a 320 by 200 graphics mode. The program uses fg_bestmode to select an available video mode (if no 320 by 200 graphics mode is available, the program exits). After establishing the selected video mode, the program uses the fg_move and fg_drawrel routines to draw a hollow rectangle in color 10 and a hollow diamond in color 9. The diamond is drawn in the middle of the rectangle, thus making it a hole with respect to the rectangle. The program leaves these shapes on the screen until a key is pressed. At that time, it calls the fg_paint routine to fill that part of the rectangle outside the diamond with color 10. After waiting for another keystroke, the program again uses fg_paint to fill the interior of the diamond with color 15. Finally, the program waits for another keystroke, restores the original video mode and screen attributes, and returns to DOS. Example 6-15. #include #include #include void main(void); void main() { int old_mode, new_mode; new_mode = fg_bestmode(320,200,1); if (new_mode < 0) { printf("This program requires a 320 x 200 "); printf("graphics mode.\n"); exit(1); } old_mode = fg_getmode(); 96 Fastgraph User's Guide fg_setmode(new_mode); fg_setcolor(10); fg_move(100,50); fg_drawrel(120,0); fg_drawrel(0,100); fg_drawrel(-120,0); fg_drawrel(0,-100); fg_setcolor(9); fg_move(160,80); fg_drawrel(30,20); fg_drawrel(-30,20); fg_drawrel(-30,-20); fg_drawrel(30,-20); fg_waitkey(); fg_setcolor(10); fg_paint(160,70); fg_waitkey(); fg_setcolor(15); fg_paint(160,100); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Summary of Fundamental Graphics Routines This section summarizes the functional descriptions of the Fastgraph routines presented in this chapter. More detailed information about these routines, including their arguments and return values, may be found in the Fastgraph Reference Manual. FG_BOX draws an unfilled rectangle in screen space, with respect to the clipping region. The width of the rectangle's edges is one pixel unless changed with the fg_boxdepth routine. FG_BOXDEPTH defines the depth of rectangles drawn with the fg_box routine. The fg_setmode routine initializes the box depth to one pixel. FG_CIRCLE draws an unfilled circle in screen space. The circle is centered at the graphics cursor position. FG_CIRCLEW draws an unfilled circle in world space. The circle is centered at the graphics cursor position. FG_CLPRECT draws a solid (filled) rectangle in screen space, with respect to the clipping region. FG_CLPRECTW draws a solid (filled) rectangle in world space, with respect to the clipping region. Chapter 6: Graphics Fundamentals 97 FG_DASH draws a dashed line from the graphics cursor position to an absolute screen space position. It also makes the destination position the new graphics cursor position. FG_DASHREL draws a dashed line from the graphics cursor position to a screen space position relative to it. It also makes the destination position the new graphics cursor position. FG_DASHRW draws a dashed line from the graphics cursor position to a world space position relative to it. It also makes the destination position the new graphics cursor position. FG_DASHW draws a dashed line from the graphics cursor position to an absolute world space position. It also makes the destination position the new graphics cursor position. FG_DRAW draws a solid line from the graphics cursor position to an absolute screen space position. It also makes the destination position the new graphics cursor position. FG_DRAWREL draws a solid line from the graphics cursor position to a screen space position relative to it. It also makes the destination position the new graphics cursor position. FG_DRAWRW draws a solid line from the graphics cursor position to a world space position relative to it. It also makes the destination position the new graphics cursor position. FG_DRAWW draws a solid line from the graphics cursor position to an absolute world space position. It also makes the destination position the new graphics cursor position. FG_DRECT draws a dithered rectangle in screen space, without regard to the clipping region. The rectangle's dither pattern is defined through a dithering matrix whose format is dependent on the video mode being used. FG_DRECTW draws a dithered rectangle in world space, without regard to the clipping region. The rectangle's dither pattern is defined through a dithering matrix whose format is dependent on the video mode being used. FG_ELLIPSE draws an unfilled ellipse in screen space. The ellipse is centered at the graphics cursor position, and its size is determined by the specified lengths of the semi-axes. FG_ELLIPSEW draws an unfilled ellipse in world space. The ellipse is centered at the graphics cursor position, and its size is determined by the specified lengths of the semi-axes. FG_ERASE clears the screen in either text or graphics modes. FG_GETPIXEL returns the color value of a specified pixel. FG_GETXPOS returns the screen space x coordinate of the graphics cursor position. FG_GETYPOS returns the screen space y coordinate of the graphics cursor position. 98 Fastgraph User's Guide FG_MOVE establishes the graphics cursor position at an absolute screen space point. FG_MOVEREL establishes the graphics cursor position at a screen space point relative to the current position. FG_MOVERW establishes the graphics cursor position at a world space point relative to the current position. FG_MOVEW establishes the graphics cursor position at an absolute world space point. FG_PAINT fills an arbitrary closed region with the current color value. The region is defined by specifying a screen space point within its interior. FG_PAINTW fills an arbitrary closed region with the current color value. The region is defined by specifying a world space point within its interior. FG_POINT draws a point (that is, displays a pixel) in screen space. FG_POINTW draws a point in world space. FG_POLYGON draws an unfilled polygon in screen space, using two coordinate arrays to define the polygon vertices. The drawing of the polygon begins at the graphics cursor position, through the vertices defined by the coordinate arrays, and finally back to the original cursor position if necessary. FG_POLYGONW draws an unfilled polygon in world space. It is the same as the fg_polygon routine, except the coordinate arrays contain world space values. FG_RECT draws a solid (filled) rectangle in screen space or character space, without regard to the clipping region. FG_RECTW draws a solid (filled) rectangle in world space, without regard to the clipping region. FG_SETCLIP defines the clipping region in screen space. The clipping region is a rectangular area outside of which graphics are suppressed. FG_SETCLIPW defines the clipping region in world space. Chapter 7 Character Display Routines 100 Fastgraph User's Guide Overview An important part of any program is the capability to display text or other characters on the screen. Fastgraph supports two character sets: the hardware or BIOS character set available with each video mode, and Fastgraph's own software character set for graphics video modes. Fastgraph/Light does not support the software character set. We'll begin this chapter with a review of character space, and then discuss the specifics about hardware and software characters. At the end of the chapter, we'll briefly explain how to implement bit-mapped characters into a program. To simplify things, the example programs presented in this chapter are mode-specific examples, and no testing is done to check if the video mode is available on the user's system. Character Space The coordinate system used for displaying hardware characters is called character space. It is the only coordinate system available in text video modes, but it is a supplementary coordinate system you can use with either screen space or world space in graphics video modes. Character space can be thought of as a grid of rows and columns, with each cell in the grid holding one character. Each cell is identified by its unique (row,column) integer coordinates. The rows and columns are numbered starting at zero; the origin is always the upper left corner of the screen. For example, in the 80-column by 25-row video modes, the (row,column) coordinates of the screen corners are shown in the following diagram. (0,0) (0,79) (24,0) (24,79) The number of rows and columns depends on the video mode, as shown in the following table. For graphics modes, the table also includes the width and height in pixels of a character cell. Mode No. of No. of Char. Char. Number Columns Rows Width Height 4 40 25 8 8 5 40 25 8 8 6 80 25 8 8 9 40 25 8 8 11 80 25 9 14 12 40 25 8 8 13 40 25 8 8 14 80 25 8 8 15 80 25 8 14 16 80 25 8 14 17 80 30 8 16 18 80 30 8 16 19 40 25 8 8 20 40 25 8 8 21 40 50 8 8 22 40 30 8 8 23 40 60 8 8 Chapter 7: Character Display Routines 101 Hardware Characters Hardware characters are available in all of Fastgraph's supported video modes. As explained in Chapter 5, text mode characters have a display attribute that defines their foreground color, their background color, and whether or not they blink. Graphics mode characters appear in a single color, as determined by the current color index. Chapter 5 also explained how Fastgraph's fg_setattr and fg_setcolor routines define the attribute or color index in which subsequent hardware characters appear. It is obviously important to define the color or attribute for hardware characters, but it is equally important to define their location on the screen. Fastgraph draws hardware characters at the position defined by the text cursor. Like the graphics cursor, the text cursor is not a cursor in the true sense, but is simply a pair of character space (row,column) coordinates with a special meaning. The fg_setmode routine sets the text cursor position to the character space coordinates (0,0), which of course is the upper left corner of the screen.(2) The Fastgraph routine fg_locate changes the text cursor position. It has two integer arguments that specify the (row,column) character space coordinates of the new position. The row values must be between 0 and one less than the number of character rows available. The column values must be between 0 and one less than the number of character columns available. The fg_text routine is Fastgraph's basic character display routine. It displays a string of hardware characters, starting at the text cursor position, using the current color attribute (for text modes) or color index (for graphics modes). If the string reaches the last column in a row, fg_text will wrap the string to the first column of the next row. Additionally, fg_text leaves the cursor one column to the right of the last character displayed (or the first column of the next row if the last character appears at the end of a row). This feature makes it possible for successive calls to fg_text to display adjacent strings. The first argument for the fg_text routine is a character string of arbitrary length, and the second argument is an integer value that specifies the number of characters to display from that string. ____________________ (2) In reality there are eight text cursors, one for each video page. The fg_setmode routine initializes each text cursor position to (0,0). The next chapter describes this in more detail. 102 Fastgraph User's Guide Example 7-1 illustrates the use of the fg_locate and fg_text routines in the 80 by 25 color text mode (mode 3). After establishing the video mode and making the BIOS cursor invisible, the program displays four strings with different attributes. The attributes are selected using the fg_setattr routine, and the strings are displayed by the fg_text routine. The first string appears in yellow (attributes 14,0,0) in the upper left corner of the screen; the fg_locate routine is not necessary because (0,0) is the default text cursor position established by fg_setmode. The second string appears in light green (10,0,0) one space to the right of the first string. Its position relies on the fact fg_text sets the new text cursor position one space to the right of the last character displayed (following the "w" of "yellow" in this case). The leading space in " green" leaves a space between the first and second strings. Similarly, the third string appears in blinking light red (12,0,1) one space to the right of the second string. The program then uses the fg_locate routine to move the text cursor to the lower left corner of the screen and displays the "Press any key" string. This string is displayed with a light red foreground against a gray background (12,7,0). The extra spaces surrounding the string extend the background color one character position to the left and right and make the string more visually appealing. Finally, once you press any key, the program restores the original video mode and screen attributes before returning to DOS. Example 7-1. #include void main(void); void main() { int old_mode; old_mode = fg_getmode(); fg_setmode(3); fg_cursor(0); fg_setattr(14,0,0); fg_text("yellow",6); fg_setattr(10,0,0); fg_text(" green",6); fg_setattr(12,0,1); fg_text(" blinking",9); fg_setattr(12,7,0); fg_locate(24,0); fg_text(" Press any key. ",16); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } The fg_where routine retrieves the text cursor position in its two integer arguments. This routine is not used as frequently as the fg_locate Chapter 7: Character Display Routines 103 and fg_text routines because more often than not your program will know the text cursor position implicitly, or you'll know in advance the locations at which text will be displayed. The fg_where routine takes two integer arguments passed as pointers (that is, by reference), and these two arguments respectively receive the text cursor's current row and column position. Example 7-2 produces the same results as example 7-1, but it does so a bit differently. It uses its own routine, put_string, to display a string at a specified row and column. The put_string routine simply calls fg_locate to establish the text cursor position and then calls fg_text to display the string. Note the use of the C library function strlen to determine the string length passed to the fg_text routine. Example 7-2 also uses the fg_where routine to retrieve the new text cursor positions, which are then passed to the put_string routine. Example 7-2. #include #include void main(void); void put_string(char*,int,int); void main() { int old_mode; int row, column; old_mode = fg_getmode(); fg_setmode(3); fg_cursor(0); fg_setattr(14,0,0); put_string("yellow",0,0); fg_setattr(10,0,0); fg_where(&row,&column); put_string("green",row,column+1); fg_setattr(12,0,1); fg_where(&row,&column); put_string("blinking",row,column+1); fg_setattr(12,7,0); put_string(" Press any key. ",24,0); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } void put_string(string,row,column) char *string; int row, column; { fg_locate(row,column); fg_text(string,strlen(string)); } 104 Fastgraph User's Guide Sometimes you may wish to change the display attribute of existing text, such as when creating a shadow around the edges of a pop-up window. The Fastgraph routine fg_chgattr performs this function. It applies the current text display attribute (as defined in the most recent call to fg_setattr or fg_setcolor) to a given number of characters, starting at the text cursor position. It leaves the text cursor one column to the right of the last character changed (or the first column of the next row if the last character is at the end of a row). The fg_chgattr routine's argument specifies the number of characters to change. This routine has no effect in graphics video modes. The Fastgraph routine fg_chgtext performs somewhat the opposite function of fg_chgattr. It displays new text but uses the display attributes already assigned to the character cells where the text will appear. The fg_chgtext routine takes the same two arguments as the fg_text routine, displays the characters starting at the text cursor position, and leaves the cursor one column to the right of the last character displayed. Like fg_chgattr, fg_chgtext has no effect in graphics video modes. Example 7-3 illustrates the fg_chgattr and fg_chgtext routines. It runs in the 80-column color text mode (mode 3), but if we change the fg_setmode argument it also would run in the monochrome text mode (mode 7). The program first displays the word "hello" in the upper left corner of the screen, using a gray foreground and black background attribute. After waiting for a keystroke, the program calls fg_chgattr to make the word "hello" appear in reverse video (that is, a black foreground and gray background attribute). After a second keystroke, the program uses fg_chgtext to change the "h" of "hello" to upper case. Following this, the program returns to DOS. Example 7-3. #include void main(void); void main() { int old_mode; old_mode = fg_getmode(); fg_setmode(3); fg_cursor(0); fg_setattr(7,0,0); fg_text("hello",5); fg_waitkey(); fg_locate(0,0); fg_setattr(0,7,0); fg_chgattr(5); fg_waitkey(); fg_locate(0,0); fg_chgtext("H",1); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Chapter 7: Character Display Routines 105 You also can retrieve the character or attribute stored in a specific character cell. The Fastgraph routine fg_getchar retrieves character values, while fg_getattr retrieves character attributes. Both routines have two integer arguments that specify the (row,column) coordinates for the character cell of interest. Example 7-4 uses fg_getchar and fg_getattr to obtain the character and attribute stored at row 24, column 0. Just before the program exits, it displays these values. Example 7-4. #include #include void main(void); void main() { int attr, value; int old_mode; old_mode = fg_getmode(); fg_setmode(3); fg_cursor(0); fg_setattr(9,7,0); fg_locate(24,0); fg_text("Test",4); value = fg_getchar(24,0); attr = fg_getattr(24,0); fg_waitkey(); fg_setmode(old_mode); fg_reset(); printf("%c %2.2X\n",value,attr); } If you need to retrieve characters and attributes from a rectangular area, it's more efficient to use the fg_getimage routine (described in Chapter 9) than to call fg_getchar and fg_getattr repeatedly. Displaying hardware characters in graphics video modes is quite different from doing so in text modes, although we use the same Fastgraph routines in both cases. Example 7-5 is similar to example 7-1, but it runs in the EGA enhanced graphics mode (mode 16) instead of a text mode. In graphics modes, the fg_cursor routine has no effect, so we have omitted it from the program. Furthermore, characters cannot be displayed with a blinking attribute, so we have omitted the blinking characters (we could simulate blinking by repetitively displaying and erasing them, but that is beyond the scope of this example). Because graphics mode characters only have a foreground color, we had to simulate the gray background of the "Press any key" string by first drawing a rectangle where that string appears. The differences between examples 7-5 and 7-1 hold for any graphics video mode, not just mode 16. 106 Fastgraph User's Guide Example 7-5. #include void main(void); void main() { int old_mode; old_mode = fg_getmode(); fg_setmode(16); fg_setcolor(14); fg_text("yellow",6); fg_setcolor(10); fg_text(" green",6); fg_setcolor(7); fg_rect(0,127,336,349); fg_setcolor(12); fg_locate(24,0); fg_text(" Press any key. ",16); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Example 7-6 demonstrates a side effect that occurs when displaying characters in graphics modes. This example uses the MCGA graphics mode (mode 19) and displays two character strings at the same location. If we were to do this in a text mode, the first string would disappear once we displayed the second string. In graphics modes, however, the portions of the first string not covered by characters from the second string are still visible. The reason for this may not be clear at first, but remember when we display characters in graphics modes, we aren't really displaying characters but merely a pixel representation of the characters. Fastgraph has no way to distinguish such pixels from any other pixels. Example 7-6. #include void main(void); void main() { int old_mode; old_mode = fg_getmode(); fg_setmode(19); fg_setcolor(14); fg_text("yellow",6); fg_locate(0,0); fg_setcolor(10); Chapter 7: Character Display Routines 107 fg_text(" green",6); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } To avoid this problem, the recommended procedure for displaying characters in graphics modes is to first erase the area where the text will appear. The easiest way to do this is to use the fg_rect routine to draw a rectangle in the background color. In example 7-6, we could do this by inserting the statements fg_setcolor(0); fg_rect(0,47,0,7); immediately before the call to fg_locate. The parameters passed to the fg_rect routine represent the 48 by 8 pixel region that corresponds to the first six character cells of row 0 in the 320 by 200 graphics modes. Conversion Routines We have already mentioned Fastgraph includes routines for converting coordinates between character space and screen space (see page 44). In this section, we will review these routines and then present an example that uses some of them. The fg_xalpha and fg_yalpha routines convert screen space coordinates to character space. The fg_xalpha routine converts a screen space x coordinate to the character space column that contains the coordinate. Similarly, the fg_yalpha routine converts a screen space y coordinate to the character space row that contains the coordinate. The fg_xconvert and fg_yconvert routines convert character space coordinates to screen space. The fg_xconvert routine converts a character space column to the screen space coordinate of its leftmost pixel. Similarly, the fg_yconvert routine converts a character space row to the screen space coordinate of its top (lowest-numbered) pixel. On page 105, example 7-5 demonstrated how to display characters in a graphics mode. Because characters do not have a background color in graphics modes, example 7-5 used the fg_rect routine to simulate a background color by drawing a gray rectangle before displaying the text. It was necessary to determine the screen coordinates of the character cells so we could pass the correct parameters to fg_rect. By using the fg_xconvert and fg_yconvert routines, we can let Fastgraph calculate the required screen coordinates. This method has the additional benefit of working in any graphics mode, whereas the coordinates passed to fg_rect in example 7-5 would only work properly in a 640 by 350 graphics mode. Example 7-7 shows how we could extend example 7-5 to use the fg_xconvert and fg_yconvert routines. Example 7-7. #include void main(void); 108 Fastgraph User's Guide void main() { int old_mode; int minx, maxx, miny, maxy; fg_old_mode = fg_getmode(); fg_setmode(16); fg_setcolor(14); fg_text("yellow",6); fg_setcolor(10); fg_text(" green",6); fg_setcolor(7); minx = fg_xconvert(0); maxx = fg_xconvert(16) - 1; miny = fg_yconvert(24); maxy = fg_yconvert(25) - 1; fg_rect(minx,maxx,miny,maxy); fg_setcolor(12); fg_locate(24,0); fg_text(" Press any key. ",16); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Software Characters Software characters, also called stroke characters or vector characters in other literature, are only are available in graphics video modes. Unlike the fixed-size hardware characters, you can display software characters in any size, at any angle, and at any position. In addition, software characters are proportionally spaced. However, software characters take longer to draw than do hardware characters. Fastgraph includes two software character fonts, called the primary font and the alternate font. The primary font contains upper and lower case letters, numbers, punctuation, and most of the other printable ASCII characters. The alternate font contains upper and lower case Greek letters and other mathematical and scientific symbols. The Fastgraph routine fg_swchar displays a string of software characters in the current color index (as defined by the most recent call to fg_setcolor). The string may contain any characters from the primary font, the alternate font, or both. You can display the characters left justified, centered, or right justified relative to the graphics cursor position. Just as the fg_text routine updates the text cursor position, fg_swchar sets the graphics cursor position just to the right of the last character drawn. The characters are clipped according to the current clipping region. In addition to the characters, the string passed to fg_swchar also may contain operators for switching fonts, underlining, subscripting, or superscripting characters. Because fg_swchar internally uses world space coordinates, you must call the fg_initw routine at some point in your program before the first call to Chapter 7: Character Display Routines 109 fg_swchar. You also must establish a world space coordinate system with the fg_setworld routine. The fg_swchar routine has three arguments. The first argument is the character string to display. The second argument is an integer value that specifies the number of characters in the string, including any characters used as special operators. The third argument is an integer value that determines the position of the string relative to the graphics cursor position. If this value is negative, the lower left corner of the first character will be at the graphics cursor position. If it is positive, the lower right corner of the last character will be at the graphics cursor position. If it is zero, the string will be horizontally centered at the graphics cursor position. The size of software characters is determined by the values passed to the fg_setsize, fg_setsizew, and fg_setratio routines. The fg_setsize routine has a single integer argument that defines the height of software characters in screen space units, while the fg_setsizew routine has a single floating point argument that defines the height in world space units. If neither of these routines is called, Fastgraph will use its default character height of one world space unit. The fg_setratio routine has a single floating point argument that defines the aspect ratio for software characters. The aspect ratio is the ratio of character width to character height. For example, an aspect ratio of 2.0 means characters are twice as wide as they are high. If the fg_setratio routine is not called, Fastgraph uses its default aspect ratio of 1. Example 7-8 displays both of the software character fonts. The program uses the enhanced EGA graphics mode (mode 16), but it could run in any graphics mode by changing the fg_setmode argument. After establishing the video mode, the program calls the fg_initw routine to initialize Fastgraph's world space parameters; this is required since the software character drawing routines internally use world space coordinates. The next statement is a call to fg_setworld that establishes a world space coordinate system with 0.01 world space units per pixel. Following this is a call to fg_setsizew that defines the character height as 0.21 world space units, or 21 pixels. Note we could have instead used the fg_setsize routine here with an integer argument of 21. The next part of the program draws the characters in the primary font on the upper half of the screen. After doing this, the program draws the alternate font characters on the lower half. In each case it does this with the fg_swchar routine. By default, the string passed to fg_swchar will produce characters from the primary font. However, you can insert a back slash character (\) in the string to toggle between the two fonts. Don't forget the C language applies a special meaning to the back slash character within strings, so you must use two consecutive back slashes to insert a single back slash in the string. Example 7-8. #include void main(void); void main() { 110 Fastgraph User's Guide int old_mode; old_mode = fg_getmode(); fg_setmode(16); fg_initw(); fg_setworld(0.0,6.39,0.0,3.49); fg_setsizew(0.21); fg_setcolor(15); fg_locate(0,26); fg_text("Software characters - font 1",28); fg_setcolor(10); fg_movew(0.0,3.1); fg_swchar("ABCDEFGHIJKLMNOPQRSTUVWXYZ",26,-1); fg_movew(0.0,2.8); fg_swchar("abcdefghijklmnopqrstuvwxyz",26,-1); fg_movew(0.0,2.5); fg_swchar("0123456789",10,-1); fg_movew(0.0,2.2); fg_swchar("!\"#$%&'()*+,-./:;<=>?[]^`{|}~",29,-1); fg_setcolor(15); fg_locate(12,26); fg_text("Software characters - font 2",28); fg_setcolor(10); fg_movew(0.0,1.4); fg_swchar("\\ABCDEFGHIJKLMNOPRSTUWXYZ",25,-1); fg_movew(0.0,1.1); fg_swchar("\\abcdefghijklmnoprstuwxyz",25,-1); fg_movew(0.0,0.4); fg_swchar("\\012345678#$%&()*+/<=>?[]{}",27,-1); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Example 7-8 displays all characters in each font. If you compare the primary font strings with the alternate font strings, you'll see the alternate font contains fewer characters. For example, the letters Q and V (either upper or lower case) have no corresponding character in the alternate font. You might have also noticed the primary font does not support the full printable ASCII character set. Any character in a string passed to the fg_swchar routine that does not have a corresponding character in the current font will display a blank character. In addition to the font change operator (the back slash character), fg_swchar recognizes three other operators. The superscript operator is a back slash followed by a caret (\^). It causes the next character to appear as a superscript. Similarly, the subscript operator is a back slash followed by a lower case v (\v); it causes the next character to appear as a subscript. The size of superscripted and subscripted characters is one half the height of the other characters. The underline operator is the underscore character (_). It causes all subsequent characters in the string to be underlined until another underscore character is found, or until the end of the string. When using these operators, be sure to include them as part of the string length count passed to fg_swchar. Chapter 7: Character Display Routines 111 Example 7-9 illustrates the use of the font selection, superscript, subscript, and underline operators with the fg_swchar routine. Again, because the back slash character has a special meaning to the C programming language, we must use two consecutive back slashes to represent a single back slash within the string. The program displays four strings: cos2o + sin2o = 1 H2O U232 One word is underlined. The theta symbol (o) in the first string is produced by displaying the character "h" in the alternate font. Note another font selection operator (\) appears immediately after the "h" to revert to the primary font. The first string also includes superscript operators (\^) to display the exponents in the equation. The second string includes a single subscripted character, while the third string shows how to display three consecutive subscripted characters. Finally, the fourth string illustrates how to underline characters. Note example 7-9 also uses the fg_setratio routine. The first three strings are drawn with an aspect ratio of 2, making them twice as wide as they are high. The fourth string is drawn with an aspect ratio of 1 (Fastgraph's default aspect ratio for software characters), so the character height is the same as the character width. Also, the strings are centered instead of left justified as in the previous example. Example 7-9. #include void main(void); void main() { int old_mode; old_mode = fg_getmode(); fg_setmode(16); fg_setcolor(10); fg_initw(); fg_setworld(0.0,6.39,0.0,3.49); fg_setratio(2.0); fg_setsizew(0.21); fg_movew(3.2,3.0); fg_swchar("cos\\^2\\h\\ + sin\\^2\\h\\ = 1",25,0); fg_movew(3.2,2.0); fg_swchar("H\\v2O U\\v2\\v3\\v2",18,0); fg_movew(3.2,1.0); fg_setratio(1.0); fg_swchar("One _word_ is underlined.",25,0); fg_waitkey(); 112 Fastgraph User's Guide fg_setmode(old_mode); fg_reset(); } The fg_setangle routine defines the angle or orientation at which software characters are displayed. Its only argument is a floating point value that specifies the angle, measured in degrees counterclockwise from the positive x axis. If a program draws software characters before calling fg_setangle, Fastgraph will use its default angle of zero degrees (that is, the characters will be oriented horizontally). In most programs, the alternate font is not needed. However, if you use the fg_swchar routine, Fastgraph will include the definitions of these characters in your program's data segment. To prevent wasting this space, Fastgraph includes the fg_swtext routine. The fg_swtext routine is same as the fg_swchar routine, except it does not include the alternate font. Since the font selection operator does not apply when using fg_swtext, the routine simply ignores it. You should only use fg_swtext if do not use fg_swchar. If you use both routines, your program will still work correctly, but its data segment will contain an extra copy of the primary font definitions. Example 7-10 demonstrates the use of the fg_setangle and fg_swtext routines. The program draws a series of strings of the form "nnn degrees", where nnn is a multiple of 15, radiating from the screen center. Each string appears at the specified angle. For example, the string "15 degrees" is drawn at an angle of 15 degrees. Example 7-10. #include void main(void); void main() { char string[24]; int angle; int old_mode; old_mode = fg_getmode(); fg_setmode(16); fg_setcolor(10); fg_initw(); fg_setworld(0.0,6.39,0.0,3.49); fg_setsizew(0.21); for (angle = 0; angle < 360; angle += 15) { fg_movew(3.2,1.75); fg_setangle((double)angle); sprintf(string," %3d degrees",angle); fg_swtext(string,16,-1); } fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Chapter 7: Character Display Routines 113 The final routine pertaining to software characters is fg_swlength, which returns the length of a specified string of software characters in world space units. The length is returned as the routine's floating point function value. The fg_swlength routine has two arguments -- a string of software characters, and an integer value specifying the number of characters in the string. As with fg_swchar and fg_swtext, the count includes any of the special operator characters. Example 7-11 demonstrates a typical use of the fg_swlength routine. The program displays the string "hello there." in light green against a gray background in the middle of the screen. As in our previous software character examples, the program uses mode 16 and first performs the necessary initializations to use software characters. Following this, the program uses the fg_swlength routine to compute the length in world space units of the string. Note we have added blank characters to each end of the string passed to fg_swlength; this increases the length of the actual string and will effectively give the gray rectangle an extended border on its left and right sides. The string length returned by fg_swlength is multiplied by 0.5, giving the distance from the middle of the screen to either side of the rectangle. The program then uses this value to compute the minimum and maximum x coordinates passed to fg_rectw. After drawing the gray rectangle, the program uses fg_swtext to draw the string of software characters in the middle of the screen. It then waits for a keystroke before restoring the original video mode and screen attributes and returning to DOS. Example 7-11. #include void main(void); void main() { int old_mode; double half; double fg_swlength(); old_mode = fg_getmode(); fg_setmode(16); fg_initw(); fg_setworld(0.0,6.39,0.0,3.49); fg_setsizew(0.21); fg_setcolor(7); half = fg_swlength(" Hello there. ",14) * 0.5; fg_rectw(3.2-half,3.2+half,1.6,1.9); fg_setcolor(10); fg_movew(3.2,1.65); fg_swtext("Hello there.",12,0); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } 114 Fastgraph User's Guide Bit-Mapped Characters Bit-mapped characters combine the properties of hardware and software characters. They are a fixed size, as hardware characters are, but they can be positioned anywhere instead of just in character cells. Because they are not scalable, they do not require floating point arithmetic, and therefore they are much faster to display than software characters. Fastgraph makes no special provision for bit-mapped characters because it treats them as if they were any other bit-mapped image. For example, to use a five-pixel by five-pixel bit-mapped font, you can construct characters as shown below and then store these representations in an image array. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * The image display routines fg_drawmap and fg_drwimage, discussed in Chapter 9, could then be used to display specific characters from the image array. Summary of Character Display Routines This section summarizes the functional descriptions of the Fastgraph routines presented in this chapter. More detailed information about these routines, including their arguments and return values, may be found in the Fastgraph Reference Manual. FG_CHGATTR applies the current text display attribute to a given number of characters, starting at the text cursor position. This routine leaves the text cursor one column to the right of the last character changed (or the first column of the next row if the last character is at the end of a row). It has no effect in graphics video modes. FG_CHGTEXT displays a string of hardware characters, starting at the text cursor position, using the existing text display attributes. This routine leaves the text cursor one column to the right of the last character displayed (or the first column of the next row if the last character is at the end of a row). It has no effect in graphics video modes. FG_GETATTR returns the character attribute stored at the specified position on the active video page. It has no effect in graphics video modes. FG_GETCHAR returns the character value stored at the specified position on the active video page. It has no effect in graphics video modes. FG_LOCATE changes the text cursor position for the active video page. FG_SETANGLE defines the angle or orientation at which software characters are displayed. The angle is measured in degrees counterclockwise from the positive x axis. FG_SETATTR establishes the current text display attribute in text video modes. This routine has no effect in graphics video modes. Chapter 7: Character Display Routines 115 FG_SETCOLOR establishes the current color index (which may be a virtual color index in graphics modes). In text modes, the fg_setcolor routine provides an alternate method of establishing the current text display attribute. FG_SETRATIO defines the aspect ratio for software characters. The aspect ratio is the ratio of character width to character height. FG_SETSIZE defines the height of software characters in screen space units. FG_SETSIZEW defines the height of software characters in world space units. FG_SWCHAR displays a string of software characters using the current color index. The string may be left justified, centered, or right justified relative to the graphics cursor position. The string passed to fg_swchar may contain special operators that allow switching between fonts, underlining, superscripting, or subscripting. This routine has no effect in text video modes. FG_SWLENGTH returns the length in world space units of a string of software characters. FG_SWTEXT is a scaled down version of the fg_swchar routine. It does not include the alternate font character definitions and thus requires less memory than fg_swchar. FG_TEXT displays a string of hardware characters, starting at the text cursor position, using the current color attribute (for text modes) or color index (for graphics modes). This routine leaves the text cursor one column to the right of the last character displayed (or the first column of the next row if the last character is at the end of a row). FG_WHERE retrieves the row and column numbers of the text cursor position. FG_XALPHA and FG_YALPHA convert screen space coordinates to character space. FG_XCONVERT and FG_YCONVERT convert character space coordinates to screen space. 116 Fastgraph User's Guide Chapter 8 Video Page Management 118 Fastgraph User's Guide Overview The amount of memory required to store one full screen of information is called a video page. This chapter will discuss video pages in detail, along with the Fastgraph routines you can use to manage video pages. Physical Pages and Virtual Pages Pages that use the memory that resides on the video adapter are called physical pages or true pages. The number of physical pages available depends on the video mode and the amount of memory resident on the user's video adapter. All video modes have at least one physical page. In certain video modes, Fastgraph can allocate available random-access memory (RAM) and treat this memory as a video page. Pages that use standard RAM in this sense are called virtual pages. From a programmer's perspective, virtual pages are essentially identical to physical pages. The following table shows the number of physical pages in each video mode. It also indicates whether or not specific video modes support virtual pages. Mode Page Size Physical Virtual Number Description in Bytes Pages Pages 0 40 column color text 2,000 8 no 1 40 column color text 2,000 8 no 2 80 column color text 4,000 4 no 3 80 column color text 4,000 4 no 4 320 x 200 CGA graphics 16,000 1 yes 5 320 x 200 CGA graphics 16,000 1 yes 6 640 x 200 CGA graphics 16,000 1 yes 7 80 column monochrome text 4,000 1 yes 9 320 x 200 Tandy graphics 32,000 1 yes 11 720 x 348 Hercules graphics 31,320 2 yes 12 320 x 200 Hercules graphics 31,320 2 yes 13 320 x 200 EGA graphics 32,000 8 no 14 640 x 200 EGA graphics 64,000 4 no 15 640 x 350 EGA mono graphics 56,000 2 no 16 640 x 350 EGA graphics 112,000 2 no 17 640 x 480 MCGA/VGA graphics 38,400 1+ no 18 640 x 480 VGA graphics 153,600 1+ no 19 320 x 200 MCGA graphics 64,000 1 yes 20 320 x 200 VGA graphics 64,000 4 no 21 320 x 400 VGA graphics 128,000 2 no 22 320 x 240 VGA graphics 76,800 3+ no 23 320 x 480 VGA graphics 153,600 1+ no The preceding table assumes the video adapter for EGA and VGA modes contains 256K bytes of video memory. For EGA adapters with less video memory, the number of physical pages is reduced proportionately. In other words, a 64K EGA has two video pages available instead of eight pages in mode 13. Chapter 8: Video Page Management 119 Note that the number of physical pages in some video modes is followed by a plus symbol. In these modes, there is an additional partial video page available. For modes 17, 18, and 23, there is one full page (page 0) plus one partial page of 320 pixel rows (page 1). For mode 22, there are three full physical pages (numbered 0 to 2) plus one partial page of 80 pixel rows (page 3). You can safely use the partial pages as long as you don't reference pixel rows beyond the last available row. However, you cannot use the fg_setvpage or the fg_text routines on the partial video page. Physical pages are numbered starting at zero. For example, there are four physical video pages available in mode 3, and they are numbered 0 to 3. Virtual pages are numbered n to 63, where n is the number of physical pages in that mode. For example, there are two physical pages (numbered 0 and 1) and 62 virtual pages (numbered 2 to 63) in mode 11. Note only modes 4 through 12 and mode 19 offer virtual pages, and the amount of conventional memory in the user's system usually limits the number of virtual pages available (this is especially true in mode 19 because of the large page size). Pages With Special Meanings There are three video pages that have special meanings to Fastgraph. The visual page, as one might guess, is the video page currently visible on the user's display. The active page is the video page to which Fastgraph writes text or graphics information. The hidden page is meaningful only to a few Fastgraph routines and will be discussed specifically within the context of those routines. The fg_setmode routine sets all three of these pages to page 0, and it does not matter if these pages are physical or virtual. One of the most useful features of multiple video pages (either physical or virtual) is the ability to build a text or graphics image off screen (that is, on some video page besides the visual page). Then, once the image is ready, we can either transfer it to the visual page, or make the page on which the image resides the visual page. This feature is especially useful in animation, for it displays an image instantaneously instead of visibly updating the screen while producing the image. Some Simple Examples In this section, we will present six variations of a simple program that uses four video pages. The program fills each video page with a rectangle and then displays text containing the video page number in the center of each page. The first two examples run in a specific text or graphics video mode and only use physical pages. The next two examples also run in a specific text or graphics video mode, but they also use virtual pages. The final two examples are more general and run in several video modes. You could of course write a program that essentially does the same thing as the examples in this section without using multiple video pages. However, to use Fastgraph's image display and animation routines effectively, you must first understand the concept of video pages. Before proceeding, we must introduce the Fastgraph routines fg_setpage and fg_setvpage. The fg_setpage routine defines the active video page, which causes Fastgraph to put subsequent text and graphics output on that page. The fg_setvpage routine defines the visual video page displayed on the 120 Fastgraph User's Guide screen. Both routines take a single integer argument between 0 and 63 that specifies the video page number. It does not matter if the referenced video page is a physical page or a virtual page. As mentioned earlier, fg_setmode makes page 0 the active and visual video page. Example 8-1 uses four video pages (numbered 0 to 3) in the 40-column color text mode (mode 1). The program first calls fg_testmode to check the availability of the requested video mode when used with four video pages. If it is available, the program calls fg_setmode to establish that video mode. The first for loop fills each of the four pages with different color rectangles and then displays black text containing the video page number in the center of each page. It does this by calling fg_setpage to define the active video page, fg_setcolor and fg_rect to draw the colored rectangles, and finally fg_setattr, fg_locate, and fg_text to display the text. The program must call fg_locate inside the loop because each video page has its own text cursor position. The second for loop successively makes each video page the visual page; the page remains displayed until you press a key. After displaying all four video pages, the program restores the original video mode and screen attributes before returning to DOS. Example 8-1. #include #include #include void main(void); #define PAGES 4 void main() { int color; int old_mode; int page; char string[8]; if (fg_testmode(1,PAGES) == 0) { printf("This program requires color.\n"); exit(1); } old_mode = fg_getmode(); fg_setmode(1); for (page = 0; page < PAGES; page++) { fg_setpage(page); color = page + 1; fg_setcolor(color); fg_rect(0,fg_getmaxx(),0,fg_getmaxy()); fg_setattr(0,color,0); fg_locate(12,17); sprintf(string,"page %d",page); fg_text(string,6); } for (page = 0; page < PAGES; page++) { Chapter 8: Video Page Management 121 fg_setvpage(page); fg_waitkey(); } fg_setmode(old_mode); fg_reset(); } Example 8-2 is similar to example 8-1, but it uses the 320 by 200 EGA graphics mode (mode 13) instead of a text mode. Note the only real difference between this program and the text mode version is the use of fg_setcolor instead of fg_setattr to make the text appear in black. Example 8-2. #include #include #include void main(void); #define PAGES 4 void main() { int color; int old_mode; int page; char string[8]; if (fg_testmode(13,PAGES) == 0) { printf("This program requires a "); printf("320 x 200 EGA graphics mode.\n"); exit(1); } old_mode = fg_getmode(); fg_setmode(13); for (page = 0; page < PAGES; page++) { fg_setpage(page); color = page + 1; fg_setcolor(color); fg_rect(0,fg_getmaxx(),0,fg_getmaxy()); fg_setcolor(0); fg_locate(12,17); sprintf(string,"page %d",page); fg_text(string,6); } for (page = 0; page < PAGES; page++) { fg_setvpage(page); fg_waitkey(); } fg_setmode(old_mode); fg_reset(); } 122 Fastgraph User's Guide Virtual video pages are created with Fastgraph's fg_allocate routine. The fg_allocate routine reserves conventional random-access memory (RAM) which Fastgraph then treats as a video page. The amount of memory required depends on the current video mode. The fg_allocate routine takes a single integer argument that specifies the page number by which the virtual page will be referenced. This value must be between 0 and 63. If you try to create a virtual page with a page number already assigned to a physical page, fg_allocate does nothing. For example, in the Hercules graphics modes (modes 11 and 12) there are two physical pages numbered 0 and 1. Virtual pages in the Hercules graphics modes must thus have page numbers between 2 and 63. If you tell fg_allocate to create a Hercules virtual page numbered 0 or 1, it does nothing because those video pages are physical pages. Similarly, if you use the fg_allocate routine in a video mode that does not support virtual video pages, it simply returns without doing anything. A possible problem with fg_allocate can occur when there is not enough memory available for creating a virtual page in the current video mode. The fg_allocate routine returns as its function value a status code indicating whether or not it was successful. The possible values of the status code are: value meaning 0 virtual page created 1 specified page number is a physical page 7 virtual page created, but memory control blocks were destroyed 8 insufficient memory to create the virtual page If you use the fg_testmode or fg_bestmode routines to check if the required number of video pages are available when using the requested video mode, you should not need to monitor the status code returned by the fg_allocate routine. The fg_freepage routine releases the memory for a virtual page created with the fg_allocate routine. It requires a single integer argument that specifies the virtual page number to release. This value must be between 0 and 63. If you try to release a physical video page, or release a virtual page that was never created, fg_freepage does nothing. It is a good idea to use fg_freepage to release all virtual video pages before a program returns control to DOS, or just before a program selects a new video mode. Example 8-3 is also similar to example 8-1, but it uses the monochrome text mode (mode 7). Because the monochrome text mode only has one physical video page, we must use virtual video pages for page numbers 1, 2, and 3. Note how the fg_allocate and fg_freepage routines are used to create and release the virtual video pages in this example. Example 8-3. #include #include Chapter 8: Video Page Management 123 #include void main(void); #define PAGES 4 void main() { int old_mode; int page; char string[8]; if (fg_testmode(7,PAGES) == 0) { printf("This program requires monochrome.\n"); exit(1); } old_mode = fg_getmode(); fg_setmode(7); fg_cursor(0); for (page = 0; page < PAGES; page++) { fg_allocate(page); fg_setpage(page); fg_setcolor(7); fg_rect(0,fg_getmaxx(),0,fg_getmaxy()); fg_setattr(0,7,0); fg_locate(12,37); sprintf(string,"page %d",page); fg_text(string,6); } for (page = 0; page < PAGES; page++) { fg_setvpage(page); fg_waitkey(); fg_freepage(page); } fg_setmode(old_mode); fg_reset(); } Example 8-4 is similar to example 8-3, but it uses the standard Hercules graphics mode (mode 11) instead of the monochrome text mode. Because the Hercules graphics modes have two physical video pages, we must use virtual video pages for page numbers 2 and 3. Note the only real difference between this program and the text mode version is the use of fg_setcolor instead of fg_setattr to make the text appear in black. Example 8-4. #include #include #include void main(void); #define PAGES 4 124 Fastgraph User's Guide void main() { int old_mode; int page; char string[8]; if (fg_testmode(11,PAGES) == 0) { printf("This program requires Hercules "); printf("monochrome graphics.\n"); exit(1); } old_mode = fg_getmode(); fg_setmode(11); for (page = 0; page < PAGES; page++) { fg_allocate(page); fg_setpage(page); fg_setcolor(7); fg_rect(0,fg_getmaxx(),0,fg_getmaxy()); fg_setcolor(0); fg_locate(12,37); sprintf(string,"page %d",page); fg_text(string,6); } for (page = 0; page < PAGES; page++) { fg_setvpage(page); fg_waitkey(); fg_freepage(page); } fg_setmode(old_mode); fg_reset(); } Example 8-5 is a generalized version of examples 8-1 and 8-3 that runs in any 80-column text video mode. To simplify the program, each video page is filled with rectangles of the same color. Note that fg_allocate and fg_freepage are used to manage the virtual video pages in case fg_bestmode selects the monochrome text mode (mode 7). If fg_bestmode selects one of the 80-column color text modes (which have four physical video pages), fg_allocate and fg_freepage will simply return without doing anything. Example 8-5. #include #include #include void main(void); #define PAGES 4 void main() { int old_mode, new_mode; Chapter 8: Video Page Management 125 int page; char string[8]; new_mode = fg_bestmode(80,25,PAGES); if (new_mode < 0) { printf("This program requires "); printf("an 80-column display.\n"); exit(1); } old_mode = fg_getmode(); fg_setmode(new_mode); fg_cursor(0); for (page = 0; page < PAGES; page++) { fg_allocate(page); fg_setpage(page); fg_setcolor(7); fg_rect(0,fg_getmaxx(),0,fg_getmaxy()); fg_setattr(0,7,0); fg_locate(12,37); sprintf(string,"page %d",page); fg_text(string,6); } for (page = 0; page < PAGES; page++) { fg_setvpage(page); fg_waitkey(); fg_freepage(page); } fg_setmode(old_mode); fg_reset(); } Example 8-6 is a generalized version of examples 8-2 and 8-4 that runs in any 320 by 200 graphics video mode. To simplify the program, each video page is filled with rectangles of the same color. As in example 8-5, fg_allocate and fg_freepage are used to manage the virtual video pages in case fg_bestmode selects a video mode with fewer than four physical video pages. Note the only real difference between this program and the text mode version is the use of fg_setcolor instead of fg_setattr to make the text appear in black. Example 8-6. #include #include #include void main(void); #define PAGES 4 void main() { int old_mode, new_mode; int page; char string[8]; 126 Fastgraph User's Guide new_mode = fg_bestmode(320,200,PAGES); if (new_mode < 0) { printf("This program requires a "); printf("320 x 200 graphics mode.\n"); exit(1); } old_mode = fg_getmode(); fg_setmode(new_mode); for (page = 0; page < PAGES; page++) { fg_allocate(page); fg_setpage(page); fg_setcolor(15); fg_rect(0,fg_getmaxx(),0,fg_getmaxy()); fg_setcolor(0); fg_locate(12,17); sprintf(string,"page %d",page); fg_text(string,6); } for (page = 0; page < PAGES; page++) { fg_setvpage(page); fg_waitkey(); fg_freepage(page); } fg_setmode(old_mode); fg_reset(); } Text Cursors As mentioned in the previous chapter, Fastgraph draws hardware characters at the position defined by the text cursor. Like the graphics cursor, the text cursor is not a cursor in the true sense, but is simply a pair of character space (row,column) coordinates with a special meaning. The first 8 video pages (that is, pages 0 through 7) each have their own text cursor. Each subsequent group of 8 video pages (pages 8 through 15, pages 16 to 23, and so forth) respectively share the same text cursor positions as the first 8 pages. This means the fg_locate routine will update one of 8 different text cursors depending on the active video page. Similarly, the fg_where routine returns the text cursor position for the active page. The fg_setmode routine sets all 8 text cursor positions to the character space coordinates (0,0). Example 8-7 demonstrates the use of different text cursors in an 80- column color text mode (mode 3). The program first displays the text "Page " on video page 0 (the visible page) and waits for a keystroke. It then makes page 1 the active video page, changes the text cursor location for that page, and displays the text "Page 1" on video page 1. Next, it appends the character "0" to the text originally displayed on page 0. Note it is not necessary to restore the text cursor position for page 0 because it is unaffected by changing the text cursor for page 1. After waiting for another Chapter 8: Video Page Management 127 keystroke, the program makes video page 1 the visual page and then waits for yet another keystroke before returning to DOS. Example 8-7. #include void main(void); void main() { int old_mode; old_mode = fg_getmode(); fg_setmode(3); fg_cursor(0); fg_setattr(10,0,0); fg_locate(1,0); fg_text("Page ",5); fg_waitkey(); fg_setpage(1); fg_locate(23,0); fg_text("Page 1",6); fg_setpage(0); fg_text("0",1); fg_waitkey(); fg_setvpage(1); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Obtaining Video Page Information Fastgraph includes two routines, fg_getpage and fg_getvpage, that respectively return the current active or visual video page number. Each routine returns the video page number as its function value, and neither routine requires any arguments. The fg_getaddr routine is sometimes useful when using virtual pages. It returns as its function value the segment address for the start of the active video page. It does not require any arguments. Although fg_getaddr is more useful when using virtual video pages, it works equally well when using physical video pages. Example 8-8 illustrates the use of the fg_getpage, fg_getvpage, and fg_getaddr routines in the standard CGA color graphics mode (mode 4). This video mode offers only one physical page, so the program uses fg_allocate to create a virtual video page (page 1). After creating the virtual page, the program makes it the active video page; page 0 remains the visual video page. The fg_getpage routine then returns the active page number (1), followed by a call to fg_getvpage to return the visual page number (0). Next, the program 128 Fastgraph User's Guide uses fg_getaddr to return the segment address for video pages 0 and 1. Finally, it restores the original video mode and screen attributes, displays the returned values, and returns to DOS. Example 8-8. #include #include void main(void); void main() { int old_mode; int active, visual; int page0, page1; old_mode = fg_getmode(); fg_setmode(4); fg_allocate(1); fg_setpage(1); active = fg_getpage(); visual = fg_getvpage(); fg_setpage(0); page0 = fg_getaddr(); fg_setpage(1); page1 = fg_getaddr(); fg_freepage(1); fg_setmode(old_mode); fg_reset(); printf("Active page is %d.\n",active); printf("Visual page is %d.\n",visual); printf("Page 0 address is %4X\n",page0); printf("Page 1 address is %4X\n",page1); } Considerations for Virtual Pages When you are using virtual pages, you should avoid using the fg_setvpage routine in sections of the program that require fast screen updates or animation sequences. This is because the PC and PS/2 video BIOS are only capable of displaying physical pages. To compensate for this restriction, Fastgraph exchanges the contents of a physical page with the requested virtual page. In other words, if page 1 is a virtual page and you make it the visual page, Fastgraph will exchange the contents of page 1 with whatever page was previously the visual page. This does not mean Fastgraph's page numbers change because Fastgraph also maintains an internal table containing video page addresses and exchanges the two corresponding table entries. As before, you would make page 1 the active video page if you wanted to write something to the visual page. About the only other potential problem when using virtual pages is what happens when you try to write to a non-existent video page (for example, if Chapter 8: Video Page Management 129 you write to virtual video page 1 before creating it with fg_allocate). In this case, Fastgraph simply redirects the video output to the visual page. Logical Pages In addition to physical and virtual video pages, Fastgraph offers another class of video pages, called logical pages. You can create logical pages in any video mode. They can exist in conventional memory, expanded memory (EMS), or extended memory (XMS). However, they are not as versatile as physical or virtual pages because the only operations you can perform with logical pages are: Copy an entire physical or virtual page to a logical page Copy an entire logical page to a physical or virtual page Copy an entire logical page to another logical page Three Fastgraph routines -- fg_alloccms, fg_allocems, and fg_allocxms -- create logical pages in conventional memory, expanded memory, and extended memory, respectively. All three routines have a single integer argument that specifies the page number by which the logical page will be referenced. The page number must be between 1 and 63 and must not reference a physical or virtual page. Their return value is 0 if the logical page is created, and negative otherwise (refer to the descriptions of these routines in the Fastgraph Reference Manual for a complete list of return values). As with virtual pages, use the fg_freepage function to release a logical page. Before you can create logical pages in expanded or extended memory, you must initialize these resources for use with Fastgraph. The fg_initems routine initializes expanded memory. To use expanded memory, you must have an Expanded Memory Manager (EMM) that conforms to the Lotus/Intel/Microsoft Expanded Memory Specification (LIM-EMS) version 3.2 or later. On 80386 and 80486 systems, the EMM386.EXE device driver supplied with DOS 5.0 can be used to treat some or all of extended memory as expanded memory. The fg_initxms routine initializes extended memory for use with Fastgraph. To use extended memory, you must have an XMS driver that conforms to the Lotus/Intel/Microsoft/AST eXtended Memory Specification version 2.0 or later, such as HIMEM.SYS. XMS drivers require an 80286, 80386, or 80486 system. The fg_initems and fg_initxms routines have no arguments. Their return value is 0 if successful, and -1 if the required driver and resources are not present. Example 8-9 illustrates the use of logical pages in a 320 x 200 color graphics mode. The program first tries to create a logical page in extended memory by calling fg_initxms and fg_allocxms. If the initialization or page creation fails, it then tries to create the page in expanded memory with fg_initems and fg_allocems. Should that fail, the program calls fg_alloccms to try to create the page in conventional memory. If it can't create the logical page at all, the program displays an error message and exits. Once the logical page is created, example 8-9 displays the word "test" in the middle of the visual page (page 0) and then uses fg_copypage to transfer the visual page contents to the logical page (page 8). Because this program runs in one of several different graphics modes, we must use a logical page number greater than any possible physical page number. We chose page 8 because mode 13 has physical pages numbered 0 through 7, and no mode has higher-numbered physical pages. After waiting for a keystroke, the 130 Fastgraph User's Guide program erases the visual page, waits for another keystroke, and copies the logical page contents back to the visual page. It then releases the logical page and exits. Example 8-9. #include #include #include void main(void); void main() { int new_mode, old_mode; int status; new_mode = fg_bestmode(320,200,1); if (new_mode < 0 || new_mode == 12) { printf("This program requires a 320 "); printf("x 200 color graphics mode.\n"); exit(1); } old_mode = fg_getmode(); fg_setmode(new_mode); status = fg_initxms(); if (status == 0) status = fg_allocxms(8); if (status < 0) { status = fg_initems(); if (status == 0) status = fg_allocems(8); } if (status < 0) status = fg_alloccms(8); if (status < 0) { fg_setmode(old_mode); fg_reset(); printf("Unable to create logical page.\n"); exit(1); } fg_setcolor(7); fg_rect(0,319,0,199); fg_setcolor(9); fg_locate(12,18); fg_text("test",4); fg_waitkey(); fg_copypage(0,8); fg_erase(); fg_waitkey(); fg_copypage(8,0); fg_waitkey(); fg_freepage(8); fg_setmode(old_mode); fg_reset(); } Chapter 8: Video Page Management 131 As mentioned before, the only function you can perform with logical pages is copying one video page to another. The fg_copypage routine provides the only way to do this for logical pages. See page 175 for a description of fg_copypage. Video Page Resizing Resizing is the process of changing the dimensions of a video page. It is available only in the native EGA graphics modes (modes 13 to 16), native VGA graphics modes (modes 17 and 18), and extended VGA modes (modes 20 to 23). Resizing does not change the screen resolution, but instead increases the video page size so that only part of the page is visible. For now, we'll just introduce resizing with a simple example, but in Chapter 11 we'll see its real power when we perform smooth panning. The Fastgraph routine fg_resize changes the dimensions of a video page. Its two integer arguments define the page width and page height, both in pixels. Example 8-10 runs in the 320 x 200 EGA graphics mode (mode 13). After establishing the video mode, it displays the word "resize" starting in column 38 of row 0. Because the characters extend beyond the last column of the row, they wrap to the next row. The program continues displaying this until you press a key. Then, it clears the screen and calls fg_resize to make the page size 640 x 200 pixels. Again the program displays the word "resize" starting in column 38 of row 0, but this time it does not wrap to the next row. This is because the resizing doubled the page width, which increased the number of character cells per row from 40 to 80. The characters that formerly wrapped to the next row now continue on an off- screen portion of the same row. Example 8-10. #include #include #include void main(void); void main() { int old_mode; if (fg_testmode(13,1) == 0) { printf("This program requires a 320 "); printf("x 200 EGA graphics mode.\n"); exit(1); } old_mode = fg_getmode(); fg_setmode(13); fg_setcolor(9); fg_locate(0,38); fg_text("resize",6); fg_waitkey(); fg_erase(); 132 Fastgraph User's Guide fg_resize(640,200); fg_setcolor(10); fg_locate(0,38); fg_text("resize",6); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } The size of a video page is constrained only by the amount of video memory available. Increasing the video page size reduces the number of physical pages available proportionally. In mode 13, for example, increasing the page size from 320 x 200 to 640 x 400 reduces the number of video pages from 8 to 2. When you call fg_resize, the visual page must be page 0. If you have created any logical video pages, you must release them with fg_freepage before calling fg_resize, and then create them again afterward. If you have initialized the mouse (with fg_mouseini), joysticks (with fg_initjoy), expanded memory (with fg_initems), or extended memory (with fg_initxms), you should re-initialize these resources after calling fg_resize. Most mouse drivers expect a fixed video page width, so the mouse cursor may become distorted after resizing video pages. When you call fg_resize, Fastgraph sets the clipping region to the new page limits. The fg_setmode routine re-establishes the dimensions of a video page to the default screen resolution for the selected video mode. Depending on the dimensions passed to fg_resize, you may end up with a partial video page. Again, suppose we're using mode 13 and have changed the page size to 960 x 400 (this is six times the default page size). The original pages 0 to 5 now comprise page 0, and original pages 6 and 7 now comprise page 1. However, there is not enough video memory left on page 1 for a full 960 x 400 page. In this case, the number of pixel rows available on page 1 would be one-third the full page size, or 133 rows. This is because the total storage required by original pages 6 and 7 is one-third the total required for original pages 0 through 5. Summary of Video Page Management Routines This section summarizes the functional descriptions of the Fastgraph routines presented in this chapter. More detailed information about these routines, including their arguments and return values, may be found in the Fastgraph Reference Manual. FG_ALLOCATE creates a virtual video page. The amount of memory required depends on the current video mode. This routine has no effect if it references a physical or logical video page. FG_ALLOCEMS creates a logical page in expanded memory (EMS). The amount of memory required depends on the current video mode and video buffer dimensions. This routine has no effect if it references a physical or virtual video page. FG_ALLOCXMS creates a logical page in extended memory (XMS). The amount of memory required depends on the current video mode and video buffer dimensions. This routine has no effect if it references a physical or virtual video page. Chapter 8: Video Page Management 133 FG_COPYPAGE transfers the contents of one video page to another. The pages may be physical, virtual, or logical video pages. If both pages are logical pages, they must exist in the same type of memory. FG_FREEPAGE releases a virtual or logical video page created with the fg_allocate, fg_alloccms, fg_allocems, or fg_allocxms routines. This routine has no effect if it references a physical video page, or a virtual page that was never created. FG_GETADDR returns the segment address of the active video page. FG_GETPAGE returns the active video page number. FG_GETVPAGE returns the visual video page number. FG_INITEMS initializes expanded memory for use with Fastgraph. FG_INITXMS initializes extended memory for use with Fastgraph. FG_RESIZE changes the dimensions of a video page in EGA and VGA graphics modes. FG_SETPAGE establishes the active video page. It may be a physical or virtual page. FG_SETVPAGE establishes the visual video page. It may be a physical or virtual page.