├── .cvsignore ├── BUGS ├── COPYING ├── ChangeLog ├── Makefile ├── Notes ├── README ├── TODO ├── biossums.c ├── clext.c ├── dataseghack ├── tests ├── lfbprof │ ├── Makefile │ ├── lfbprof.c │ └── lfbprof.h └── testbios.c ├── vbe.c ├── vbe.h ├── vbe_display_api.txt ├── vbetables-gen.c ├── vgabios.c ├── vgabios.h ├── vgafonts.h └── vgatables.h /.cvsignore: -------------------------------------------------------------------------------- 1 | vbetables.h 2 | -------------------------------------------------------------------------------- /BUGS: -------------------------------------------------------------------------------- 1 | Not all the functions have been implemented yet. 2 | 3 | Please report any bugs to 4 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | 504 | 505 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | 3 | CC = gcc 4 | CFLAGS = -g -O2 -Wall -Wstrict-prototypes 5 | LDFLAGS = 6 | 7 | GCC = gcc 8 | BCC = bcc 9 | AS86 = as86 10 | 11 | RELEASE = `pwd | sed "s-.*/--"` 12 | RELDATE = `date '+%d %b %Y'` 13 | RELVERS = `pwd | sed "s-.*/--" | sed "s/vgabios//" | sed "s/-//"` 14 | 15 | VGABIOS_DATE = "-DVGABIOS_DATE=\"$(RELDATE)\"" 16 | 17 | all: bios cirrus-bios stdvga-bios vmware-bios qxl-bios 18 | 19 | bios: vgabios.bin vgabios.debug.bin 20 | 21 | cirrus-bios: vgabios-cirrus.bin vgabios-cirrus.debug.bin 22 | 23 | stdvga-bios: vgabios-stdvga.bin vgabios-stdvga.debug.bin 24 | 25 | vmware-bios: vgabios-vmware.bin vgabios-vmware.debug.bin 26 | 27 | qxl-bios: vgabios-qxl.bin vgabios-qxl.debug.bin 28 | 29 | clean: 30 | /bin/rm -f biossums vbetables-gen vbetables.h *.o *.s *.ld86 \ 31 | temp.awk.* vgabios*.orig _vgabios_* _vgabios-debug_* core vgabios*.bin vgabios*.txt $(RELEASE).bin *.bak 32 | 33 | dist-clean: clean 34 | 35 | # source files 36 | VGA_FILES := vgabios.c vgabios.h vgafonts.h vgatables.h 37 | VBE_FILES := vbe.h vbe.c vbetables.h 38 | 39 | # build flags 40 | vgabios.bin : VGAFLAGS := -DVBE -DPCI_VID=0x1234 41 | vgabios.debug.bin : VGAFLAGS := -DVBE -DPCI_VID=0x1234 -DDEBUG 42 | vgabios-cirrus.bin : VGAFLAGS := -DCIRRUS -DPCIBIOS 43 | vgabios-cirrus.debug.bin : VGAFLAGS := -DCIRRUS -DPCIBIOS -DCIRRUS_DEBUG 44 | vgabios-stdvga.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x1234 -DPCI_DID=0x1111 45 | vgabios-stdvga.debug.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x1234 -DPCI_DID=0x1111 -DDEBUG 46 | vgabios-vmware.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x15ad -DPCI_DID=0x0405 47 | vgabios-vmware.debug.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x15ad -DPCI_DID=0x0405 -DDEBUG 48 | vgabios-qxl.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x1b36 -DPCI_DID=0x0100 49 | vgabios-qxl.debug.bin : VGAFLAGS := -DVBE -DPCIBIOS -DPCI_VID=0x1b36 -DPCI_DID=0x0100 -DDEBUG 50 | 51 | # dist names 52 | vgabios.bin : DISTNAME := VGABIOS-lgpl-latest.bin 53 | vgabios.debug.bin : DISTNAME := VGABIOS-lgpl-latest.debug.bin 54 | vgabios-cirrus.bin : DISTNAME := VGABIOS-lgpl-latest.cirrus.bin 55 | vgabios-cirrus.debug.bin : DISTNAME := VGABIOS-lgpl-latest.cirrus.debug.bin 56 | vgabios-stdvga.bin : DISTNAME := VGABIOS-lgpl-latest.stdvga.bin 57 | vgabios-stdvga.debug.bin : DISTNAME := VGABIOS-lgpl-latest.stdvga.debug.bin 58 | vgabios-vmware.bin : DISTNAME := VGABIOS-lgpl-latest.vmware.bin 59 | vgabios-vmware.debug.bin : DISTNAME := VGABIOS-lgpl-latest.vmware.debug.bin 60 | vgabios-qxl.bin : DISTNAME := VGABIOS-lgpl-latest.qxl.bin 61 | vgabios-qxl.debug.bin : DISTNAME := VGABIOS-lgpl-latest.qxl.debug.bin 62 | 63 | # dependencies 64 | vgabios.bin : $(VGA_FILES) $(VBE_FILES) biossums 65 | vgabios.debug.bin : $(VGA_FILES) $(VBE_FILES) biossums 66 | vgabios-cirrus.bin : $(VGA_FILES) clext.c biossums 67 | vgabios-cirrus.debug.bin : $(VGA_FILES) clext.c biossums 68 | vgabios-stdvga.bin : $(VGA_FILES) $(VBE_FILES) biossums 69 | vgabios-stdvga.debug.bin : $(VGA_FILES) $(VBE_FILES) biossums 70 | vgabios-vmware.bin : $(VGA_FILES) $(VBE_FILES) biossums 71 | vgabios-vmware.debug.bin : $(VGA_FILES) $(VBE_FILES) biossums 72 | vgabios-qxl.bin : $(VGA_FILES) $(VBE_FILES) biossums 73 | vgabios-qxl.debug.bin : $(VGA_FILES) $(VBE_FILES) biossums 74 | 75 | # build rule 76 | %.bin: 77 | $(GCC) -E -P vgabios.c $(VGABIOS_VERS) $(VGAFLAGS) $(VGABIOS_DATE) > _$*_.c 78 | $(BCC) -o $*.s -C-c -D__i86__ -S -0 _$*_.c 79 | sed -e 's/^\.text//' -e 's/^\.data//' $*.s > _$*_.s 80 | $(AS86) _$*_.s -b $*.bin -u -w- -g -0 -j -O -l $*.txt 81 | rm -f _$*_.s _$*_.c $*.s 82 | mv $*.bin $(DISTNAME) 83 | ./biossums $(DISTNAME) 84 | ls -l $(DISTNAME) 85 | 86 | release: 87 | VGABIOS_VERS=\"-DVGABIOS_VERS=\\\"$(RELVERS)\\\"\" make bios cirrus-bios 88 | /bin/rm -f *.o *.s *.ld86 \ 89 | temp.awk.* vgabios.*.orig _vgabios_.*.c core *.bak .#* 90 | cp VGABIOS-lgpl-latest.bin ../$(RELEASE).bin 91 | cp VGABIOS-lgpl-latest.debug.bin ../$(RELEASE).debug.bin 92 | cp VGABIOS-lgpl-latest.cirrus.bin ../$(RELEASE).cirrus.bin 93 | cp VGABIOS-lgpl-latest.cirrus.debug.bin ../$(RELEASE).cirrus.debug.bin 94 | tar czvf ../$(RELEASE).tgz --exclude CVS -C .. $(RELEASE)/ 95 | 96 | biossums: biossums.c 97 | $(CC) -o biossums biossums.c 98 | 99 | vbetables-gen: vbetables-gen.c 100 | $(CC) -o vbetables-gen vbetables-gen.c 101 | 102 | vbetables.h: vbetables-gen 103 | ./vbetables-gen > $@ 104 | -------------------------------------------------------------------------------- /Notes: -------------------------------------------------------------------------------- 1 | Development notes 2 | ----------------- 3 | 4 | - need to split video init function 5 | 1. set bios variables 6 | 2. do the real init with io based on bios variables 7 | 8 | - characters format switching will set the bios 9 | variables and call function #2 above 10 | 11 | - need to rework the tables as explained in Interrupt list 12 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Plex86/Bochs VGABios 2 | -------------------- 3 | 4 | The goal of this project is to have a LGPL'd Video Bios in plex86, 5 | Bochs and qemu. 6 | This VGA Bios is very specific to the emulated VGA card. 7 | It is NOT meant to drive a physical vga card. 8 | 9 | 10 | Cirrus SVGA extension 11 | --------------------- 12 | 13 | The Cirrus SVGA extension is designed for the Cirrus emulation in Bochs and 14 | qemu. The initial patch for the Cirrus extension has been written by Makoto 15 | Suzuki (suzu). 16 | 17 | 18 | Install 19 | ------- 20 | To compile the VGA Bios you will need : 21 | - gcc 22 | - bcc 23 | - as86 24 | - ld86 25 | 26 | Untar the archive, and type make. You should get a "VGABIOS-lgpl-latest.bin" 27 | file. Alternatively, you can use the binary file "VGABIOS-lgpl-latest.bin", 28 | i have compiled for you. 29 | 30 | Edit your plex86/bochs conf file, and modify the load-rom command in the 31 | VGA BIOS section, to point to the new vgabios image file. 32 | 33 | 34 | Debugging 35 | --------- 36 | You can get a very basic debugging system: messages printed by the vgabios. 37 | You have to register the "unmapped" device driver in plex86 or bochs, and make 38 | sure it grabs port 0xfff0. 39 | 40 | Comment the #undef DEBUG at the beginning of vgabios.c. 41 | You can then use the "printf" function in the bios. 42 | 43 | 44 | Testing 45 | ------- 46 | Look at the "testvga.c" file in the archive. This is a minimal Turbo C 2.0 47 | source file that calls a few int10 functions. Feel free to modify it to suit 48 | your needs. 49 | 50 | 51 | Copyright and License 52 | --------------------- 53 | This program has been written by Christophe Bothamy 54 | It is protected by the GNU Lesser Public License, which you should 55 | have received a copy of along with this package. 56 | 57 | 58 | Reverse Engineering 59 | ------------------- 60 | The VGA Bios has been written without reverse-engineering any existing Bios. 61 | 62 | 63 | Acknowledgment 64 | -------------- 65 | The source code contains code ripped from rombios.c of plex86, written 66 | by Kevin Lawton 67 | 68 | The source code contains fonts from fntcol16.zip (c) by Joseph Gil avalable at : 69 | ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip 70 | These fonts are public domain 71 | 72 | The source code is based on information taken from : 73 | - Kevin Lawton's vga card emulation for bochs/plex86 74 | - Ralf Brown's interrupts list avalaible at 75 | http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html 76 | - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/ 77 | - Michael Abrash's Graphics Programming Black Book 78 | - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" 79 | edited by sybex 80 | - DOSEMU 1.0.1 source code for several tables values and formulas 81 | 82 | 83 | Feedback 84 | -------- 85 | Please report any bugs, comments, patches for this VGA Bios to info@vruppert.de 86 | You can find the latest release at : http://www.nongnu.org/vgabios/ 87 | For any information on bochs, visit the website http://bochs.sourceforge.net/ 88 | For any information on qemu, visit the website http://fabrice.bellard.free.fr/qemu/ 89 | 90 | 91 | History 92 | ------- 93 | vgabios-0.6c : Apr 08 2009 94 | - Volker 95 | . added DPMS support to cirrus vgabios (patch from Gleb Natapov) 96 | . use VBE LFB address from PCI base address if present 97 | . added support for a lot more non-standard VBE modes (e.g. widescreen modes) 98 | . minor bugfixes 99 | 100 | vgabios-0.6b : May 30 2008 101 | - Volker 102 | . added PCI data structure for the Cirrus VGABIOS images 103 | . minor bugfixes in biossums utility, VBE support and makefile 104 | 105 | vgabios-0.6a : Aug 19 2006 106 | - Volker 107 | . added minimal support for the video parameter table (VPT) 108 | . Cirrus SVGA now supports the "no clear" bit in Cirrus and VESA mode 109 | . Bochs VBE protected mode interface improved 110 | . save/restore video state support for Bochs VBE and standard VGA added 111 | . generate vbetables.h dynamicly 112 | . VBE video memory increased to 8 MB (VBE dispi ID changed to B0C4) 113 | . lots of 4bpp VBE fixes (all 4bpp VBE modes now enabled) 114 | . VGA compatible setup for VBE modes added 115 | 116 | vgabios-0.5d : Dec 29 2005 117 | - Volker 118 | . Bochs VBE protected mode interface added (based on a patch by malc@pulsesoft.com) 119 | . biossums utility now supports VGABIOS sizes up to 64 kBytes 120 | . VGA mode 0x11: all color planes must be enabled in this 2-color VGA mode 121 | 122 | vgabios-0.5c : Jul 07 2005 123 | - Volker 124 | . BIOS configuration word usually reports initial mode 80x25 color text 125 | . vgabios function 0x0e (write teletype): linefeed (0x0a) only increments the 126 | cursor row value 127 | 128 | vgabios-0.5b : May 24 2005 129 | - Volker 130 | . fixed return value for the default case in the VBE section (non-debug mode) 131 | . removed unused stuff 132 | 133 | vgabios-0.5a : Mar 07 2005 134 | - Volker 135 | . Cirrus SVGA extension (initial patches from Makoto Suzuki, improvements 136 | from Fabrice Bellard) 137 | . vgabios image size is now exactly 32k with a checksum 138 | . a lot of vgabios and vbe functions rewritten in assembler 139 | . dynamicly generated VBE mode info list 140 | . write character function for CGA and LINEAR8 modes 141 | . read/write graphics pixel for some graphics modes 142 | . text scroll feature for some graphics modes 143 | . VBE 8-bit DAC support 144 | 145 | vgabios-0.4c : Nov 06 2003 146 | - Christophe 147 | . fix font problem on initial screen of NT4 Loader 148 | 149 | vgabios-0.4b : Nov 04 2003 150 | - Volker 151 | . fix offset of character tables 152 | . optimizations of CRT controller accesses 153 | . VBE i/o registers changed to 0x01CE/CF 154 | (suggestion from Daniel Gimpelevich) 155 | . "noclear" flag stored in BIOS area 156 | . fix character height returned by get_font_info function 157 | 158 | vgabios-0.4a : Aug 17 2003 159 | - Volker 160 | . VBE mode search rewritten (VBE modes with LFB bit removed) 161 | . many bugfixes and optimizations 162 | . write character function implemented for graphics modes 163 | . support for 15bpp, 16bpp, 24bpp and 32bpp VBE modes added 164 | . SVGA mode 0x6A added 165 | . VBE modes 0x102, 0x117, 0x118 and 0x142 (Bochs specific) 166 | 167 | vgabios-0.3b : Nov 23 2002 168 | - Christophe 169 | . added lfb-mode numbers (patch from mathis) 170 | . updated the Makefile 171 | . removed display of copyrights. 172 | . changed the Copyright string to "LGPL VGABios developers" 173 | - Volker 174 | . set the cursor shape depending on the current font height 175 | . clear BL before calling int 0x10 function 0x1103 in vgabios_init_func 176 | . added some text font functions 177 | - Jeroen 178 | . Forced to new DISPI (0xb0c1) interface (requires latest bochs vbe code) 179 | . Added multibuffering support 180 | . Added new DISPI interface for: virt width, height, x offset, y offset 181 | . Added LFB modes (to be used with the vbe-lfb patch in bochs) 182 | see VBE_HAVE_LFB in vbe.c (currently default enabled) 183 | . updated TODO & docs for changes after bochs 1.4 184 | 185 | vgabios-0.3a : Mar 10 2002 186 | - Christophe 187 | . Fixed bug in function ah=13 188 | - Jeroen 189 | . updated vbebios implementation to new api 190 | . added vbe_display_api documentation 191 | . added 640x400x8, 640x480x8, 800x600x8, 1024x768 192 | (>640x480 needs a special bochs patch atm) 193 | . added 320x200x8 vbe support (uses the standard 320x200x8 vga mode to 194 | display, this allows for testing & having something on screen as well, 195 | at least until bochs host side display is up & running) 196 | . adding lfbprof (vbe) testprogram (+some small fixes to it) 197 | . merging with vbebios 0.2 198 | 199 | vgabios-0.2b : Nov 19 2001 200 | - Christophe 201 | . Fixed bug in function ah=13 202 | 203 | vgabios-0.2a : Nov 09 2001 204 | - Christophe 205 | . Included bugfix from techt@pikeonline.net about grayscale summing 206 | . Added the "IBM" string at org 0x1e as Bart Oldeman suggested 207 | . Fixed DS and ES that where inverted in the int10 parameters list! 208 | . The following have been implemented : 209 | - function ax=1a00, ax=1a01, ah=1b 210 | - function ax=1130 211 | . Added debug messages for unimplemented/unknown functions 212 | Must be compiled with DEBUG defined. The output is trapped 213 | by the unknown-ioport driver of plex/bochs (port 0xfff0 is used) 214 | 215 | vgabios-0.1a : May 8 2001 216 | - Christophe 217 | . First release. The work has been focused only on text mode. 218 | . The following have been implemented : 219 | - inits 220 | - int 10 handler 221 | - functions ah=00, ah=01, ah=02, ah=03, ah=05, ah=06, ah=07, ah=08 222 | ah=09, ah=0a, ah=0e, ah=0f, ax=1000, ax=1001, ax=1002, ax=1003 223 | ax=1007, ax=1008, ax=1009, ax=1010, ax=1012, ax=1013, ax=1015 224 | ax=1017, ax=1018, ax=1019, ax=101a, ax=101b, ah=12 bl=10, 225 | ah=12 bl=30, ah=12 bl=31, ah=12 bl=32, ah=12 bl=33, ah=12 bl=34 226 | ah=13 227 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Short term : 2 | ------------ 3 | 4 | General 5 | - Fix init mode (ah=00). Should use more BIOS variables 6 | - Add new functionalities and modify static functionality table 7 | - Performance : 16 bits IO 8 | 9 | v0.7 10 | - Implement the remaining functions (don't know if all are needed): 11 | - chargen ax=1120, ax=1121, ax=1122, ax=1123, ax=1124 12 | - display switch interface ah=12 bl=35 13 | - video refresh control ah=12 bl=36 14 | - Graphic modes 15 | 16 | v1.0 17 | - Bugfixes 18 | 19 | 20 | ================================================================================================= 21 | VBE: 22 | ---- 23 | Long term: 24 | - have plex86 host side display interface 25 | - have text io functions in vbe mode 26 | 27 | -------------------------------------------------------------------------------- /biossums.c: -------------------------------------------------------------------------------- 1 | /* biossums.c --- written by Eike W. for the Bochs BIOS */ 2 | /* adapted for the LGPL'd VGABIOS by vruppert */ 3 | 4 | /* This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | #include 19 | #include 20 | #include 21 | 22 | typedef unsigned char byte; 23 | 24 | void check( int value, char* message ); 25 | 26 | #define MAX_BIOS_DATA 0x10000 27 | 28 | long chksum_bios_get_offset( byte* data, long offset ); 29 | byte chksum_bios_calc_value( byte* data, long offset ); 30 | byte chksum_bios_get_value( byte* data, long offset ); 31 | void chksum_bios_set_value( byte* data, long offset, byte value ); 32 | 33 | #define PMID_LEN 20 34 | #define PMID_CHKSUM 19 35 | 36 | long chksum_pmid_get_offset( byte* data, long offset ); 37 | byte chksum_pmid_calc_value( byte* data, long offset ); 38 | byte chksum_pmid_get_value( byte* data, long offset ); 39 | void chksum_pmid_set_value( byte* data, long offset, byte value ); 40 | 41 | #define PCIR_LEN 24 42 | 43 | long chksum_pcir_get_offset( byte* data, long offset ); 44 | 45 | 46 | byte bios_data[MAX_BIOS_DATA]; 47 | long bios_len; 48 | 49 | 50 | int main(int argc, char* argv[]) 51 | { 52 | FILE* stream; 53 | long offset, tmp_offset, pcir_offset; 54 | byte bios_len_byte, cur_val = 0, new_val = 0; 55 | int hits, modified; 56 | 57 | if (argc != 2) { 58 | printf( "Error. Need a file-name as an argument.\n" ); 59 | exit( EXIT_FAILURE ); 60 | } 61 | 62 | if ((stream = fopen(argv[1], "rb")) == NULL) { 63 | printf("Error opening %s for reading.\n", argv[1]); 64 | exit(EXIT_FAILURE); 65 | } 66 | memset(bios_data, 0, MAX_BIOS_DATA); 67 | bios_len = fread(bios_data, 1, MAX_BIOS_DATA, stream); 68 | if (bios_len > MAX_BIOS_DATA) { 69 | printf("Error reading max. 65536 Bytes from %s.\n", argv[1]); 70 | fclose(stream); 71 | exit(EXIT_FAILURE); 72 | } 73 | fclose(stream); 74 | modified = 0; 75 | if (bios_len < 0x8000) { 76 | bios_len = 0x8000; 77 | modified = 1; 78 | } else if ((bios_len & 0x1FF) != 0) { 79 | bios_len = (bios_len + 0x200) & ~0x1FF; 80 | modified = 1; 81 | } 82 | bios_len_byte = (byte)(bios_len / 512); 83 | if (bios_len_byte != bios_data[2]) { 84 | if (modified == 0) { 85 | bios_len += 0x200; 86 | } 87 | bios_data[2] = (byte)(bios_len / 512); 88 | modified = 1; 89 | } 90 | 91 | hits = 0; 92 | offset = 0L; 93 | while( (tmp_offset = chksum_pmid_get_offset( bios_data, offset )) != -1L ) { 94 | offset = tmp_offset; 95 | cur_val = chksum_pmid_get_value( bios_data, offset ); 96 | new_val = chksum_pmid_calc_value( bios_data, offset ); 97 | printf( "\nPMID entry at: 0x%4lX\n", offset ); 98 | printf( "Current checksum: 0x%02X\n", cur_val ); 99 | printf( "Calculated checksum: 0x%02X ", new_val ); 100 | hits++; 101 | } 102 | if ((hits == 1) && (cur_val != new_val)) { 103 | printf("Setting checksum."); 104 | chksum_pmid_set_value( bios_data, offset, new_val ); 105 | if (modified == 0) { 106 | bios_len += 0x200; 107 | bios_data[2]++; 108 | } 109 | modified = 1; 110 | } 111 | if (hits >= 2) { 112 | printf( "Multiple PMID entries! No checksum set." ); 113 | } 114 | if (hits) { 115 | printf("\n"); 116 | } 117 | 118 | offset = 0L; 119 | pcir_offset = chksum_pcir_get_offset( bios_data, offset ); 120 | if (pcir_offset != -1L) { 121 | if (bios_data[pcir_offset + 16] != bios_data[2]) { 122 | bios_data[pcir_offset + 16] = bios_data[2]; 123 | if (modified == 0) { 124 | bios_len += 0x200; 125 | bios_data[2]++; 126 | bios_data[pcir_offset + 16]++; 127 | } 128 | modified = 1; 129 | } 130 | } 131 | 132 | offset = 0L; 133 | do { 134 | offset = chksum_bios_get_offset(bios_data, offset); 135 | cur_val = chksum_bios_get_value(bios_data, offset); 136 | new_val = chksum_bios_calc_value(bios_data, offset); 137 | if ((cur_val != new_val) && (modified == 0)) { 138 | bios_len += 0x200; 139 | bios_data[2]++; 140 | if (pcir_offset != -1L) { 141 | bios_data[pcir_offset + 16]++; 142 | } 143 | modified = 1; 144 | } else { 145 | printf("\nBios checksum at: 0x%4lX\n", offset); 146 | printf("Current checksum: 0x%02X\n", cur_val); 147 | printf("Calculated checksum: 0x%02X ", new_val); 148 | if (cur_val != new_val) { 149 | printf("Setting checksum."); 150 | chksum_bios_set_value(bios_data, offset, new_val); 151 | cur_val = new_val; 152 | modified = 1; 153 | } 154 | printf( "\n" ); 155 | } 156 | } while (cur_val != new_val); 157 | 158 | if (modified == 1) { 159 | if ((stream = fopen( argv[1], "wb")) == NULL) { 160 | printf("Error opening %s for writing.\n", argv[1]); 161 | exit(EXIT_FAILURE); 162 | } 163 | if (fwrite(bios_data, 1, bios_len, stream) < bios_len) { 164 | printf("Error writing %d KBytes to %s.\n", bios_len / 1024, argv[1]); 165 | fclose(stream); 166 | exit(EXIT_FAILURE); 167 | } 168 | fclose(stream); 169 | } 170 | 171 | return (EXIT_SUCCESS); 172 | } 173 | 174 | 175 | void check( int okay, char* message ) { 176 | 177 | if( !okay ) { 178 | printf( "\n\nError. %s.\n", message ); 179 | exit( EXIT_FAILURE ); 180 | } 181 | } 182 | 183 | 184 | long chksum_bios_get_offset( byte* data, long offset ) { 185 | 186 | return (bios_len - 1); 187 | } 188 | 189 | 190 | byte chksum_bios_calc_value( byte* data, long offset ) { 191 | 192 | int i; 193 | byte sum; 194 | 195 | sum = 0; 196 | for( i = 0; i < offset; i++ ) { 197 | sum = sum + *( data + i ); 198 | } 199 | sum = -sum; /* iso ensures -s + s == 0 on unsigned types */ 200 | return( sum ); 201 | } 202 | 203 | 204 | byte chksum_bios_get_value( byte* data, long offset ) { 205 | 206 | return( *( data + offset ) ); 207 | } 208 | 209 | 210 | void chksum_bios_set_value( byte* data, long offset, byte value ) { 211 | 212 | *( data + offset ) = value; 213 | } 214 | 215 | 216 | byte chksum_pmid_calc_value( byte* data, long offset ) { 217 | 218 | int i; 219 | int len; 220 | byte sum; 221 | 222 | len = PMID_LEN; 223 | check((offset + len) <= (bios_len - 1), "PMID entry length out of bounds" ); 224 | sum = 0; 225 | for( i = 0; i < len; i++ ) { 226 | if( i != PMID_CHKSUM ) { 227 | sum = sum + *( data + offset + i ); 228 | } 229 | } 230 | sum = -sum; 231 | return( sum ); 232 | } 233 | 234 | 235 | long chksum_pmid_get_offset( byte* data, long offset ) { 236 | 237 | long result = -1L; 238 | 239 | while ((offset + PMID_LEN) < (bios_len - 1)) { 240 | offset = offset + 1; 241 | if( *( data + offset + 0 ) == 'P' && \ 242 | *( data + offset + 1 ) == 'M' && \ 243 | *( data + offset + 2 ) == 'I' && \ 244 | *( data + offset + 3 ) == 'D' ) { 245 | result = offset; 246 | break; 247 | } 248 | } 249 | return( result ); 250 | } 251 | 252 | 253 | byte chksum_pmid_get_value( byte* data, long offset ) { 254 | 255 | check((offset + PMID_CHKSUM) <= (bios_len - 1), "PMID checksum out of bounds" ); 256 | return( *( data + offset + PMID_CHKSUM ) ); 257 | } 258 | 259 | 260 | void chksum_pmid_set_value( byte* data, long offset, byte value ) { 261 | 262 | check((offset + PMID_CHKSUM) <= (bios_len - 1), "PMID checksum out of bounds" ); 263 | *( data + offset + PMID_CHKSUM ) = value; 264 | } 265 | 266 | 267 | long chksum_pcir_get_offset( byte* data, long offset ) { 268 | 269 | long result = -1L; 270 | 271 | while ((offset + PCIR_LEN) < (bios_len - 1)) { 272 | offset = offset + 1; 273 | if( *( data + offset + 0 ) == 'P' && \ 274 | *( data + offset + 1 ) == 'C' && \ 275 | *( data + offset + 2 ) == 'I' && \ 276 | *( data + offset + 3 ) == 'R' ) { 277 | result = offset; 278 | break; 279 | } 280 | } 281 | return( result ); 282 | } 283 | -------------------------------------------------------------------------------- /clext.c: -------------------------------------------------------------------------------- 1 | // 2 | // QEMU Cirrus CLGD 54xx VGABIOS Extension. 3 | // 4 | // Copyright (c) 2004 Makoto Suzuki (suzu) 5 | // 6 | // This library is free software; you can redistribute it and/or 7 | // modify it under the terms of the GNU Lesser General Public 8 | // License as published by the Free Software Foundation; either 9 | // version 2 of the License, or (at your option) any later version. 10 | // 11 | // This library is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | // Lesser General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU Lesser General Public 17 | // License along with this library; if not, write to the Free Software 18 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | // 20 | 21 | //#define CIRRUS_VESA3_PMINFO 22 | #ifdef VBE 23 | #undef CIRRUS_VESA3_PMINFO 24 | #endif 25 | 26 | #define PM_BIOSMEM_CURRENT_MODE 0x449 27 | #define PM_BIOSMEM_CRTC_ADDRESS 0x463 28 | #define PM_BIOSMEM_VBE_MODE 0x4BA 29 | 30 | typedef struct 31 | { 32 | /* + 0 */ 33 | unsigned short mode; 34 | unsigned short width; 35 | unsigned short height; 36 | unsigned short depth; 37 | /* + 8 */ 38 | unsigned short hidden_dac; /* 0x3c6 */ 39 | unsigned short *seq; /* 0x3c4 */ 40 | unsigned short *graph; /* 0x3ce */ 41 | unsigned short *crtc; /* 0x3d4 */ 42 | /* +16 */ 43 | unsigned char bitsperpixel; 44 | unsigned char vesacolortype; 45 | unsigned char vesaredmask; 46 | unsigned char vesaredpos; 47 | unsigned char vesagreenmask; 48 | unsigned char vesagreenpos; 49 | unsigned char vesabluemask; 50 | unsigned char vesabluepos; 51 | /* +24 */ 52 | unsigned char vesareservedmask; 53 | unsigned char vesareservedpos; 54 | } cirrus_mode_t; 55 | #define CIRRUS_MODE_SIZE 26 56 | 57 | 58 | /* For VESA BIOS 3.0 */ 59 | #define CIRRUS_PM16INFO_SIZE 20 60 | 61 | /* VGA */ 62 | unsigned short cseq_vga[] = {0x0007,0xffff}; 63 | unsigned short cgraph_vga[] = {0x0009,0x000a,0x000b,0xffff}; 64 | unsigned short ccrtc_vga[] = {0x001a,0x001b,0x001d,0xffff}; 65 | 66 | /* extensions */ 67 | unsigned short cgraph_svgacolor[] = { 68 | 0x0000,0x0001,0x0002,0x0003,0x0004,0x4005,0x0506,0x0f07,0xff08, 69 | 0x0009,0x000a,0x000b, 70 | 0xffff 71 | }; 72 | /* 640x480x8 */ 73 | unsigned short cseq_640x480x8[] = { 74 | 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107, 75 | 0x580b,0x580c,0x580d,0x580e, 76 | 0x0412,0x0013,0x2017, 77 | 0x331b,0x331c,0x331d,0x331e, 78 | 0xffff 79 | }; 80 | unsigned short ccrtc_640x480x8[] = { 81 | 0x2c11, 82 | 0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07, 83 | 0x4009,0x000c,0x000d, 84 | 0xea10,0xdf12,0x5013,0x4014,0xdf15,0x0b16,0xc317,0xff18, 85 | 0x001a,0x221b,0x001d, 86 | 0xffff 87 | }; 88 | /* 640x480x16 */ 89 | unsigned short cseq_640x480x16[] = { 90 | 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707, 91 | 0x580b,0x580c,0x580d,0x580e, 92 | 0x0412,0x0013,0x2017, 93 | 0x331b,0x331c,0x331d,0x331e, 94 | 0xffff 95 | }; 96 | unsigned short ccrtc_640x480x16[] = { 97 | 0x2c11, 98 | 0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07, 99 | 0x4009,0x000c,0x000d, 100 | 0xea10,0xdf12,0xa013,0x4014,0xdf15,0x0b16,0xc317,0xff18, 101 | 0x001a,0x221b,0x001d, 102 | 0xffff 103 | }; 104 | /* 640x480x24 */ 105 | unsigned short cseq_640x480x24[] = { 106 | 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507, 107 | 0x580b,0x580c,0x580d,0x580e, 108 | 0x0412,0x0013,0x2017, 109 | 0x331b,0x331c,0x331d,0x331e, 110 | 0xffff 111 | }; 112 | unsigned short ccrtc_640x480x24[] = { 113 | 0x2c11, 114 | 0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07, 115 | 0x4009,0x000c,0x000d, 116 | 0xea10,0xdf12,0x0013,0x4014,0xdf15,0x0b16,0xc317,0xff18, 117 | 0x001a,0x321b,0x001d, 118 | 0xffff 119 | }; 120 | /* 800x600x8 */ 121 | unsigned short cseq_800x600x8[] = { 122 | 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107, 123 | 0x230b,0x230c,0x230d,0x230e, 124 | 0x0412,0x0013,0x2017, 125 | 0x141b,0x141c,0x141d,0x141e, 126 | 0xffff 127 | }; 128 | unsigned short ccrtc_800x600x8[] = { 129 | 0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007, 130 | 0x6009,0x000c,0x000d, 131 | 0x7d10,0x5712,0x6413,0x4014,0x5715,0x9816,0xc317,0xff18, 132 | 0x001a,0x221b,0x001d, 133 | 0xffff 134 | }; 135 | /* 800x600x16 */ 136 | unsigned short cseq_800x600x16[] = { 137 | 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707, 138 | 0x230b,0x230c,0x230d,0x230e, 139 | 0x0412,0x0013,0x2017, 140 | 0x141b,0x141c,0x141d,0x141e, 141 | 0xffff 142 | }; 143 | unsigned short ccrtc_800x600x16[] = { 144 | 0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007, 145 | 0x6009,0x000c,0x000d, 146 | 0x7d10,0x5712,0xc813,0x4014,0x5715,0x9816,0xc317,0xff18, 147 | 0x001a,0x221b,0x001d, 148 | 0xffff 149 | }; 150 | /* 800x600x24 */ 151 | unsigned short cseq_800x600x24[] = { 152 | 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507, 153 | 0x230b,0x230c,0x230d,0x230e, 154 | 0x0412,0x0013,0x2017, 155 | 0x141b,0x141c,0x141d,0x141e, 156 | 0xffff 157 | }; 158 | unsigned short ccrtc_800x600x24[] = { 159 | 0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007, 160 | 0x6009,0x000c,0x000d, 161 | 0x7d10,0x5712,0x2c13,0x4014,0x5715,0x9816,0xc317,0xff18, 162 | 0x001a,0x321b,0x001d, 163 | 0xffff 164 | }; 165 | /* 1024x768x8 */ 166 | unsigned short cseq_1024x768x8[] = { 167 | 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107, 168 | 0x760b,0x760c,0x760d,0x760e, 169 | 0x0412,0x0013,0x2017, 170 | 0x341b,0x341c,0x341d,0x341e, 171 | 0xffff 172 | }; 173 | unsigned short ccrtc_1024x768x8[] = { 174 | 0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507, 175 | 0x6009,0x000c,0x000d, 176 | 0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18, 177 | 0x001a,0x221b,0x001d, 178 | 0xffff 179 | }; 180 | /* 1024x768x16 */ 181 | unsigned short cseq_1024x768x16[] = { 182 | 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707, 183 | 0x760b,0x760c,0x760d,0x760e, 184 | 0x0412,0x0013,0x2017, 185 | 0x341b,0x341c,0x341d,0x341e, 186 | 0xffff 187 | }; 188 | unsigned short ccrtc_1024x768x16[] = { 189 | 0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507, 190 | 0x6009,0x000c,0x000d, 191 | 0x0310,0xff12,0x0013,0x4014,0xff15,0x2416,0xc317,0xff18, 192 | 0x001a,0x321b,0x001d, 193 | 0xffff 194 | }; 195 | /* 1024x768x24 */ 196 | unsigned short cseq_1024x768x24[] = { 197 | 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507, 198 | 0x760b,0x760c,0x760d,0x760e, 199 | 0x0412,0x0013,0x2017, 200 | 0x341b,0x341c,0x341d,0x341e, 201 | 0xffff 202 | }; 203 | unsigned short ccrtc_1024x768x24[] = { 204 | 0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507, 205 | 0x6009,0x000c,0x000d, 206 | 0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18, 207 | 0x001a,0x321b,0x001d, 208 | 0xffff 209 | }; 210 | /* 1280x1024x8 */ 211 | unsigned short cseq_1280x1024x8[] = { 212 | 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107, 213 | 0x760b,0x760c,0x760d,0x760e, 214 | 0x0412,0x0013,0x2017, 215 | 0x341b,0x341c,0x341d,0x341e, 216 | 0xffff 217 | }; 218 | unsigned short ccrtc_1280x1024x8[] = { 219 | 0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707, 220 | 0x6009,0x000c,0x000d, 221 | 0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18, 222 | 0x001a,0x221b,0x001d, 223 | 0xffff 224 | }; 225 | /* 1280x1024x16 */ 226 | unsigned short cseq_1280x1024x16[] = { 227 | 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707, 228 | 0x760b,0x760c,0x760d,0x760e, 229 | 0x0412,0x0013,0x2017, 230 | 0x341b,0x341c,0x341d,0x341e, 231 | 0xffff 232 | }; 233 | unsigned short ccrtc_1280x1024x16[] = { 234 | 0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707, 235 | 0x6009,0x000c,0x000d, 236 | 0x0310,0xff12,0x4013,0x4014,0xff15,0x2416,0xc317,0xff18, 237 | 0x001a,0x321b,0x001d, 238 | 0xffff 239 | }; 240 | 241 | /* 1600x1200x8 */ 242 | unsigned short cseq_1600x1200x8[] = { 243 | 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107, 244 | 0x760b,0x760c,0x760d,0x760e, 245 | 0x0412,0x0013,0x2017, 246 | 0x341b,0x341c,0x341d,0x341e, 247 | 0xffff 248 | }; 249 | unsigned short ccrtc_1600x1200x8[] = { 250 | 0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707, 251 | 0x6009,0x000c,0x000d, 252 | 0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18, 253 | 0x001a,0x221b,0x001d, 254 | 0xffff 255 | }; 256 | 257 | cirrus_mode_t cirrus_modes[] = 258 | { 259 | {0x5f,640,480,8,0x00, 260 | cseq_640x480x8,cgraph_svgacolor,ccrtc_640x480x8,8, 261 | 4,0,0,0,0,0,0,0,0}, 262 | {0x64,640,480,16,0xe1, 263 | cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16, 264 | 6,5,11,6,5,5,0,0,0}, 265 | {0x66,640,480,15,0xf0, 266 | cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16, 267 | 6,5,10,5,5,5,0,1,15}, 268 | {0x71,640,480,24,0xe5, 269 | cseq_640x480x24,cgraph_svgacolor,ccrtc_640x480x24,24, 270 | 6,8,16,8,8,8,0,0,0}, 271 | 272 | {0x5c,800,600,8,0x00, 273 | cseq_800x600x8,cgraph_svgacolor,ccrtc_800x600x8,8, 274 | 4,0,0,0,0,0,0,0,0}, 275 | {0x65,800,600,16,0xe1, 276 | cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16, 277 | 6,5,11,6,5,5,0,0,0}, 278 | {0x67,800,600,15,0xf0, 279 | cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16, 280 | 6,5,10,5,5,5,0,1,15}, 281 | 282 | {0x60,1024,768,8,0x00, 283 | cseq_1024x768x8,cgraph_svgacolor,ccrtc_1024x768x8,8, 284 | 4,0,0,0,0,0,0,0,0}, 285 | {0x74,1024,768,16,0xe1, 286 | cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16, 287 | 6,5,11,6,5,5,0,0,0}, 288 | {0x68,1024,768,15,0xf0, 289 | cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16, 290 | 6,5,10,5,5,5,0,1,15}, 291 | 292 | {0x78,800,600,24,0xe5, 293 | cseq_800x600x24,cgraph_svgacolor,ccrtc_800x600x24,24, 294 | 6,8,16,8,8,8,0,0,0}, 295 | {0x79,1024,768,24,0xe5, 296 | cseq_1024x768x24,cgraph_svgacolor,ccrtc_1024x768x24,24, 297 | 6,8,16,8,8,8,0,0,0}, 298 | 299 | {0x6d,1280,1024,8,0x00, 300 | cseq_1280x1024x8,cgraph_svgacolor,ccrtc_1280x1024x8,8, 301 | 4,0,0,0,0,0,0,0,0}, 302 | {0x69,1280,1024,15,0xf0, 303 | cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16,16, 304 | 6,5,10,5,5,5,0,1,15}, 305 | {0x75,1280,1024,16,0xe1, 306 | cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16,16, 307 | 6,5,11,6,5,5,0,0,0}, 308 | 309 | {0x7b,1600,1200,8,0x00, 310 | cseq_1600x1200x8,cgraph_svgacolor,ccrtc_1600x1200x8,8, 311 | 4,0,0,0,0,0,0,0,0}, 312 | 313 | {0xfe,0,0,0,0,cseq_vga,cgraph_vga,ccrtc_vga,0, 314 | 0xff,0,0,0,0,0,0,0,0}, 315 | {0xff,0,0,0,0,0,0,0,0, 316 | 0xff,0,0,0,0,0,0,0,0}, 317 | }; 318 | 319 | unsigned char cirrus_id_table[] = { 320 | // 5430 321 | 0xA0, 0x32, 322 | // 5446 323 | 0xB8, 0x39, 324 | 325 | 0xff, 0xff 326 | }; 327 | 328 | 329 | unsigned short cirrus_vesa_modelist[] = { 330 | // 640x480x8 331 | 0x101, 0x5f, 332 | // 640x480x15 333 | 0x110, 0x66, 334 | // 640x480x16 335 | 0x111, 0x64, 336 | // 640x480x24 337 | 0x112, 0x71, 338 | // 800x600x8 339 | 0x103, 0x5c, 340 | // 800x600x15 341 | 0x113, 0x67, 342 | // 800x600x16 343 | 0x114, 0x65, 344 | // 800x600x24 345 | 0x115, 0x78, 346 | // 1024x768x8 347 | 0x105, 0x60, 348 | // 1024x768x15 349 | 0x116, 0x68, 350 | // 1024x768x16 351 | 0x117, 0x74, 352 | // 1024x768x24 353 | 0x118, 0x79, 354 | // 1280x1024x8 355 | 0x107, 0x6d, 356 | // 1280x1024x15 357 | 0x119, 0x69, 358 | // 1280x1024x16 359 | 0x11a, 0x75, 360 | // invalid 361 | 0xffff,0xffff 362 | }; 363 | 364 | 365 | ASM_START 366 | 367 | cirrus_installed: 368 | .ascii "cirrus-compatible VGA is detected" 369 | .byte 0x0d,0x0a 370 | .byte 0x0d,0x0a,0x00 371 | 372 | cirrus_not_installed: 373 | .ascii "cirrus-compatible VGA is not detected" 374 | .byte 0x0d,0x0a 375 | .byte 0x0d,0x0a,0x00 376 | 377 | cirrus_vesa_vendorname: 378 | cirrus_vesa_productname: 379 | cirrus_vesa_oemname: 380 | .ascii "VGABIOS Cirrus extension" 381 | .byte 0 382 | cirrus_vesa_productrevision: 383 | .ascii "1.0" 384 | .byte 0 385 | 386 | cirrus_init: 387 | call cirrus_check 388 | jnz no_cirrus 389 | SET_INT_VECTOR(0x10, #0xC000, #cirrus_int10_handler) 390 | mov al, #0x0f ; memory setup 391 | mov dx, #0x3C4 392 | out dx, al 393 | inc dx 394 | in al, dx 395 | and al, #0x18 396 | mov ah, al 397 | mov al, #0x0a 398 | dec dx 399 | out dx, ax 400 | mov ax, #0x0007 ; set vga mode 401 | out dx, ax 402 | mov ax, #0x0431 ; reset bitblt 403 | mov dx, #0x3CE 404 | out dx, ax 405 | mov ax, #0x0031 406 | out dx, ax 407 | no_cirrus: 408 | ret 409 | 410 | cirrus_display_info: 411 | push ds 412 | push si 413 | push cs 414 | pop ds 415 | call cirrus_check 416 | mov si, #cirrus_not_installed 417 | jnz cirrus_msgnotinstalled 418 | mov si, #cirrus_installed 419 | 420 | cirrus_msgnotinstalled: 421 | call _display_string 422 | pop si 423 | pop ds 424 | ret 425 | 426 | cirrus_check: 427 | push ax 428 | push dx 429 | mov ax, #0x9206 430 | mov dx, #0x3C4 431 | out dx, ax 432 | inc dx 433 | in al, dx 434 | cmp al, #0x12 435 | pop dx 436 | pop ax 437 | ret 438 | 439 | 440 | cirrus_int10_handler: 441 | pushf 442 | push bp 443 | cmp ah, #0x00 ;; set video mode 444 | jz cirrus_set_video_mode 445 | cmp ah, #0x12 ;; cirrus extension 446 | jz cirrus_extbios 447 | cmp ah, #0x4F ;; VESA extension 448 | jz cirrus_vesa 449 | 450 | cirrus_unhandled: 451 | pop bp 452 | popf 453 | jmp vgabios_int10_handler 454 | 455 | cirrus_return: 456 | #ifdef CIRRUS_DEBUG 457 | call cirrus_debug_dump 458 | #endif 459 | pop bp 460 | popf 461 | iret 462 | 463 | cirrus_set_video_mode: 464 | #ifdef CIRRUS_DEBUG 465 | call cirrus_debug_dump 466 | #endif 467 | push si 468 | push ax 469 | push bx 470 | push ds 471 | #ifdef CIRRUS_VESA3_PMINFO 472 | db 0x2e ;; cs: 473 | mov si, [cirrus_vesa_sel0000_data] 474 | #else 475 | xor si, si 476 | #endif 477 | mov ds, si 478 | xor bx, bx 479 | mov [PM_BIOSMEM_VBE_MODE], bx 480 | pop ds 481 | pop bx 482 | call cirrus_get_modeentry 483 | jnc cirrus_set_video_mode_extended 484 | mov al, #0xfe 485 | call cirrus_get_modeentry_nomask 486 | call cirrus_switch_mode 487 | pop ax 488 | pop si 489 | jmp cirrus_unhandled 490 | 491 | cirrus_extbios: 492 | #ifdef CIRRUS_DEBUG 493 | call cirrus_debug_dump 494 | #endif 495 | cmp bl, #0x80 496 | jb cirrus_unhandled 497 | cmp bl, #0xAF 498 | ja cirrus_unhandled 499 | push bx 500 | and bx, #0x7F 501 | shl bx, 1 502 | db 0x2e ;; cs: 503 | mov bp, cirrus_extbios_handlers[bx] 504 | pop bx 505 | push #cirrus_return 506 | push bp 507 | ret 508 | 509 | cirrus_vesa: 510 | #ifdef CIRRUS_DEBUG 511 | call cirrus_debug_dump 512 | #endif 513 | cmp al, #0x10 514 | ja cirrus_vesa_not_handled 515 | push bx 516 | xor bx, bx 517 | mov bl, al 518 | shl bx, 1 519 | db 0x2e ;; cs: 520 | mov bp, cirrus_vesa_handlers[bx] 521 | pop bx 522 | push #cirrus_return 523 | push bp 524 | ret 525 | 526 | cirrus_vesa_not_handled: 527 | mov ax, #0x014F ;; not implemented 528 | jmp cirrus_return 529 | 530 | #ifdef CIRRUS_DEBUG 531 | cirrus_debug_dump: 532 | push es 533 | push ds 534 | pusha 535 | push cs 536 | pop ds 537 | call _cirrus_debugmsg 538 | popa 539 | pop ds 540 | pop es 541 | ret 542 | #endif 543 | 544 | cirrus_set_video_mode_extended: 545 | call cirrus_switch_mode 546 | pop ax ;; mode 547 | test al, #0x80 548 | jnz cirrus_set_video_mode_extended_1 549 | push ax 550 | mov ax, #0xffff ; set to 0xff to keep win 2K happy 551 | call cirrus_clear_vram 552 | pop ax 553 | cirrus_set_video_mode_extended_1: 554 | and al, #0x7f 555 | 556 | push ds 557 | #ifdef CIRRUS_VESA3_PMINFO 558 | db 0x2e ;; cs: 559 | mov si, [cirrus_vesa_sel0000_data] 560 | #else 561 | xor si, si 562 | #endif 563 | mov ds, si 564 | mov [PM_BIOSMEM_CURRENT_MODE], al 565 | pop ds 566 | 567 | mov al, #0x20 568 | 569 | pop si 570 | jmp cirrus_return 571 | 572 | cirrus_vesa_pmbios_init: 573 | retf 574 | cirrus_vesa_pmbios_entry: 575 | pushf 576 | push bp 577 | cmp ah, #0x4F 578 | jnz cirrus_vesa_pmbios_unimplemented 579 | cmp al, #0x0F 580 | ja cirrus_vesa_pmbios_unimplemented 581 | push bx 582 | xor bx, bx 583 | mov bl, al 584 | shl bx, 1 585 | db 0x2e ;; cs: 586 | mov bp, cirrus_vesa_handlers[bx] 587 | pop bx 588 | push #cirrus_vesa_pmbios_return 589 | push bp 590 | ret 591 | cirrus_vesa_pmbios_unimplemented: 592 | mov ax, #0x014F 593 | cirrus_vesa_pmbios_return: 594 | pop bp 595 | popf 596 | retf 597 | 598 | ; in si:mode table 599 | cirrus_switch_mode: 600 | push ds 601 | push bx 602 | push dx 603 | push cs 604 | pop ds 605 | 606 | mov bx, [si+10] ;; seq 607 | mov dx, #0x3c4 608 | mov ax, #0x1206 609 | out dx, ax ;; Unlock cirrus special 610 | call cirrus_switch_mode_setregs 611 | 612 | mov bx, [si+12] ;; graph 613 | mov dx, #0x3ce 614 | call cirrus_switch_mode_setregs 615 | 616 | mov bx, [si+14] ;; crtc 617 | call cirrus_get_crtc 618 | call cirrus_switch_mode_setregs 619 | 620 | mov dx, #0x3c6 621 | mov al, #0x00 622 | out dx, al 623 | in al, dx 624 | in al, dx 625 | in al, dx 626 | in al, dx 627 | mov al, [si+8] ;; hidden dac 628 | out dx, al 629 | mov al, #0xff 630 | out dx, al 631 | 632 | mov al, #0x00 633 | mov bl, [si+17] ;; memory model 634 | or bl, bl 635 | jz is_text_mode 636 | mov al, #0x01 637 | cmp bl, #0x03 638 | jnz is_text_mode 639 | or al, #0x40 640 | is_text_mode: 641 | mov bl, #0x10 642 | call biosfn_get_single_palette_reg 643 | and bh, #0xfe 644 | or bh, al 645 | call biosfn_set_single_palette_reg 646 | 647 | pop dx 648 | pop bx 649 | pop ds 650 | ret 651 | 652 | cirrus_enable_16k_granularity: 653 | push ax 654 | push dx 655 | mov dx, #0x3ce 656 | mov al, #0x0b 657 | out dx, al 658 | inc dx 659 | in al, dx 660 | or al, #0x20 ;; enable 16k 661 | out dx, al 662 | pop dx 663 | pop ax 664 | ret 665 | 666 | cirrus_switch_mode_setregs: 667 | csms_1: 668 | mov ax, [bx] 669 | cmp ax, #0xffff 670 | jz csms_2 671 | out dx, ax 672 | add bx, #0x2 673 | jmp csms_1 674 | csms_2: 675 | ret 676 | 677 | cirrus_extbios_80h: 678 | push dx 679 | call cirrus_get_crtc 680 | mov al, #0x27 681 | out dx, al 682 | inc dx 683 | in al, dx 684 | mov bx, #_cirrus_id_table 685 | c80h_1: 686 | db 0x2e ;; cs: 687 | mov ah, [bx] 688 | cmp ah, al 689 | jz c80h_2 690 | cmp ah, #0xff 691 | jz c80h_2 692 | inc bx 693 | inc bx 694 | jmp c80h_1 695 | c80h_2: 696 | db 0x2e ;; cs: 697 | mov al, 0x1[bx] 698 | pop dx 699 | mov ah, #0x00 700 | xor bx, bx 701 | ret 702 | 703 | cirrus_extbios_81h: 704 | mov ax, #0x100 ;; XXX 705 | ret 706 | cirrus_extbios_82h: 707 | push dx 708 | call cirrus_get_crtc 709 | xor ax, ax 710 | mov al, #0x27 711 | out dx, al 712 | inc dx 713 | in al, dx 714 | and al, #0x03 715 | mov ah, #0xAF 716 | pop dx 717 | ret 718 | 719 | cirrus_extbios_85h: 720 | push cx 721 | push dx 722 | mov dx, #0x3C4 723 | mov al, #0x0f ;; get DRAM band width 724 | out dx, al 725 | inc dx 726 | in al, dx 727 | ;; al = 4 << bandwidth 728 | mov cl, al 729 | shr cl, #0x03 730 | and cl, #0x03 731 | cmp cl, #0x03 732 | je c85h2 733 | mov al, #0x04 734 | shl al, cl 735 | jmp c85h3 736 | c85h2: 737 | ;; 4MB or 2MB 738 | and al, #0x80 739 | mov al, #0x20 ;; 2 MB 740 | je c85h3 741 | mov al, #0x40 ;; 4 MB 742 | c85h3: 743 | pop dx 744 | pop cx 745 | ret 746 | 747 | cirrus_extbios_9Ah: 748 | mov ax, #0x4060 749 | mov cx, #0x1132 750 | ret 751 | 752 | cirrus_extbios_A0h: 753 | call cirrus_get_modeentry 754 | mov ah, #0x01 755 | sbb ah, #0x00 756 | mov bx, cirrus_extbios_A0h_callback 757 | mov si, #0xffff 758 | mov di, bx 759 | mov ds, bx 760 | mov es, bx 761 | ret 762 | 763 | cirrus_extbios_A0h_callback: 764 | ;; fatal: not implemented yet 765 | cli 766 | hlt 767 | retf 768 | 769 | cirrus_extbios_A1h: 770 | mov bx, #0x0E00 ;; IBM 8512/8513, color 771 | ret 772 | 773 | cirrus_extbios_A2h: 774 | mov al, #0x07 ;; HSync 31.5 - 64.0 kHz 775 | ret 776 | 777 | cirrus_extbios_AEh: 778 | mov al, #0x01 ;; High Refresh 75Hz 779 | ret 780 | 781 | cirrus_extbios_unimplemented: 782 | ret 783 | 784 | cirrus_vesa_00h: 785 | push ds 786 | push si 787 | mov bp, di 788 | push es 789 | pop ds 790 | cld 791 | mov ax, [di] 792 | cmp ax, #0x4256 ;; VB 793 | jnz cv00_1 794 | mov ax, [di+2] 795 | cmp ax, #0x3245 ;; E2 796 | jnz cv00_1 797 | ;; VBE2 798 | lea di, 0x14[bp] 799 | mov ax, #0x0100 ;; soft ver. 800 | stosw 801 | mov ax, # cirrus_vesa_vendorname 802 | stosw 803 | mov ax, cs 804 | stosw 805 | mov ax, # cirrus_vesa_productname 806 | stosw 807 | mov ax, cs 808 | stosw 809 | mov ax, # cirrus_vesa_productrevision 810 | stosw 811 | mov ax, cs 812 | stosw 813 | cv00_1: 814 | mov di, bp 815 | mov ax, #0x4556 ;; VE 816 | stosw 817 | mov ax, #0x4153 ;; SA 818 | stosw 819 | mov ax, #0x0200 ;; v2.00 820 | stosw 821 | mov ax, # cirrus_vesa_oemname 822 | stosw 823 | mov ax, cs 824 | stosw 825 | xor ax, ax ;; caps 826 | stosw 827 | stosw 828 | lea ax, 0x40[bp] 829 | stosw 830 | mov ax, es 831 | stosw 832 | call cirrus_extbios_85h ;; vram in 64k 833 | mov ah, #0x00 834 | stosw 835 | 836 | push cs 837 | pop ds 838 | lea di, 0x40[bp] 839 | mov si, #_cirrus_vesa_modelist 840 | cv00_2: 841 | lodsw 842 | stosw 843 | add si, #2 844 | cmp ax, #0xffff 845 | jnz cv00_2 846 | 847 | mov ax, #0x004F 848 | mov di, bp 849 | pop si 850 | pop ds 851 | ret 852 | 853 | cirrus_vesa_01h: 854 | mov ax, cx 855 | and ax, #0x3fff 856 | call cirrus_vesamode_to_mode 857 | cmp ax, #0xffff 858 | jnz cirrus_vesa_01h_1 859 | jmp cirrus_vesa_unimplemented 860 | cirrus_vesa_01h_1: 861 | push ds 862 | push si 863 | push cx 864 | push dx 865 | push bx 866 | mov bp, di 867 | cld 868 | push cs 869 | pop ds 870 | call cirrus_get_modeentry_nomask 871 | 872 | push di 873 | xor ax, ax 874 | mov cx, #0x80 875 | rep 876 | stosw ;; clear buffer 877 | pop di 878 | 879 | mov ax, #0x003b ;; mode 880 | stosw 881 | mov ax, #0x0007 ;; attr 882 | stosw 883 | mov ax, #0x0010 ;; granularity =16K 884 | stosw 885 | mov ax, #0x0040 ;; size =64K 886 | stosw 887 | mov ax, #0xA000 ;; segment A 888 | stosw 889 | xor ax, ax ;; no segment B 890 | stosw 891 | mov ax, #cirrus_vesa_05h_farentry 892 | stosw 893 | mov ax, cs 894 | stosw 895 | call cirrus_get_line_offset_entry 896 | stosw ;; bytes per scan line 897 | mov ax, [si+2] ;; width 898 | stosw 899 | mov ax, [si+4] ;; height 900 | stosw 901 | mov ax, #0x08 902 | stosb 903 | mov ax, #0x10 904 | stosb 905 | mov al, #1 ;; count of planes 906 | stosb 907 | mov al, [si+6] ;; bpp 908 | stosb 909 | mov al, #0x1 ;; XXX number of banks 910 | stosb 911 | mov al, [si+17] 912 | stosb ;; memory model 913 | mov al, #0x0 ;; XXX size of bank in K 914 | stosb 915 | call cirrus_get_line_offset_entry 916 | mov bx, [si+4] 917 | mul bx ;; dx:ax=vramdisp 918 | or ax, ax 919 | jz cirrus_vesa_01h_3 920 | inc dx 921 | cirrus_vesa_01h_3: 922 | call cirrus_extbios_85h ;; al=vram in 64k 923 | mov ah, #0x00 924 | mov cx, dx 925 | xor dx, dx 926 | div cx 927 | dec ax 928 | stosb ;; number of image pages = vramtotal/vramdisp-1 929 | mov al, #0x00 930 | stosb 931 | 932 | ;; v1.2+ stuffs 933 | push si 934 | add si, #18 935 | movsw 936 | movsw 937 | movsw 938 | movsw 939 | pop si 940 | 941 | mov ah, [si+16] 942 | mov al, #0x0 943 | sub ah, #9 944 | rcl al, #1 ; bit 0=palette flag 945 | stosb ;; direct screen mode info 946 | 947 | ;; v2.0+ stuffs 948 | ;; 32-bit LFB address 949 | xor ax, ax 950 | stosw 951 | mov ax, #0x1013 ;; vendor Cirrus 952 | call _pci_get_lfb_addr 953 | stosw 954 | or ax, ax 955 | jz cirrus_vesa_01h_4 956 | push di 957 | mov di, bp 958 | db 0x26 ;; es: 959 | mov ax, [di] 960 | or ax, #0x0080 ;; mode bit 7:LFB 961 | stosw 962 | pop di 963 | cirrus_vesa_01h_4: 964 | 965 | xor ax, ax 966 | stosw ; reserved 967 | stosw ; reserved 968 | stosw ; reserved 969 | 970 | mov ax, #0x004F 971 | mov di, bp 972 | pop bx 973 | pop dx 974 | pop cx 975 | pop si 976 | pop ds 977 | 978 | test cx, #0x4000 ;; LFB flag 979 | jz cirrus_vesa_01h_5 980 | push cx 981 | db 0x26 ;; es: 982 | mov cx, [di] 983 | cmp cx, #0x0080 ;; is LFB supported? 984 | jnz cirrus_vesa_01h_6 985 | mov ax, #0x014F ;; error - no LFB 986 | cirrus_vesa_01h_6: 987 | pop cx 988 | cirrus_vesa_01h_5: 989 | ret 990 | 991 | cirrus_vesa_02h: 992 | ;; XXX support CRTC registers 993 | test bx, #0x3e00 994 | jnz cirrus_vesa_02h_2 ;; unknown flags 995 | mov ax, bx 996 | and ax, #0x1ff ;; bit 8-0 mode 997 | cmp ax, #0x100 ;; legacy VGA mode 998 | jb cirrus_vesa_02h_legacy 999 | call cirrus_vesamode_to_mode 1000 | cmp ax, #0xffff 1001 | jnz cirrus_vesa_02h_1 1002 | cirrus_vesa_02h_2: 1003 | jmp cirrus_vesa_unimplemented 1004 | cirrus_vesa_02h_legacy: 1005 | #ifdef CIRRUS_VESA3_PMINFO 1006 | db 0x2e ;; cs: 1007 | cmp byte ptr [cirrus_vesa_is_protected_mode], #0 1008 | jnz cirrus_vesa_02h_2 1009 | #endif // CIRRUS_VESA3_PMINFO 1010 | int #0x10 1011 | mov ax, #0x004F 1012 | ret 1013 | cirrus_vesa_02h_1: 1014 | push si 1015 | push ax 1016 | call cirrus_get_modeentry_nomask 1017 | call cirrus_switch_mode 1018 | test bx, #0x4000 ;; LFB 1019 | jnz cirrus_vesa_02h_3 1020 | call cirrus_enable_16k_granularity 1021 | cirrus_vesa_02h_3: 1022 | test bx, #0x8000 ;; no clear 1023 | jnz cirrus_vesa_02h_4 1024 | push ax 1025 | xor ax,ax 1026 | call cirrus_clear_vram 1027 | pop ax 1028 | cirrus_vesa_02h_4: 1029 | pop ax 1030 | push ds 1031 | #ifdef CIRRUS_VESA3_PMINFO 1032 | db 0x2e ;; cs: 1033 | mov si, [cirrus_vesa_sel0000_data] 1034 | #else 1035 | xor si, si 1036 | #endif 1037 | mov ds, si 1038 | mov [PM_BIOSMEM_CURRENT_MODE], al 1039 | mov [PM_BIOSMEM_VBE_MODE], bx 1040 | pop ds 1041 | pop si 1042 | mov ax, #0x004F 1043 | ret 1044 | 1045 | cirrus_vesa_03h: 1046 | push ds 1047 | #ifdef CIRRUS_VESA3_PMINFO 1048 | db 0x2e ;; cs: 1049 | mov ax, [cirrus_vesa_sel0000_data] 1050 | #else 1051 | xor ax, ax 1052 | #endif 1053 | mov ds, ax 1054 | mov bx, # PM_BIOSMEM_VBE_MODE 1055 | mov ax, [bx] 1056 | mov bx, ax 1057 | test bx, bx 1058 | jnz cirrus_vesa_03h_1 1059 | mov bx, # PM_BIOSMEM_CURRENT_MODE 1060 | mov al, [bx] 1061 | mov bl, al 1062 | xor bh, bh 1063 | cirrus_vesa_03h_1: 1064 | mov ax, #0x004f 1065 | pop ds 1066 | ret 1067 | 1068 | cirrus_vesa_05h_farentry: 1069 | call cirrus_vesa_05h 1070 | retf 1071 | 1072 | cirrus_vesa_05h: 1073 | cmp bl, #0x01 1074 | ja cirrus_vesa_05h_1 1075 | cmp bh, #0x00 1076 | jz cirrus_vesa_05h_setmempage 1077 | cmp bh, #0x01 1078 | jz cirrus_vesa_05h_getmempage 1079 | cirrus_vesa_05h_1: 1080 | jmp cirrus_vesa_unimplemented 1081 | cirrus_vesa_05h_setmempage: 1082 | or dh, dh ; address must be < 0x100 1083 | jnz cirrus_vesa_05h_1 1084 | push dx 1085 | mov al, bl ;; bl=bank number 1086 | add al, #0x09 1087 | mov ah, dl ;; dx=window address in granularity 1088 | mov dx, #0x3ce 1089 | out dx, ax 1090 | pop dx 1091 | mov ax, #0x004F 1092 | ret 1093 | cirrus_vesa_05h_getmempage: 1094 | mov al, bl ;; bl=bank number 1095 | add al, #0x09 1096 | mov dx, #0x3ce 1097 | out dx, al 1098 | inc dx 1099 | in al, dx 1100 | xor dx, dx 1101 | mov dl, al ;; dx=window address in granularity 1102 | mov ax, #0x004F 1103 | ret 1104 | 1105 | cirrus_vesa_06h: 1106 | mov ax, cx 1107 | cmp bl, #0x01 1108 | je cirrus_vesa_06h_3 1109 | cmp bl, #0x02 1110 | je cirrus_vesa_06h_2 1111 | jb cirrus_vesa_06h_1 1112 | mov ax, #0x0100 1113 | ret 1114 | cirrus_vesa_06h_1: 1115 | call cirrus_get_bpp_bytes 1116 | mov bl, al 1117 | xor bh, bh 1118 | mov ax, cx 1119 | mul bx 1120 | cirrus_vesa_06h_2: 1121 | call cirrus_set_line_offset 1122 | cirrus_vesa_06h_3: 1123 | call cirrus_get_bpp_bytes 1124 | mov bl, al 1125 | xor bh, bh 1126 | xor dx, dx 1127 | call cirrus_get_line_offset 1128 | push ax 1129 | div bx 1130 | mov cx, ax 1131 | pop bx 1132 | call cirrus_extbios_85h ;; al=vram in 64k 1133 | xor dx, dx 1134 | mov dl, al 1135 | xor ax, ax 1136 | div bx 1137 | mov dx, ax 1138 | mov ax, #0x004f 1139 | ret 1140 | 1141 | cirrus_vesa_07h: 1142 | cmp bl, #0x80 1143 | je cirrus_vesa_07h_1 1144 | cmp bl, #0x01 1145 | je cirrus_vesa_07h_2 1146 | jb cirrus_vesa_07h_1 1147 | mov ax, #0x0100 1148 | ret 1149 | cirrus_vesa_07h_1: 1150 | push dx 1151 | call cirrus_get_bpp_bytes 1152 | mov bl, al 1153 | xor bh, bh 1154 | mov ax, cx 1155 | mul bx 1156 | pop bx 1157 | push ax 1158 | call cirrus_get_line_offset 1159 | mul bx 1160 | pop bx 1161 | add ax, bx 1162 | jnc cirrus_vesa_07h_3 1163 | inc dx 1164 | cirrus_vesa_07h_3: 1165 | push dx 1166 | and dx, #0x0003 1167 | mov bx, #0x04 1168 | div bx 1169 | pop dx 1170 | shr dx, #2 1171 | call cirrus_set_start_addr 1172 | mov ax, #0x004f 1173 | ret 1174 | cirrus_vesa_07h_2: 1175 | call cirrus_get_start_addr 1176 | shl dx, #2 1177 | push dx 1178 | mov bx, #0x04 1179 | mul bx 1180 | pop bx 1181 | or dx, bx 1182 | push ax 1183 | call cirrus_get_line_offset 1184 | mov bx, ax 1185 | pop ax 1186 | div bx 1187 | push ax 1188 | push dx 1189 | call cirrus_get_bpp_bytes 1190 | mov bl, al 1191 | xor bh, bh 1192 | pop ax 1193 | xor dx, dx 1194 | div bx 1195 | mov cx, ax 1196 | pop dx 1197 | mov ax, #0x004f 1198 | ret 1199 | 1200 | cirrus_vesa_10h: 1201 | cmp bl, #0x00 1202 | jne cirrus_vesa_10h_01 1203 | mov bx, #0x0f30 1204 | mov ax, #0x004f 1205 | ret 1206 | cirrus_vesa_10h_01: 1207 | cmp bl, #0x01 1208 | jne cirrus_vesa_10h_02 1209 | push dx 1210 | push ds 1211 | mov dx, #0x40 1212 | mov ds, dx 1213 | mov [0xb9], bh 1214 | pop ds 1215 | pop dx 1216 | mov ax, #0x004f 1217 | ret 1218 | cirrus_vesa_10h_02: 1219 | cmp bl, #0x02 1220 | jne cirrus_vesa_unimplemented 1221 | push dx 1222 | push ds 1223 | mov dx, #0x40 1224 | mov ds, dx 1225 | mov bh, [0xb9] 1226 | pop ds 1227 | pop dx 1228 | mov ax, #0x004f 1229 | ret 1230 | 1231 | cirrus_vesa_unimplemented: 1232 | mov ax, #0x014F ;; not implemented 1233 | ret 1234 | 1235 | 1236 | ;; in ax:vesamode, out ax:cirrusmode 1237 | cirrus_vesamode_to_mode: 1238 | push ds 1239 | push cx 1240 | push si 1241 | push cs 1242 | pop ds 1243 | mov cx, #0xffff 1244 | mov si, #_cirrus_vesa_modelist 1245 | cvtm_1: 1246 | cmp [si],ax 1247 | jz cvtm_2 1248 | cmp [si],cx 1249 | jz cvtm_2 1250 | add si, #4 1251 | jmp cvtm_1 1252 | cvtm_2: 1253 | mov ax,[si+2] 1254 | pop si 1255 | pop cx 1256 | pop ds 1257 | ret 1258 | 1259 | ; cirrus_get_crtc 1260 | ;; NOTE - may be called in protected mode 1261 | cirrus_get_crtc: 1262 | push ds 1263 | push ax 1264 | mov dx, #0x3cc 1265 | in al, dx 1266 | and al, #0x01 1267 | shl al, #5 1268 | mov dx, #0x3b4 1269 | add dl, al 1270 | pop ax 1271 | pop ds 1272 | ret 1273 | 1274 | ;; in - al:mode, out - cflag:result, si:table, ax:destroyed 1275 | cirrus_get_modeentry: 1276 | and al, #0x7f 1277 | cirrus_get_modeentry_nomask: 1278 | mov si, #_cirrus_modes 1279 | cgm_1: 1280 | db 0x2e ;; cs: 1281 | mov ah, [si] 1282 | cmp al, ah 1283 | jz cgm_2 1284 | cmp ah, #0xff 1285 | jz cgm_4 1286 | add si, # CIRRUS_MODE_SIZE 1287 | jmp cgm_1 1288 | cgm_4: 1289 | xor si, si 1290 | stc ;; video mode is not supported 1291 | jmp cgm_3 1292 | cgm_2: 1293 | clc ;; video mode is supported 1294 | cgm_3: 1295 | ret 1296 | 1297 | ;; out - al:bytes per pixel 1298 | cirrus_get_bpp_bytes: 1299 | push dx 1300 | mov dx, #0x03c4 1301 | mov al, #0x07 1302 | out dx, al 1303 | inc dx 1304 | in al, dx 1305 | and al, #0x0e 1306 | cmp al, #0x06 1307 | jne cirrus_get_bpp_bytes_1 1308 | and al, #0x02 1309 | cirrus_get_bpp_bytes_1: 1310 | shr al, #1 1311 | cmp al, #0x04 1312 | je cirrus_get_bpp_bytes_2 1313 | inc al 1314 | cirrus_get_bpp_bytes_2: 1315 | pop dx 1316 | ret 1317 | 1318 | ;; in - ax: new line offset 1319 | cirrus_set_line_offset: 1320 | shr ax, #3 1321 | push ax 1322 | call cirrus_get_crtc 1323 | mov al, #0x13 1324 | out dx, al 1325 | inc dx 1326 | pop ax 1327 | out dx, al 1328 | dec dx 1329 | mov al, #0x1b 1330 | out dx, al 1331 | inc dx 1332 | shl ah, #4 1333 | in al, dx 1334 | and al, #ef 1335 | or al, ah 1336 | out dx, al 1337 | ret 1338 | 1339 | ;; out - ax: active line offset 1340 | cirrus_get_line_offset: 1341 | push dx 1342 | push bx 1343 | call cirrus_get_crtc 1344 | mov al, #0x13 1345 | out dx, al 1346 | inc dx 1347 | in al, dx 1348 | mov bl, al 1349 | dec dx 1350 | mov al, #0x1b 1351 | out dx, al 1352 | inc dx 1353 | in al, dx 1354 | mov ah, al 1355 | shr ah, #4 1356 | and ah, #0x01 1357 | mov al, bl 1358 | shl ax, #3 1359 | pop bx 1360 | pop dx 1361 | ret 1362 | 1363 | ;; in - si: table 1364 | ;; out - ax: line offset for mode 1365 | cirrus_get_line_offset_entry: 1366 | push bx 1367 | mov bx, [si+14] ;; crtc table 1368 | push bx 1369 | offset_loop1: 1370 | mov ax, [bx] 1371 | cmp al, #0x13 1372 | je offset_found1 1373 | inc bx 1374 | inc bx 1375 | jnz offset_loop1 1376 | offset_found1: 1377 | xor al, al 1378 | shr ax, #5 1379 | pop bx 1380 | push ax 1381 | offset_loop2: 1382 | mov ax, [bx] 1383 | cmp al, #0x1b 1384 | je offset_found2 1385 | inc bx 1386 | inc bx 1387 | jnz offset_loop2 1388 | offset_found2: 1389 | pop bx 1390 | and ax, #0x1000 1391 | shr ax, #1 1392 | or ax, bx 1393 | pop bx 1394 | ret 1395 | 1396 | ;; in - new address in DX:AX 1397 | cirrus_set_start_addr: 1398 | push bx 1399 | push dx 1400 | push ax 1401 | call cirrus_get_crtc 1402 | mov al, #0x0d 1403 | out dx, al 1404 | inc dx 1405 | pop ax 1406 | out dx, al 1407 | dec dx 1408 | mov al, #0x0c 1409 | out dx, al 1410 | inc dx 1411 | mov al, ah 1412 | out dx, al 1413 | dec dx 1414 | mov al, #0x1d 1415 | out dx, al 1416 | inc dx 1417 | in al, dx 1418 | and al, #0x7f 1419 | pop bx 1420 | mov ah, bl 1421 | shl bl, #4 1422 | and bl, #0x80 1423 | or al, bl 1424 | out dx, al 1425 | dec dx 1426 | mov bl, ah 1427 | and ah, #0x01 1428 | shl bl, #1 1429 | and bl, #0x0c 1430 | or ah, bl 1431 | mov al, #0x1b 1432 | out dx, al 1433 | inc dx 1434 | in al, dx 1435 | and al, #0xf2 1436 | or al, ah 1437 | out dx, al 1438 | pop bx 1439 | ret 1440 | 1441 | ;; out - current address in DX:AX 1442 | cirrus_get_start_addr: 1443 | push bx 1444 | call cirrus_get_crtc 1445 | mov al, #0x0c 1446 | out dx, al 1447 | inc dx 1448 | in al, dx 1449 | mov ah, al 1450 | dec dx 1451 | mov al, #0x0d 1452 | out dx, al 1453 | inc dx 1454 | in al, dx 1455 | push ax 1456 | dec dx 1457 | mov al, #0x1b 1458 | out dx, al 1459 | inc dx 1460 | in al, dx 1461 | dec dx 1462 | mov bl, al 1463 | and al, #0x01 1464 | and bl, #0x0c 1465 | shr bl, #1 1466 | or bl, al 1467 | mov al, #0x1d 1468 | out dx, al 1469 | inc dx 1470 | in al, dx 1471 | and al, #0x80 1472 | shr al, #4 1473 | or bl, al 1474 | mov dl, bl 1475 | xor dh, dh 1476 | pop ax 1477 | pop bx 1478 | ret 1479 | 1480 | cirrus_clear_vram: 1481 | pusha 1482 | push es 1483 | mov si, ax 1484 | 1485 | call cirrus_enable_16k_granularity 1486 | call cirrus_extbios_85h 1487 | shl al, #2 1488 | mov bl, al 1489 | xor ah,ah 1490 | cirrus_clear_vram_1: 1491 | mov al, #0x09 1492 | mov dx, #0x3ce 1493 | out dx, ax 1494 | push ax 1495 | mov cx, #0xa000 1496 | mov es, cx 1497 | xor di, di 1498 | mov ax, si 1499 | mov cx, #8192 1500 | cld 1501 | rep 1502 | stosw 1503 | pop ax 1504 | inc ah 1505 | cmp ah, bl 1506 | jne cirrus_clear_vram_1 1507 | 1508 | xor ah,ah 1509 | mov dx, #0x3ce 1510 | out dx, ax 1511 | 1512 | pop es 1513 | popa 1514 | ret 1515 | 1516 | cirrus_extbios_handlers: 1517 | ;; 80h 1518 | dw cirrus_extbios_80h 1519 | dw cirrus_extbios_81h 1520 | dw cirrus_extbios_82h 1521 | dw cirrus_extbios_unimplemented 1522 | ;; 84h 1523 | dw cirrus_extbios_unimplemented 1524 | dw cirrus_extbios_85h 1525 | dw cirrus_extbios_unimplemented 1526 | dw cirrus_extbios_unimplemented 1527 | ;; 88h 1528 | dw cirrus_extbios_unimplemented 1529 | dw cirrus_extbios_unimplemented 1530 | dw cirrus_extbios_unimplemented 1531 | dw cirrus_extbios_unimplemented 1532 | ;; 8Ch 1533 | dw cirrus_extbios_unimplemented 1534 | dw cirrus_extbios_unimplemented 1535 | dw cirrus_extbios_unimplemented 1536 | dw cirrus_extbios_unimplemented 1537 | ;; 90h 1538 | dw cirrus_extbios_unimplemented 1539 | dw cirrus_extbios_unimplemented 1540 | dw cirrus_extbios_unimplemented 1541 | dw cirrus_extbios_unimplemented 1542 | ;; 94h 1543 | dw cirrus_extbios_unimplemented 1544 | dw cirrus_extbios_unimplemented 1545 | dw cirrus_extbios_unimplemented 1546 | dw cirrus_extbios_unimplemented 1547 | ;; 98h 1548 | dw cirrus_extbios_unimplemented 1549 | dw cirrus_extbios_unimplemented 1550 | dw cirrus_extbios_9Ah 1551 | dw cirrus_extbios_unimplemented 1552 | ;; 9Ch 1553 | dw cirrus_extbios_unimplemented 1554 | dw cirrus_extbios_unimplemented 1555 | dw cirrus_extbios_unimplemented 1556 | dw cirrus_extbios_unimplemented 1557 | ;; A0h 1558 | dw cirrus_extbios_A0h 1559 | dw cirrus_extbios_A1h 1560 | dw cirrus_extbios_A2h 1561 | dw cirrus_extbios_unimplemented 1562 | ;; A4h 1563 | dw cirrus_extbios_unimplemented 1564 | dw cirrus_extbios_unimplemented 1565 | dw cirrus_extbios_unimplemented 1566 | dw cirrus_extbios_unimplemented 1567 | ;; A8h 1568 | dw cirrus_extbios_unimplemented 1569 | dw cirrus_extbios_unimplemented 1570 | dw cirrus_extbios_unimplemented 1571 | dw cirrus_extbios_unimplemented 1572 | ;; ACh 1573 | dw cirrus_extbios_unimplemented 1574 | dw cirrus_extbios_unimplemented 1575 | dw cirrus_extbios_AEh 1576 | dw cirrus_extbios_unimplemented 1577 | 1578 | cirrus_vesa_handlers: 1579 | ;; 00h 1580 | dw cirrus_vesa_00h 1581 | dw cirrus_vesa_01h 1582 | dw cirrus_vesa_02h 1583 | dw cirrus_vesa_03h 1584 | ;; 04h 1585 | dw cirrus_vesa_unimplemented 1586 | dw cirrus_vesa_05h 1587 | dw cirrus_vesa_06h 1588 | dw cirrus_vesa_07h 1589 | ;; 08h 1590 | dw cirrus_vesa_unimplemented 1591 | dw cirrus_vesa_unimplemented 1592 | dw cirrus_vesa_unimplemented 1593 | dw cirrus_vesa_unimplemented 1594 | ;; 0Ch 1595 | dw cirrus_vesa_unimplemented 1596 | dw cirrus_vesa_unimplemented 1597 | dw cirrus_vesa_unimplemented 1598 | dw cirrus_vesa_unimplemented 1599 | ;; 10h 1600 | dw cirrus_vesa_10h 1601 | 1602 | 1603 | ASM_END 1604 | 1605 | #ifdef CIRRUS_VESA3_PMINFO 1606 | ASM_START 1607 | cirrus_vesa_pminfo: 1608 | /* + 0 */ 1609 | .byte 0x50,0x4d,0x49,0x44 ;; signature[4] 1610 | /* + 4 */ 1611 | dw cirrus_vesa_pmbios_entry ;; entry_bios 1612 | dw cirrus_vesa_pmbios_init ;; entry_init 1613 | /* + 8 */ 1614 | cirrus_vesa_sel0000_data: 1615 | dw 0x0000 ;; sel_00000 1616 | cirrus_vesa_selA000_data: 1617 | dw 0xA000 ;; sel_A0000 1618 | /* +12 */ 1619 | cirrus_vesa_selB000_data: 1620 | dw 0xB000 ;; sel_B0000 1621 | cirrus_vesa_selB800_data: 1622 | dw 0xB800 ;; sel_B8000 1623 | /* +16 */ 1624 | cirrus_vesa_selC000_data: 1625 | dw 0xC000 ;; sel_C0000 1626 | cirrus_vesa_is_protected_mode: 1627 | ;; protected mode flag and checksum 1628 | dw (~((0xf2 + (cirrus_vesa_pmbios_entry >> 8) + (cirrus_vesa_pmbios_entry) \ 1629 | + (cirrus_vesa_pmbios_init >> 8) + (cirrus_vesa_pmbios_init)) & 0xff) << 8) + 0x01 1630 | ASM_END 1631 | #endif // CIRRUS_VESA3_PMINFO 1632 | 1633 | 1634 | #ifdef CIRRUS_DEBUG 1635 | static void cirrus_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS) 1636 | Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS; 1637 | { 1638 | if((GET_AH()!=0x0E)&&(GET_AH()!=0x02)&&(GET_AH()!=0x09)&&(AX!=0x4F05)) 1639 | printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX); 1640 | } 1641 | #endif 1642 | -------------------------------------------------------------------------------- /dataseghack: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | awk \ 4 | 'BEGIN { }\ 5 | /^\.text/,/DATA_SEG_DEFS_HERE/ { print }\ 6 | END { }'\ 7 | $1 > temp.awk.1 8 | 9 | awk \ 10 | 'BEGIN { i = 0; last = "hello" }\ 11 | /BLOCK_STRINGS_BEGIN/,/^\.bss/ { if ( i > 1 ) { print last } last = $0; i = i + 1 }\ 12 | END { }'\ 13 | $1 > temp.awk.2 14 | 15 | awk \ 16 | 'BEGIN { }\ 17 | /DATA_SEG_DEFS_HERE/,/BLOCK_STRINGS_BEGIN/ { print }\ 18 | END { }'\ 19 | $1 > temp.awk.3 20 | 21 | cp $1 $1.orig 22 | cat temp.awk.1 temp.awk.2 temp.awk.3 | sed -e 's/^\.data//' -e 's/^\.bss//' -e 's/^\.text//' > $1 23 | /bin/rm -f temp.awk.1 temp.awk.2 temp.awk.3 $1.orig 24 | -------------------------------------------------------------------------------- /tests/lfbprof/Makefile: -------------------------------------------------------------------------------- 1 | # Very simple makefile for LFBPROF.C using Watcom C++ 10.0a with DOS4GW 2 | 3 | lfbprof.exe: lfbprof.c lfbprof.h 4 | wcl386 -zq -s -d2 lfbprof.c 5 | 6 | -------------------------------------------------------------------------------- /tests/lfbprof/lfbprof.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * VBE 2.0 Linear Framebuffer Profiler 4 | * By Kendall Bennett and Brian Hook 5 | * 6 | * Filename: LFBPROF.C 7 | * Language: ANSI C 8 | * Environment: Watcom C/C++ 10.0a with DOS4GW 9 | * 10 | * Description: Simple program to profile the speed of screen clearing 11 | * and full screen BitBlt operations using a VESA VBE 2.0 12 | * linear framebuffer from 32 bit protected mode. 13 | * 14 | * For simplicity, this program only supports 256 color 15 | * SuperVGA video modes that support a linear framebuffer. 16 | * 17 | * 18 | * 2002/02/18: Jeroen Janssen 19 | * - fixed unsigned short for mode list (-1 != 0xffff otherwise) 20 | * - fixed LfbMapRealPointer macro mask problem (some modes were skipped) 21 | * 22 | ****************************************************************************/ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "lfbprof.h" 30 | 31 | /*---------------------------- Global Variables ---------------------------*/ 32 | 33 | int VESABuf_len = 1024; /* Length of VESABuf */ 34 | int VESABuf_sel = 0; /* Selector for VESABuf */ 35 | int VESABuf_rseg; /* Real mode segment of VESABuf */ 36 | unsigned short modeList[50]; /* List of available VBE modes */ 37 | float clearsPerSec; /* Number of clears per second */ 38 | float clearsMbPerSec; /* Memory transfer for clears */ 39 | float bitBltsPerSec; /* Number of BitBlt's per second */ 40 | float bitBltsMbPerSec; /* Memory transfer for bitblt's */ 41 | int xres,yres; /* Video mode resolution */ 42 | int bytesperline; /* Bytes per scanline for mode */ 43 | long imageSize; /* Length of the video image */ 44 | char *LFBPtr; /* Pointer to linear framebuffer */ 45 | 46 | /*------------------------- DPMI interface routines -----------------------*/ 47 | 48 | void DPMI_allocRealSeg(int size,int *sel,int *r_seg) 49 | /**************************************************************************** 50 | * 51 | * Function: DPMI_allocRealSeg 52 | * Parameters: size - Size of memory block to allocate 53 | * sel - Place to return protected mode selector 54 | * r_seg - Place to return real mode segment 55 | * 56 | * Description: Allocates a block of real mode memory using DPMI services. 57 | * This routine returns both a protected mode selector and 58 | * real mode segment for accessing the memory block. 59 | * 60 | ****************************************************************************/ 61 | { 62 | union REGS r; 63 | 64 | r.w.ax = 0x100; /* DPMI allocate DOS memory */ 65 | r.w.bx = (size + 0xF) >> 4; /* number of paragraphs */ 66 | int386(0x31, &r, &r); 67 | if (r.w.cflag) 68 | FatalError("DPMI_allocRealSeg failed!"); 69 | *sel = r.w.dx; /* Protected mode selector */ 70 | *r_seg = r.w.ax; /* Real mode segment */ 71 | } 72 | 73 | void DPMI_freeRealSeg(unsigned sel) 74 | /**************************************************************************** 75 | * 76 | * Function: DPMI_allocRealSeg 77 | * Parameters: sel - Protected mode selector of block to free 78 | * 79 | * Description: Frees a block of real mode memory. 80 | * 81 | ****************************************************************************/ 82 | { 83 | union REGS r; 84 | 85 | r.w.ax = 0x101; /* DPMI free DOS memory */ 86 | r.w.dx = sel; /* DX := selector from 0x100 */ 87 | int386(0x31, &r, &r); 88 | } 89 | 90 | typedef struct { 91 | long edi; 92 | long esi; 93 | long ebp; 94 | long reserved; 95 | long ebx; 96 | long edx; 97 | long ecx; 98 | long eax; 99 | short flags; 100 | short es,ds,fs,gs,ip,cs,sp,ss; 101 | } _RMREGS; 102 | 103 | #define IN(reg) rmregs.e##reg = in->x.reg 104 | #define OUT(reg) out->x.reg = rmregs.e##reg 105 | 106 | int DPMI_int86(int intno, RMREGS *in, RMREGS *out) 107 | /**************************************************************************** 108 | * 109 | * Function: DPMI_int86 110 | * Parameters: intno - Interrupt number to issue 111 | * in - Pointer to structure for input registers 112 | * out - Pointer to structure for output registers 113 | * Returns: Value returned by interrupt in AX 114 | * 115 | * Description: Issues a real mode interrupt using DPMI services. 116 | * 117 | ****************************************************************************/ 118 | { 119 | _RMREGS rmregs; 120 | union REGS r; 121 | struct SREGS sr; 122 | 123 | memset(&rmregs, 0, sizeof(rmregs)); 124 | IN(ax); IN(bx); IN(cx); IN(dx); IN(si); IN(di); 125 | 126 | segread(&sr); 127 | r.w.ax = 0x300; /* DPMI issue real interrupt */ 128 | r.h.bl = intno; 129 | r.h.bh = 0; 130 | r.w.cx = 0; 131 | sr.es = sr.ds; 132 | r.x.edi = (unsigned)&rmregs; 133 | int386x(0x31, &r, &r, &sr); /* Issue the interrupt */ 134 | 135 | OUT(ax); OUT(bx); OUT(cx); OUT(dx); OUT(si); OUT(di); 136 | out->x.cflag = rmregs.flags & 0x1; 137 | return out->x.ax; 138 | } 139 | 140 | int DPMI_int86x(int intno, RMREGS *in, RMREGS *out, RMSREGS *sregs) 141 | /**************************************************************************** 142 | * 143 | * Function: DPMI_int86 144 | * Parameters: intno - Interrupt number to issue 145 | * in - Pointer to structure for input registers 146 | * out - Pointer to structure for output registers 147 | * sregs - Values to load into segment registers 148 | * Returns: Value returned by interrupt in AX 149 | * 150 | * Description: Issues a real mode interrupt using DPMI services. 151 | * 152 | ****************************************************************************/ 153 | { 154 | _RMREGS rmregs; 155 | union REGS r; 156 | struct SREGS sr; 157 | 158 | memset(&rmregs, 0, sizeof(rmregs)); 159 | IN(ax); IN(bx); IN(cx); IN(dx); IN(si); IN(di); 160 | rmregs.es = sregs->es; 161 | rmregs.ds = sregs->ds; 162 | 163 | segread(&sr); 164 | r.w.ax = 0x300; /* DPMI issue real interrupt */ 165 | r.h.bl = intno; 166 | r.h.bh = 0; 167 | r.w.cx = 0; 168 | sr.es = sr.ds; 169 | r.x.edi = (unsigned)&rmregs; 170 | int386x(0x31, &r, &r, &sr); /* Issue the interrupt */ 171 | 172 | OUT(ax); OUT(bx); OUT(cx); OUT(dx); OUT(si); OUT(di); 173 | sregs->es = rmregs.es; 174 | sregs->cs = rmregs.cs; 175 | sregs->ss = rmregs.ss; 176 | sregs->ds = rmregs.ds; 177 | out->x.cflag = rmregs.flags & 0x1; 178 | return out->x.ax; 179 | } 180 | 181 | int DPMI_allocSelector(void) 182 | /**************************************************************************** 183 | * 184 | * Function: DPMI_allocSelector 185 | * Returns: Newly allocated protected mode selector 186 | * 187 | * Description: Allocates a new protected mode selector using DPMI 188 | * services. This selector has a base address and limit of 0. 189 | * 190 | ****************************************************************************/ 191 | { 192 | int sel; 193 | union REGS r; 194 | 195 | r.w.ax = 0; /* DPMI allocate selector */ 196 | r.w.cx = 1; /* Allocate a single selector */ 197 | int386(0x31, &r, &r); 198 | if (r.x.cflag) 199 | FatalError("DPMI_allocSelector() failed!"); 200 | sel = r.w.ax; 201 | 202 | r.w.ax = 9; /* DPMI set access rights */ 203 | r.w.bx = sel; 204 | r.w.cx = 0x8092; /* 32 bit page granular */ 205 | int386(0x31, &r, &r); 206 | return sel; 207 | } 208 | 209 | long DPMI_mapPhysicalToLinear(long physAddr,long limit) 210 | /**************************************************************************** 211 | * 212 | * Function: DPMI_mapPhysicalToLinear 213 | * Parameters: physAddr - Physical memory address to map 214 | * limit - Length-1 of physical memory region to map 215 | * Returns: Starting linear address for mapped memory 216 | * 217 | * Description: Maps a section of physical memory into the linear address 218 | * space of a process using DPMI calls. Note that this linear 219 | * address cannot be used directly, but must be used as the 220 | * base address for a selector. 221 | * 222 | ****************************************************************************/ 223 | { 224 | union REGS r; 225 | 226 | r.w.ax = 0x800; /* DPMI map physical to linear */ 227 | r.w.bx = physAddr >> 16; 228 | r.w.cx = physAddr & 0xFFFF; 229 | r.w.si = limit >> 16; 230 | r.w.di = limit & 0xFFFF; 231 | int386(0x31, &r, &r); 232 | if (r.x.cflag) 233 | FatalError("DPMI_mapPhysicalToLinear() failed!"); 234 | return ((long)r.w.bx << 16) + r.w.cx; 235 | } 236 | 237 | void DPMI_setSelectorBase(int sel,long linAddr) 238 | /**************************************************************************** 239 | * 240 | * Function: DPMI_setSelectorBase 241 | * Parameters: sel - Selector to change base address for 242 | * linAddr - Linear address used for new base address 243 | * 244 | * Description: Sets the base address for the specified selector. 245 | * 246 | ****************************************************************************/ 247 | { 248 | union REGS r; 249 | 250 | r.w.ax = 7; /* DPMI set selector base address */ 251 | r.w.bx = sel; 252 | r.w.cx = linAddr >> 16; 253 | r.w.dx = linAddr & 0xFFFF; 254 | int386(0x31, &r, &r); 255 | if (r.x.cflag) 256 | FatalError("DPMI_setSelectorBase() failed!"); 257 | } 258 | 259 | void DPMI_setSelectorLimit(int sel,long limit) 260 | /**************************************************************************** 261 | * 262 | * Function: DPMI_setSelectorLimit 263 | * Parameters: sel - Selector to change limit for 264 | * limit - Limit-1 for the selector 265 | * 266 | * Description: Sets the memory limit for the specified selector. 267 | * 268 | ****************************************************************************/ 269 | { 270 | union REGS r; 271 | 272 | r.w.ax = 8; /* DPMI set selector limit */ 273 | r.w.bx = sel; 274 | r.w.cx = limit >> 16; 275 | r.w.dx = limit & 0xFFFF; 276 | int386(0x31, &r, &r); 277 | if (r.x.cflag) 278 | FatalError("DPMI_setSelectorLimit() failed!"); 279 | } 280 | 281 | /*-------------------------- VBE Interface routines -----------------------*/ 282 | 283 | void FatalError(char *msg) 284 | { 285 | fprintf(stderr,"%s\n", msg); 286 | exit(1); 287 | } 288 | 289 | static void ExitVBEBuf(void) 290 | { 291 | DPMI_freeRealSeg(VESABuf_sel); 292 | } 293 | 294 | void VBE_initRMBuf(void) 295 | /**************************************************************************** 296 | * 297 | * Function: VBE_initRMBuf 298 | * Description: Initialises the VBE transfer buffer in real mode memory. 299 | * This routine is called by the VESAVBE module every time 300 | * it needs to use the transfer buffer, so we simply allocate 301 | * it once and then return. 302 | * 303 | ****************************************************************************/ 304 | { 305 | if (!VESABuf_sel) { 306 | DPMI_allocRealSeg(VESABuf_len, &VESABuf_sel, &VESABuf_rseg); 307 | atexit(ExitVBEBuf); 308 | } 309 | } 310 | 311 | void VBE_callESDI(RMREGS *regs, void *buffer, int size) 312 | /**************************************************************************** 313 | * 314 | * Function: VBE_callESDI 315 | * Parameters: regs - Registers to load when calling VBE 316 | * buffer - Buffer to copy VBE info block to 317 | * size - Size of buffer to fill 318 | * 319 | * Description: Calls the VESA VBE and passes in a buffer for the VBE to 320 | * store information in, which is then copied into the users 321 | * buffer space. This works in protected mode as the buffer 322 | * passed to the VESA VBE is allocated in conventional 323 | * memory, and is then copied into the users memory block. 324 | * 325 | ****************************************************************************/ 326 | { 327 | RMSREGS sregs; 328 | 329 | VBE_initRMBuf(); 330 | sregs.es = VESABuf_rseg; 331 | regs->x.di = 0; 332 | _fmemcpy(MK_FP(VESABuf_sel,0),buffer,size); 333 | DPMI_int86x(0x10, regs, regs, &sregs); 334 | _fmemcpy(buffer,MK_FP(VESABuf_sel,0),size); 335 | } 336 | 337 | int VBE_detect(void) 338 | /**************************************************************************** 339 | * 340 | * Function: VBE_detect 341 | * Parameters: vgaInfo - Place to store the VGA information block 342 | * Returns: VBE version number, or 0 if not detected. 343 | * 344 | * Description: Detects if a VESA VBE is out there and functioning 345 | * correctly. If we detect a VBE interface we return the 346 | * VGAInfoBlock returned by the VBE and the VBE version number. 347 | * 348 | ****************************************************************************/ 349 | { 350 | RMREGS regs; 351 | unsigned short *p1,*p2; 352 | VBE_vgaInfo vgaInfo; 353 | 354 | /* Put 'VBE2' into the signature area so that the VBE 2.0 BIOS knows 355 | * that we have passed a 512 byte extended block to it, and wish 356 | * the extended information to be filled in. 357 | */ 358 | strncpy(vgaInfo.VESASignature,"VBE2",4); 359 | 360 | /* Get the SuperVGA Information block */ 361 | regs.x.ax = 0x4F00; 362 | VBE_callESDI(®s, &vgaInfo, sizeof(VBE_vgaInfo)); 363 | if (regs.x.ax != 0x004F) 364 | return 0; 365 | if (strncmp(vgaInfo.VESASignature,"VESA",4) != 0) 366 | return 0; 367 | 368 | /* Now that we have detected a VBE interface, copy the list of available 369 | * video modes into our local buffer. We *must* copy this mode list, 370 | * since the VBE will build the mode list in the VBE_vgaInfo buffer 371 | * that we have passed, so the next call to the VBE will trash the 372 | * list of modes. 373 | */ 374 | printf("videomodeptr %x\n",vgaInfo.VideoModePtr); 375 | p1 = LfbMapRealPointer(vgaInfo.VideoModePtr); 376 | p2 = modeList; 377 | while (*p1 != -1) 378 | { 379 | printf("found mode %x\n",*p1); 380 | *p2++ = *p1++; 381 | } 382 | *p2 = -1; 383 | return vgaInfo.VESAVersion; 384 | } 385 | 386 | int VBE_getModeInfo(int mode,VBE_modeInfo *modeInfo) 387 | /**************************************************************************** 388 | * 389 | * Function: VBE_getModeInfo 390 | * Parameters: mode - VBE mode to get information for 391 | * modeInfo - Place to store VBE mode information 392 | * Returns: 1 on success, 0 if function failed. 393 | * 394 | * Description: Obtains information about a specific video mode from the 395 | * VBE. You should use this function to find the video mode 396 | * you wish to set, as the new VBE 2.0 mode numbers may be 397 | * completely arbitrary. 398 | * 399 | ****************************************************************************/ 400 | { 401 | RMREGS regs; 402 | 403 | regs.x.ax = 0x4F01; /* Get mode information */ 404 | regs.x.cx = mode; 405 | VBE_callESDI(®s, modeInfo, sizeof(VBE_modeInfo)); 406 | if (regs.x.ax != 0x004F) 407 | return 0; 408 | if ((modeInfo->ModeAttributes & vbeMdAvailable) == 0) 409 | return 0; 410 | return 1; 411 | } 412 | 413 | void VBE_setVideoMode(int mode) 414 | /**************************************************************************** 415 | * 416 | * Function: VBE_setVideoMode 417 | * Parameters: mode - VBE mode number to initialise 418 | * 419 | ****************************************************************************/ 420 | { 421 | RMREGS regs; 422 | regs.x.ax = 0x4F02; 423 | regs.x.bx = mode; 424 | DPMI_int86(0x10,®s,®s); 425 | } 426 | 427 | /*-------------------- Application specific routines ----------------------*/ 428 | 429 | void *GetPtrToLFB(long physAddr) 430 | /**************************************************************************** 431 | * 432 | * Function: GetPtrToLFB 433 | * Parameters: physAddr - Physical memory address of linear framebuffer 434 | * Returns: Far pointer to the linear framebuffer memory 435 | * 436 | ****************************************************************************/ 437 | { 438 | int sel; 439 | long linAddr,limit = (4096 * 1024) - 1; 440 | 441 | // sel = DPMI_allocSelector(); 442 | linAddr = DPMI_mapPhysicalToLinear(physAddr,limit); 443 | // DPMI_setSelectorBase(sel,linAddr); 444 | // DPMI_setSelectorLimit(sel,limit); 445 | // return MK_FP(sel,0); 446 | return (void*)linAddr; 447 | } 448 | 449 | void AvailableModes(void) 450 | /**************************************************************************** 451 | * 452 | * Function: AvailableModes 453 | * 454 | * Description: Display a list of available LFB mode resolutions. 455 | * 456 | ****************************************************************************/ 457 | { 458 | unsigned short *p; 459 | VBE_modeInfo modeInfo; 460 | 461 | printf("Usage: LFBPROF \n\n"); 462 | printf("Available 256 color video modes:\n"); 463 | for (p = modeList; *p != -1; p++) { 464 | if (VBE_getModeInfo(*p, &modeInfo)) { 465 | /* Filter out only 8 bit linear framebuffer modes */ 466 | if ((modeInfo.ModeAttributes & vbeMdLinear) == 0) 467 | continue; 468 | if (modeInfo.MemoryModel != vbeMemPK 469 | || modeInfo.BitsPerPixel != 8 470 | || modeInfo.NumberOfPlanes != 1) 471 | continue; 472 | printf(" %4d x %4d %d bits per pixel\n", 473 | modeInfo.XResolution, modeInfo.YResolution, 474 | modeInfo.BitsPerPixel); 475 | } 476 | } 477 | exit(1); 478 | } 479 | 480 | void InitGraphics(int x,int y) 481 | /**************************************************************************** 482 | * 483 | * Function: InitGraphics 484 | * Parameters: x,y - Requested video mode resolution 485 | * 486 | * Description: Initialise the specified video mode. We search through 487 | * the list of available video modes for one that matches 488 | * the resolution and color depth are are looking for. 489 | * 490 | ****************************************************************************/ 491 | { 492 | unsigned short *p; 493 | VBE_modeInfo modeInfo; 494 | printf("InitGraphics\n"); 495 | 496 | for (p = modeList; *p != -1; p++) { 497 | if (VBE_getModeInfo(*p, &modeInfo)) { 498 | /* Filter out only 8 bit linear framebuffer modes */ 499 | if ((modeInfo.ModeAttributes & vbeMdLinear) == 0) 500 | continue; 501 | if (modeInfo.MemoryModel != vbeMemPK 502 | || modeInfo.BitsPerPixel != 8 503 | || modeInfo.NumberOfPlanes != 1) 504 | continue; 505 | if (modeInfo.XResolution != x || modeInfo.YResolution != y) 506 | continue; 507 | xres = x; 508 | yres = y; 509 | bytesperline = modeInfo.BytesPerScanLine; 510 | imageSize = bytesperline * yres; 511 | VBE_setVideoMode(*p | vbeUseLFB); 512 | LFBPtr = GetPtrToLFB(modeInfo.PhysBasePtr); 513 | return; 514 | } 515 | } 516 | printf("Valid video mode not found\n"); 517 | exit(1); 518 | } 519 | 520 | void EndGraphics(void) 521 | /**************************************************************************** 522 | * 523 | * Function: EndGraphics 524 | * 525 | * Description: Restores text mode. 526 | * 527 | ****************************************************************************/ 528 | { 529 | RMREGS regs; 530 | printf("EndGraphics\n"); 531 | regs.x.ax = 0x3; 532 | DPMI_int86(0x10, ®s, ®s); 533 | } 534 | 535 | void ProfileMode(void) 536 | /**************************************************************************** 537 | * 538 | * Function: ProfileMode 539 | * 540 | * Description: Profiles framebuffer performance for simple screen clearing 541 | * and for copying from system memory to video memory (BitBlt). 542 | * This routine thrashes the CPU cache by cycling through 543 | * enough system memory buffers to invalidate the entire 544 | * CPU external cache before re-using the first memory buffer 545 | * again. 546 | * 547 | ****************************************************************************/ 548 | { 549 | int i,numClears,numBlts,maxImages; 550 | long startTicks,endTicks; 551 | void *image[10],*dst; 552 | printf("ProfileMode\n"); 553 | 554 | /* Profile screen clearing operation */ 555 | startTicks = LfbGetTicks(); 556 | numClears = 0; 557 | while ((LfbGetTicks() - startTicks) < 182) 558 | LfbMemset(LFBPtr,numClears++,imageSize); 559 | endTicks = LfbGetTicks(); 560 | clearsPerSec = numClears / ((endTicks - startTicks) * 0.054925); 561 | clearsMbPerSec = (clearsPerSec * imageSize) / 1048576.0; 562 | 563 | /* Profile system memory to video memory copies */ 564 | maxImages = ((512 * 1024U) / imageSize) + 2; 565 | for (i = 0; i < maxImages; i++) { 566 | image[i] = malloc(imageSize); 567 | if (image[i] == NULL) 568 | FatalError("Not enough memory to profile BitBlt!"); 569 | memset(image[i],i+1,imageSize); 570 | } 571 | startTicks = LfbGetTicks(); 572 | numBlts = 0; 573 | while ((LfbGetTicks() - startTicks) < 182) 574 | LfbMemcpy(LFBPtr,image[numBlts++ % maxImages],imageSize); 575 | endTicks = LfbGetTicks(); 576 | bitBltsPerSec = numBlts / ((endTicks - startTicks) * 0.054925); 577 | bitBltsMbPerSec = (bitBltsPerSec * imageSize) / 1048576.0; 578 | } 579 | 580 | void main(int argc, char *argv[]) 581 | { 582 | if (VBE_detect() < 0x200) 583 | FatalError("This program requires VBE 2.0; Please install UniVBE 5.1."); 584 | if (argc != 3) 585 | AvailableModes(); /* Display available modes */ 586 | 587 | InitGraphics(atoi(argv[1]),atoi(argv[2])); /* Start graphics */ 588 | ProfileMode(); /* Profile the video mode */ 589 | EndGraphics(); /* Restore text mode */ 590 | 591 | printf("Profiling results for %dx%d 8 bits per pixel.\n",xres,yres); 592 | printf("%3.2f clears/s, %2.2f Mb/s\n", clearsPerSec, clearsMbPerSec); 593 | printf("%3.2f bitBlt/s, %2.2f Mb/s\n", bitBltsPerSec, bitBltsMbPerSec); 594 | } 595 | -------------------------------------------------------------------------------- /tests/lfbprof/lfbprof.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * VBE 2.0 Linear Framebuffer Profiler 4 | * By Kendall Bennett and Brian Hook 5 | * 6 | * Filename: LFBPROF.H 7 | * Language: ANSI C 8 | * Environment: Watcom C/C++ 10.0a with DOS4GW 9 | * 10 | * Description: Header file for the LFBPROF.C progam. 11 | * 12 | ****************************************************************************/ 13 | 14 | #ifndef __LFBPROF_H 15 | #define __LFBPROF_H 16 | 17 | /*---------------------- Macros and type definitions ----------------------*/ 18 | 19 | #pragma pack(1) 20 | 21 | /* SuperVGA information block */ 22 | 23 | typedef struct { 24 | char VESASignature[4]; /* 'VESA' 4 byte signature */ 25 | short VESAVersion; /* VBE version number */ 26 | long OemStringPtr; /* Pointer to OEM string */ 27 | long Capabilities; /* Capabilities of video card */ 28 | long VideoModePtr; /* Pointer to supported modes */ 29 | short TotalMemory; /* Number of 64kb memory blocks */ 30 | 31 | /* VBE 2.0 extensions */ 32 | 33 | short OemSoftwareRev; /* OEM Software revision number */ 34 | long OemVendorNamePtr; /* Pointer to Vendor Name string */ 35 | long OemProductNamePtr; /* Pointer to Product Name string */ 36 | long OemProductRevPtr; /* Pointer to Product Revision str */ 37 | char reserved[222]; /* Pad to 256 byte block size */ 38 | char OemDATA[256]; /* Scratch pad for OEM data */ 39 | } VBE_vgaInfo; 40 | 41 | /* SuperVGA mode information block */ 42 | 43 | typedef struct { 44 | short ModeAttributes; /* Mode attributes */ 45 | char WinAAttributes; /* Window A attributes */ 46 | char WinBAttributes; /* Window B attributes */ 47 | short WinGranularity; /* Window granularity in k */ 48 | short WinSize; /* Window size in k */ 49 | short WinASegment; /* Window A segment */ 50 | short WinBSegment; /* Window B segment */ 51 | long WinFuncPtr; /* Pointer to window function */ 52 | short BytesPerScanLine; /* Bytes per scanline */ 53 | short XResolution; /* Horizontal resolution */ 54 | short YResolution; /* Vertical resolution */ 55 | char XCharSize; /* Character cell width */ 56 | char YCharSize; /* Character cell height */ 57 | char NumberOfPlanes; /* Number of memory planes */ 58 | char BitsPerPixel; /* Bits per pixel */ 59 | char NumberOfBanks; /* Number of CGA style banks */ 60 | char MemoryModel; /* Memory model type */ 61 | char BankSize; /* Size of CGA style banks */ 62 | char NumberOfImagePages; /* Number of images pages */ 63 | char res1; /* Reserved */ 64 | char RedMaskSize; /* Size of direct color red mask */ 65 | char RedFieldPosition; /* Bit posn of lsb of red mask */ 66 | char GreenMaskSize; /* Size of direct color green mask */ 67 | char GreenFieldPosition; /* Bit posn of lsb of green mask */ 68 | char BlueMaskSize; /* Size of direct color blue mask */ 69 | char BlueFieldPosition; /* Bit posn of lsb of blue mask */ 70 | char RsvdMaskSize; /* Size of direct color res mask */ 71 | char RsvdFieldPosition; /* Bit posn of lsb of res mask */ 72 | char DirectColorModeInfo; /* Direct color mode attributes */ 73 | 74 | /* VBE 2.0 extensions */ 75 | 76 | long PhysBasePtr; /* Physical address for linear buf */ 77 | long OffScreenMemOffset; /* Pointer to start of offscreen mem*/ 78 | short OffScreenMemSize; /* Amount of offscreen mem in 1K's */ 79 | char res2[206]; /* Pad to 256 byte block size */ 80 | } VBE_modeInfo; 81 | 82 | #define vbeMemPK 4 /* Packed Pixel memory model */ 83 | #define vbeUseLFB 0x4000 /* Enable linear framebuffer mode */ 84 | 85 | /* Flags for the mode attributes returned by VBE_getModeInfo. If 86 | * vbeMdNonBanked is set to 1 and vbeMdLinear is also set to 1, then only 87 | * the linear framebuffer mode is available. 88 | */ 89 | 90 | #define vbeMdAvailable 0x0001 /* Video mode is available */ 91 | #define vbeMdColorMode 0x0008 /* Mode is a color video mode */ 92 | #define vbeMdGraphMode 0x0010 /* Mode is a graphics mode */ 93 | #define vbeMdNonBanked 0x0040 /* Banked mode is not supported */ 94 | #define vbeMdLinear 0x0080 /* Linear mode supported */ 95 | 96 | /* Structures for issuing real mode interrupts with DPMI */ 97 | 98 | struct _RMWORDREGS { 99 | unsigned short ax, bx, cx, dx, si, di, cflag; 100 | }; 101 | 102 | struct _RMBYTEREGS { 103 | unsigned char al, ah, bl, bh, cl, ch, dl, dh; 104 | }; 105 | 106 | typedef union { 107 | struct _RMWORDREGS x; 108 | struct _RMBYTEREGS h; 109 | } RMREGS; 110 | 111 | typedef struct { 112 | unsigned short es; 113 | unsigned short cs; 114 | unsigned short ss; 115 | unsigned short ds; 116 | } RMSREGS; 117 | 118 | /* Inline assembler block fill/move routines */ 119 | 120 | void LfbMemset(void *p,int c,int n); 121 | #pragma aux LfbMemset = \ 122 | "shr ecx,2" \ 123 | "xor eax,eax" \ 124 | "mov al,bl" \ 125 | "shl ebx,8" \ 126 | "or ax,bx" \ 127 | "mov ebx,eax" \ 128 | "shl ebx,16" \ 129 | "or eax,ebx" \ 130 | "rep stosd" \ 131 | parm [edi] [ebx] [ecx]; 132 | 133 | void LfbMemcpy(void *dst,void *src,int n); 134 | #pragma aux LfbMemcpy = \ 135 | "shr ecx,2" \ 136 | "rep movsd" \ 137 | parm [edi] [esi] [ecx]; 138 | 139 | /* Map a real mode pointer into address space */ 140 | 141 | #define LfbMapRealPointer(p) (void*)(((unsigned)((p) & 0xFFFF0000) >> 12) + ((p) & 0xFFFF)) 142 | 143 | /* Get the current timer tick count */ 144 | 145 | #define LfbGetTicks() *((long*)0x46C) 146 | 147 | #pragma pack() 148 | 149 | #endif /* __LFBPROF_H */ 150 | -------------------------------------------------------------------------------- /tests/testbios.c: -------------------------------------------------------------------------------- 1 | /* 2 | This is a little turbo C program that executes 3 | several int10, and let you inspect the content 4 | of the vgabios area 5 | 6 | It is used to test the behavior of the vgabios 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | typedef unsigned char Bit8u; 15 | typedef unsigned short Bit16u; 16 | 17 | typedef struct 18 | {Bit8u initial; 19 | Bit8u current; 20 | Bit16u nbcols; 21 | Bit16u regen; 22 | Bit16u start; 23 | Bit16u curpos[8]; 24 | Bit8u curtyp; 25 | Bit8u curpage; 26 | Bit16u crtc; 27 | Bit16u msr; 28 | Bit16u cgapal; 29 | Bit8u nbrows; 30 | Bit16u cheight; 31 | Bit8u ctl; 32 | Bit8u switches; 33 | Bit8u modeset; 34 | Bit8u dcc; 35 | Bit16u vsseg; 36 | Bit16u vsoffset; 37 | } BIOSAREA; 38 | 39 | void int10ax0003(struct REGPACK *regs) 40 | { 41 | regs->r_ax=0x0003; 42 | intr(0x10,regs); 43 | } 44 | 45 | void int10ax02(struct REGPACK *regs) 46 | { 47 | regs->r_ax=0x0200; 48 | regs->r_bx=0x0000; 49 | regs->r_dx=0x1710; 50 | intr(0x10,regs); 51 | printf("We are now at 24/17"); 52 | } 53 | 54 | void int10ax03(struct REGPACK *regs) 55 | { 56 | regs->r_ax=0x0300; 57 | regs->r_bx=0x0000; 58 | intr(0x10,regs); 59 | printf("\nCursor is ax%04x cx%04x dx%04x\n",regs->r_ax,regs->r_cx,regs->r_dx); 60 | } 61 | 62 | void int10ax0501(struct REGPACK *regs) 63 | { 64 | regs->r_ax=0x0501; 65 | intr(0x10,regs); 66 | regs->r_ax=0x0e61; 67 | regs->r_bx=0x0000; 68 | intr(0x10,regs); 69 | printf("We are now on page 2"); 70 | } 71 | 72 | void int10ax0602(struct REGPACK *regs) 73 | { 74 | regs->r_ax=0x0602; 75 | regs->r_bx=0x0700; 76 | regs->r_cx=0x0101; 77 | regs->r_dx=0x0a0a; 78 | intr(0x10,regs); 79 | printf("Scrolled 2 up"); 80 | } 81 | 82 | void int10ax0702(struct REGPACK *regs) 83 | { 84 | regs->r_ax=0x0702; 85 | regs->r_bx=0x0700; 86 | regs->r_cx=0x0101; 87 | regs->r_dx=0x0a0a; 88 | intr(0x10,regs); 89 | printf("Scrolled 2 down"); 90 | } 91 | 92 | void int10ax08(struct REGPACK *regs) 93 | { 94 | regs->r_ax=0x0800; 95 | regs->r_bx=0x0000; 96 | intr(0x10,regs); 97 | } 98 | 99 | void int10ax09(struct REGPACK *regs) 100 | { 101 | char attr; 102 | regs->r_ax=0x0501; 103 | intr(0x10,regs); 104 | for(attr=0;attr<16;attr++) 105 | {printf("%02x ",attr); 106 | regs->r_ax=0x0961+attr; 107 | regs->r_bx=0x0100+attr; 108 | regs->r_cx=0x0016; 109 | intr(0x10,regs); 110 | printf("\n"); 111 | } 112 | } 113 | 114 | void int10ax0a(struct REGPACK *regs) 115 | { 116 | regs->r_ax=0x0501; 117 | intr(0x10,regs); 118 | regs->r_ax=0x0a62; 119 | regs->r_bx=0x0101; 120 | regs->r_cx=0x0016; 121 | intr(0x10,regs); 122 | } 123 | 124 | void int10ax0f(struct REGPACK *regs) 125 | { 126 | regs->r_ax=0x0501; 127 | intr(0x10,regs); 128 | regs->r_ax=0x0f00; 129 | intr(0x10,regs); 130 | } 131 | 132 | void int10ax1b(struct REGPACK *regs) 133 | {unsigned char table[64]; 134 | unsigned char far *ptable; 135 | int i; 136 | 137 | regs->r_ax=0x0501; 138 | intr(0x10,regs); 139 | regs->r_ax=0x1b00; 140 | regs->r_bx=0x0000; 141 | ptable=&table; 142 | regs->r_es=FP_SEG(ptable); 143 | regs->r_di=FP_OFF(ptable); 144 | printf("Read state info in %04x:%04x\n",regs->r_es,regs->r_di); 145 | intr(0x10,regs); 146 | 147 | for(i=0;i<64;i++) 148 | {if(i%16==0)printf("\n%02x ",i); 149 | printf("%02x ",table[i]); 150 | } 151 | printf("\n"); 152 | } 153 | 154 | static unsigned char var[64]; 155 | 156 | void int10ax13(struct REGPACK *regs) 157 | {unsigned char far *pvar; 158 | 159 | pvar=&var; 160 | 161 | regs->r_ax=0x1300; 162 | regs->r_bx=0x000b; 163 | regs->r_dx=0x1010; 164 | regs->r_cx=0x0002; 165 | regs->r_es=FP_SEG(pvar); 166 | regs->r_bp=FP_OFF(pvar); 167 | pokeb(regs->r_es,regs->r_bp,'t'); 168 | pokeb(regs->r_es,regs->r_bp+1,'b'); 169 | printf("Writing from %04x:%04x\n",regs->r_es,regs->r_bp); 170 | intr(0x10,regs); 171 | 172 | } 173 | 174 | void switch_50(struct REGPACK *regs) 175 | { 176 | regs->r_ax=0x1202; 177 | regs->r_bx=0x3000; 178 | intr(0x10,regs); 179 | regs->r_ax=0x0003; 180 | intr(0x10,regs); 181 | regs->r_ax=0x1112; 182 | regs->r_bx=0x0000; 183 | intr(0x10,regs); 184 | } 185 | 186 | char exec_function(struct REGPACK *regs) 187 | {char c; 188 | 189 | printf("--- Functions --------------------\n"); 190 | printf("a. int10 ax0003\t"); 191 | printf("b. int10 ax02\t"); 192 | printf("c. int10 ax03\t"); 193 | printf("d. int10 ax0501\n"); 194 | printf("e. int10 ax0602\t"); 195 | printf("f. int10 ax0702\t"); 196 | printf("g. int10 ax08\t"); 197 | printf("h. int10 ax09\t"); 198 | printf("i. int10 ax0a\n"); 199 | printf("j. int10 ax0f\t"); 200 | printf("k. int10 ax1b\t"); 201 | printf("l. int10 ax13\n"); 202 | printf("q. Quit\t"); 203 | printf("r. switch to 50 lines\n"); 204 | c=getche(); 205 | 206 | switch(c) 207 | {case 'a': 208 | int10ax0003(regs); 209 | break; 210 | case 'b': 211 | int10ax02(regs); 212 | break; 213 | case 'c': 214 | int10ax03(regs); 215 | break; 216 | case 'd': 217 | int10ax0501(regs); 218 | break; 219 | case 'e': 220 | int10ax0602(regs); 221 | break; 222 | case 'f': 223 | int10ax0702(regs); 224 | break; 225 | case 'g': 226 | int10ax08(regs); 227 | break; 228 | case 'h': 229 | int10ax09(regs); 230 | break; 231 | case 'i': 232 | int10ax0a(regs); 233 | break; 234 | case 'j': 235 | int10ax0f(regs); 236 | break; 237 | case 'k': 238 | int10ax1b(regs); 239 | break; 240 | case 'l': 241 | int10ax13(regs); 242 | break; 243 | case 'q': 244 | break; 245 | case 'r': 246 | switch_50(regs); 247 | break; 248 | default: 249 | printf("No such function!\n"); 250 | } 251 | 252 | if(c=='q')return 1; 253 | while(kbhit()==0); 254 | c=getch(); 255 | 256 | return 0; 257 | } 258 | 259 | void read_bios_area(BIOSAREA *biosarea) 260 | { 261 | biosarea->initial=peekb(0x40,0x10); 262 | biosarea->current=peekb(0x40,0x49); 263 | biosarea->nbcols=peek(0x40,0x4a); 264 | biosarea->regen=peek(0x40,0x4c); 265 | biosarea->start=peek(0x40,0x4e); 266 | biosarea->curpos[0]=peek(0x40,0x50); 267 | biosarea->curpos[1]=peek(0x40,0x52); 268 | biosarea->curpos[2]=peek(0x40,0x54); 269 | biosarea->curpos[3]=peek(0x40,0x56); 270 | biosarea->curpos[4]=peek(0x40,0x58); 271 | biosarea->curpos[5]=peek(0x40,0x5a); 272 | biosarea->curpos[6]=peek(0x40,0x5c); 273 | biosarea->curpos[7]=peek(0x40,0x5e); 274 | biosarea->curtyp=peek(0x40,0x60); 275 | biosarea->curpage=peekb(0x40,0x62); 276 | biosarea->crtc=peek(0x40,0x63); 277 | biosarea->msr=peekb(0x40,0x65); 278 | biosarea->cgapal=peekb(0x40,0x66); 279 | biosarea->nbrows=peekb(0x40,0x84); 280 | biosarea->cheight=peek(0x40,0x85); 281 | biosarea->ctl=peekb(0x40,0x87); 282 | biosarea->switches=peekb(0x40,0x88); 283 | biosarea->modeset=peekb(0x40,0x89); 284 | biosarea->dcc=peekb(0x40,0x8a); 285 | biosarea->vsseg=peek(0x40,0xa8); 286 | biosarea->vsoffset=peek(0x40,0xaa); 287 | } 288 | 289 | void show_bios_area(BIOSAREA *biosarea) 290 | { 291 | printf("--- BIOS area --------------------\n"); 292 | printf("initial : %02x\t",biosarea->initial); 293 | printf("current : %02x\t",biosarea->current); 294 | printf("nbcols : %04x\t",biosarea->nbcols); 295 | printf("regen : %04x\t",biosarea->regen); 296 | printf("start : %04x\n",biosarea->start); 297 | printf("curpos : %04x %04x %04x %04x %04x %04x %04x %04x\n", 298 | biosarea->curpos[0], biosarea->curpos[1], biosarea->curpos[2], biosarea->curpos[3], 299 | biosarea->curpos[4], biosarea->curpos[5], biosarea->curpos[6], biosarea->curpos[7]); 300 | printf("curtyp : %04x\t",biosarea->curtyp); 301 | printf("curpage : %02x\t",biosarea->curpage); 302 | printf("crtc : %04x\t",biosarea->crtc); 303 | printf("msr : %04x\n",biosarea->msr); 304 | printf("cgapal : %04x\t",biosarea->cgapal); 305 | printf("nbrows-1: %02x\t",biosarea->nbrows); 306 | printf("cheight : %04x\t",biosarea->cheight); 307 | printf("ctl : %02x\n",biosarea->ctl); 308 | printf("switches: %02x\t",biosarea->switches); 309 | printf("modeset : %02x\t",biosarea->modeset); 310 | printf("dcc : %02x\t",biosarea->dcc); 311 | printf("vs : %04x:%04x\n",biosarea->vsseg,biosarea->vsoffset); 312 | } 313 | 314 | void show_regs(struct REGPACK *regs) 315 | { 316 | printf("--- Registers --------------------\n"); 317 | printf("ax %04x\t",regs->r_ax); 318 | printf("bx %04x\t",regs->r_bx); 319 | printf("cx %04x\t",regs->r_cx); 320 | printf("dx %04x\t",regs->r_dx); 321 | printf("ds %04x\t",regs->r_ds); 322 | printf("si %04x\t",regs->r_si); 323 | printf("es %04x\t",regs->r_es); 324 | printf("di %04x\n",regs->r_di); 325 | } 326 | 327 | void reset_videomode() 328 | { 329 | struct REGPACK regs; 330 | 331 | regs.r_ax=0x0003; 332 | intr(0x10,®s); 333 | } 334 | 335 | void main() 336 | { 337 | 338 | BIOSAREA biosarea; 339 | struct REGPACK regs; 340 | 341 | directvideo=0; 342 | 343 | while(1) 344 | { 345 | read_bios_area(&biosarea); 346 | 347 | reset_videomode(); 348 | show_bios_area(&biosarea); 349 | show_regs(®s); 350 | 351 | if(exec_function(®s)!=0)break; 352 | } 353 | } 354 | -------------------------------------------------------------------------------- /vbe.h: -------------------------------------------------------------------------------- 1 | #ifndef vbe_h_included 2 | #define vbe_h_included 3 | 4 | #include "vgabios.h" 5 | 6 | // DISPI helper function 7 | void dispi_set_enable(enable); 8 | 9 | /** VBE int10 API 10 | * 11 | * See the function descriptions in vbe.c for more information 12 | */ 13 | Boolean vbe_has_vbe_display(); 14 | void vbe_biosfn_return_controller_information(AX, ES, DI); 15 | void vbe_biosfn_return_mode_information(AX, CX, ES, DI); 16 | void vbe_biosfn_set_mode(AX, BX, ES, DI); 17 | void vbe_biosfn_save_restore_state(AX, CX, DX, ES, BX); 18 | void vbe_biosfn_set_get_palette_data(AX); 19 | void vbe_biosfn_return_protected_mode_interface(AX); 20 | 21 | // The official VBE Information Block 22 | typedef struct VbeInfoBlock 23 | { 24 | Bit8u VbeSignature[4]; 25 | Bit16u VbeVersion; 26 | Bit16u OemStringPtr_Off; 27 | Bit16u OemStringPtr_Seg; 28 | Bit8u Capabilities[4]; 29 | Bit16u VideoModePtr_Off; 30 | Bit16u VideoModePtr_Seg; 31 | Bit16u TotalMemory; 32 | Bit16u OemSoftwareRev; 33 | Bit16u OemVendorNamePtr_Off; 34 | Bit16u OemVendorNamePtr_Seg; 35 | Bit16u OemProductNamePtr_Off; 36 | Bit16u OemProductNamePtr_Seg; 37 | Bit16u OemProductRevPtr_Off; 38 | Bit16u OemProductRevPtr_Seg; 39 | Bit16u Reserved[111]; // used for dynamicly generated mode list 40 | Bit8u OemData[256]; 41 | } VbeInfoBlock; 42 | 43 | 44 | // This one is for compactly storing a static list of mode info blocks 45 | // this saves us 189 bytes per block 46 | typedef struct ModeInfoBlockCompact 47 | { 48 | // Mandatory information for all VBE revisions 49 | Bit16u ModeAttributes; 50 | Bit8u WinAAttributes; 51 | Bit8u WinBAttributes; 52 | Bit16u WinGranularity; 53 | Bit16u WinSize; 54 | Bit16u WinASegment; 55 | Bit16u WinBSegment; 56 | Bit32u WinFuncPtr; 57 | Bit16u BytesPerScanLine; 58 | // Mandatory information for VBE 1.2 and above 59 | Bit16u XResolution; 60 | Bit16u YResolution; 61 | Bit8u XCharSize; 62 | Bit8u YCharSize; 63 | Bit8u NumberOfPlanes; 64 | Bit8u BitsPerPixel; 65 | Bit8u NumberOfBanks; 66 | Bit8u MemoryModel; 67 | Bit8u BankSize; 68 | Bit8u NumberOfImagePages; 69 | Bit8u Reserved_page; 70 | // Direct Color fields (required for direct/6 and YUV/7 memory models) 71 | Bit8u RedMaskSize; 72 | Bit8u RedFieldPosition; 73 | Bit8u GreenMaskSize; 74 | Bit8u GreenFieldPosition; 75 | Bit8u BlueMaskSize; 76 | Bit8u BlueFieldPosition; 77 | Bit8u RsvdMaskSize; 78 | Bit8u RsvdFieldPosition; 79 | Bit8u DirectColorModeInfo; 80 | // Mandatory information for VBE 2.0 and above 81 | Bit32u PhysBasePtr; 82 | Bit32u OffScreenMemOffset; 83 | Bit16u OffScreenMemSize; 84 | // Mandatory information for VBE 3.0 and above 85 | Bit16u LinBytesPerScanLine; 86 | Bit8u BnkNumberOfPages; 87 | Bit8u LinNumberOfPages; 88 | Bit8u LinRedMaskSize; 89 | Bit8u LinRedFieldPosition; 90 | Bit8u LinGreenMaskSize; 91 | Bit8u LinGreenFieldPosition; 92 | Bit8u LinBlueMaskSize; 93 | Bit8u LinBlueFieldPosition; 94 | Bit8u LinRsvdMaskSize; 95 | Bit8u LinRsvdFieldPosition; 96 | Bit32u MaxPixelClock; 97 | // Bit8u Reserved[189]; // DO NOT PUT THIS IN HERE because of Compact Mode Info storage in bios 98 | } ModeInfoBlockCompact; 99 | 100 | typedef struct ModeInfoBlock 101 | { 102 | // Mandatory information for all VBE revisions 103 | Bit16u ModeAttributes; 104 | Bit8u WinAAttributes; 105 | Bit8u WinBAttributes; 106 | Bit16u WinGranularity; 107 | Bit16u WinSize; 108 | Bit16u WinASegment; 109 | Bit16u WinBSegment; 110 | Bit32u WinFuncPtr; 111 | Bit16u BytesPerScanLine; 112 | // Mandatory information for VBE 1.2 and above 113 | Bit16u XResolution; 114 | Bit16u YResolution; 115 | Bit8u XCharSize; 116 | Bit8u YCharSize; 117 | Bit8u NumberOfPlanes; 118 | Bit8u BitsPerPixel; 119 | Bit8u NumberOfBanks; 120 | Bit8u MemoryModel; 121 | Bit8u BankSize; 122 | Bit8u NumberOfImagePages; 123 | Bit8u Reserved_page; 124 | // Direct Color fields (required for direct/6 and YUV/7 memory models) 125 | Bit8u RedMaskSize; 126 | Bit8u RedFieldPosition; 127 | Bit8u GreenMaskSize; 128 | Bit8u GreenFieldPosition; 129 | Bit8u BlueMaskSize; 130 | Bit8u BlueFieldPosition; 131 | Bit8u RsvdMaskSize; 132 | Bit8u RsvdFieldPosition; 133 | Bit8u DirectColorModeInfo; 134 | // Mandatory information for VBE 2.0 and above 135 | Bit32u PhysBasePtr; 136 | Bit32u OffScreenMemOffset; 137 | Bit16u OffScreenMemSize; 138 | // Mandatory information for VBE 3.0 and above 139 | Bit16u LinBytesPerScanLine; 140 | Bit8u BnkNumberOfPages; 141 | Bit8u LinNumberOfPages; 142 | Bit8u LinRedMaskSize; 143 | Bit8u LinRedFieldPosition; 144 | Bit8u LinGreenMaskSize; 145 | Bit8u LinGreenFieldPosition; 146 | Bit8u LinBlueMaskSize; 147 | Bit8u LinBlueFieldPosition; 148 | Bit8u LinRsvdMaskSize; 149 | Bit8u LinRsvdFieldPosition; 150 | Bit32u MaxPixelClock; 151 | Bit8u Reserved[189]; 152 | } ModeInfoBlock; 153 | 154 | typedef struct ModeInfoListItem 155 | { 156 | Bit16u mode; 157 | ModeInfoBlockCompact info; 158 | } ModeInfoListItem; 159 | 160 | // VBE Return Status Info 161 | // AL 162 | #define VBE_RETURN_STATUS_SUPPORTED 0x4F 163 | #define VBE_RETURN_STATUS_UNSUPPORTED 0x00 164 | // AH 165 | #define VBE_RETURN_STATUS_SUCCESSFULL 0x00 166 | #define VBE_RETURN_STATUS_FAILED 0x01 167 | #define VBE_RETURN_STATUS_NOT_SUPPORTED 0x02 168 | #define VBE_RETURN_STATUS_INVALID 0x03 169 | 170 | // VBE Mode Numbers 171 | 172 | #define VBE_MODE_VESA_DEFINED 0x0100 173 | #define VBE_MODE_REFRESH_RATE_USE_CRTC 0x0800 174 | #define VBE_MODE_LINEAR_FRAME_BUFFER 0x4000 175 | #define VBE_MODE_PRESERVE_DISPLAY_MEMORY 0x8000 176 | 177 | // VBE GFX Mode Number 178 | 179 | #define VBE_VESA_MODE_640X400X8 0x100 180 | #define VBE_VESA_MODE_640X480X8 0x101 181 | #define VBE_VESA_MODE_800X600X4 0x102 182 | #define VBE_VESA_MODE_800X600X8 0x103 183 | #define VBE_VESA_MODE_1024X768X4 0x104 184 | #define VBE_VESA_MODE_1024X768X8 0x105 185 | #define VBE_VESA_MODE_1280X1024X4 0x106 186 | #define VBE_VESA_MODE_1280X1024X8 0x107 187 | #define VBE_VESA_MODE_320X200X1555 0x10D 188 | #define VBE_VESA_MODE_320X200X565 0x10E 189 | #define VBE_VESA_MODE_320X200X888 0x10F 190 | #define VBE_VESA_MODE_640X480X1555 0x110 191 | #define VBE_VESA_MODE_640X480X565 0x111 192 | #define VBE_VESA_MODE_640X480X888 0x112 193 | #define VBE_VESA_MODE_800X600X1555 0x113 194 | #define VBE_VESA_MODE_800X600X565 0x114 195 | #define VBE_VESA_MODE_800X600X888 0x115 196 | #define VBE_VESA_MODE_1024X768X1555 0x116 197 | #define VBE_VESA_MODE_1024X768X565 0x117 198 | #define VBE_VESA_MODE_1024X768X888 0x118 199 | #define VBE_VESA_MODE_1280X1024X1555 0x119 200 | #define VBE_VESA_MODE_1280X1024X565 0x11A 201 | #define VBE_VESA_MODE_1280X1024X888 0x11B 202 | #define VBE_VESA_MODE_1600X1200X8 0x11C 203 | #define VBE_VESA_MODE_1600X1200X1555 0x11D 204 | #define VBE_VESA_MODE_1600X1200X565 0x11E 205 | #define VBE_VESA_MODE_1600X1200X888 0x11F 206 | 207 | // BOCHS/PLEX86 'own' mode numbers 208 | #define VBE_OWN_MODE_320X200X8888 0x140 209 | #define VBE_OWN_MODE_640X400X8888 0x141 210 | #define VBE_OWN_MODE_640X480X8888 0x142 211 | #define VBE_OWN_MODE_800X600X8888 0x143 212 | #define VBE_OWN_MODE_1024X768X8888 0x144 213 | #define VBE_OWN_MODE_1280X1024X8888 0x145 214 | #define VBE_OWN_MODE_320X200X8 0x146 215 | #define VBE_OWN_MODE_1600X1200X8888 0x147 216 | #define VBE_OWN_MODE_1152X864X8 0x148 217 | #define VBE_OWN_MODE_1152X864X1555 0x149 218 | #define VBE_OWN_MODE_1152X864X565 0x14a 219 | #define VBE_OWN_MODE_1152X864X888 0x14b 220 | #define VBE_OWN_MODE_1152X864X8888 0x14c 221 | 222 | #define VBE_VESA_MODE_END_OF_LIST 0xFFFF 223 | 224 | // Capabilities 225 | 226 | #define VBE_CAPABILITY_8BIT_DAC 0x0001 227 | #define VBE_CAPABILITY_NOT_VGA_COMPATIBLE 0x0002 228 | #define VBE_CAPABILITY_RAMDAC_USE_BLANK_BIT 0x0004 229 | #define VBE_CAPABILITY_STEREOSCOPIC_SUPPORT 0x0008 230 | #define VBE_CAPABILITY_STEREO_VIA_VESA_EVC 0x0010 231 | 232 | // Mode Attributes 233 | 234 | #define VBE_MODE_ATTRIBUTE_SUPPORTED 0x0001 235 | #define VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE 0x0002 236 | #define VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT 0x0004 237 | #define VBE_MODE_ATTRIBUTE_COLOR_MODE 0x0008 238 | #define VBE_MODE_ATTRIBUTE_GRAPHICS_MODE 0x0010 239 | #define VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE 0x0020 240 | #define VBE_MODE_ATTRIBUTE_NO_VGA_COMPATIBLE_WINDOW 0x0040 241 | #define VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE 0x0080 242 | #define VBE_MODE_ATTRIBUTE_DOUBLE_SCAN_MODE 0x0100 243 | #define VBE_MODE_ATTRIBUTE_INTERLACE_MODE 0x0200 244 | #define VBE_MODE_ATTRIBUTE_HARDWARE_TRIPLE_BUFFER 0x0400 245 | #define VBE_MODE_ATTRIBUTE_HARDWARE_STEREOSCOPIC_DISPLAY 0x0800 246 | #define VBE_MODE_ATTRIBUTE_DUAL_DISPLAY_START_ADDRESS 0x1000 247 | 248 | #define VBE_MODE_ATTTRIBUTE_LFB_ONLY ( VBE_MODE_ATTRIBUTE_NO_VGA_COMPATIBLE_WINDOW | VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE ) 249 | 250 | // Window attributes 251 | 252 | #define VBE_WINDOW_ATTRIBUTE_RELOCATABLE 0x01 253 | #define VBE_WINDOW_ATTRIBUTE_READABLE 0x02 254 | #define VBE_WINDOW_ATTRIBUTE_WRITEABLE 0x04 255 | 256 | // Memory model 257 | 258 | #define VBE_MEMORYMODEL_TEXT_MODE 0x00 259 | #define VBE_MEMORYMODEL_CGA_GRAPHICS 0x01 260 | #define VBE_MEMORYMODEL_HERCULES_GRAPHICS 0x02 261 | #define VBE_MEMORYMODEL_PLANAR 0x03 262 | #define VBE_MEMORYMODEL_PACKED_PIXEL 0x04 263 | #define VBE_MEMORYMODEL_NON_CHAIN_4_256 0x05 264 | #define VBE_MEMORYMODEL_DIRECT_COLOR 0x06 265 | #define VBE_MEMORYMODEL_YUV 0x07 266 | 267 | // DirectColorModeInfo 268 | 269 | #define VBE_DIRECTCOLOR_COLOR_RAMP_PROGRAMMABLE 0x01 270 | #define VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE 0x02 271 | 272 | // GUEST <-> HOST Communication API 273 | 274 | // FIXME: either dynamicly ask host for this or put somewhere high in physical memory 275 | // like 0xE0000000 276 | 277 | 278 | #define VBE_DISPI_BANK_ADDRESS 0xA0000 279 | #define VBE_DISPI_BANK_SIZE_KB 64 280 | 281 | #define VBE_DISPI_MAX_XRES 2560 282 | #define VBE_DISPI_MAX_YRES 1600 283 | 284 | #define VBE_DISPI_IOPORT_INDEX 0x01CE 285 | #define VBE_DISPI_IOPORT_DATA 0x01CF 286 | 287 | #define VBE_DISPI_INDEX_ID 0x0 288 | #define VBE_DISPI_INDEX_XRES 0x1 289 | #define VBE_DISPI_INDEX_YRES 0x2 290 | #define VBE_DISPI_INDEX_BPP 0x3 291 | #define VBE_DISPI_INDEX_ENABLE 0x4 292 | #define VBE_DISPI_INDEX_BANK 0x5 293 | #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 294 | #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 295 | #define VBE_DISPI_INDEX_X_OFFSET 0x8 296 | #define VBE_DISPI_INDEX_Y_OFFSET 0x9 297 | #define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa 298 | 299 | #define VBE_DISPI_ID0 0xB0C0 300 | #define VBE_DISPI_ID1 0xB0C1 301 | #define VBE_DISPI_ID2 0xB0C2 302 | #define VBE_DISPI_ID3 0xB0C3 303 | #define VBE_DISPI_ID4 0xB0C4 304 | #define VBE_DISPI_ID5 0xB0C5 305 | 306 | #define VBE_DISPI_DISABLED 0x00 307 | #define VBE_DISPI_ENABLED 0x01 308 | #define VBE_DISPI_GETCAPS 0x02 309 | #define VBE_DISPI_8BIT_DAC 0x20 310 | #define VBE_DISPI_LFB_ENABLED 0x40 311 | #define VBE_DISPI_NOCLEARMEM 0x80 312 | 313 | #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 314 | 315 | #endif 316 | -------------------------------------------------------------------------------- /vbe_display_api.txt: -------------------------------------------------------------------------------- 1 | VBE Display API 2 | ------------------------------------------------------------------------------------------------------------- 3 | This document is part of the Bochs/VBEBios documentation, 4 | it specifies the bochs host <-> vbebios client communication. 5 | 6 | That means, the display code implementation and the vbebios code depend 7 | very heavily on each other. As such, this documents needs be synchronised 8 | between bochs CVS and the vgabios CVS. 9 | 10 | This document does not describe how the VBEBios implements the VBE2/3 spec. 11 | This document does not describe how the Bochs display code will display gfx based upon this spec. 12 | 13 | 14 | API History 15 | ----------- 16 | 0xb0c0 supports the following VBE_DISPI_ interfaces (present in Bochs 1.4): 17 | VBE_DISPI_INDEX_ID 18 | VBE_DISPI_INDEX_XRES 19 | VBE_DISPI_INDEX_YRES 20 | VBE_DISPI_INDEX_BPP 21 | VBE_DISPI_INDEX_ENABLE 22 | VBE_DISPI_INDEX_BANK 23 | 24 | Bpp format supported is: 25 | VBE_DISPI_BPP_8 26 | 27 | 0xb0c1 supports 0xb0c0 VBE_DISPI_ interfaces, additional interfaces (present in Bochs 2.0): 28 | VBE_DISPI_INDEX_VIRT_WIDTH 29 | VBE_DISPI_INDEX_VIRT_HEIGHT 30 | VBE_DISPI_INDEX_X_OFFSET 31 | VBE_DISPI_INDEX_Y_OFFSET 32 | 33 | 0xb0c2 supports 0xb0c1 VBE_DISPI_ interfaces, interfaces updated for 34 | additional features (present in Bochs 2.1): 35 | VBE_DISPI_INDEX_BPP supports >8bpp color depth (value = bits) 36 | VBE_DISPI_INDEX_ENABLE supports new flags VBE_DISPI_NOCLEARMEM and VBE_DISPI_LFB_ENABLED 37 | VBE i/o registers changed from 0xFF80/81 to 0x01CE/CF 38 | 39 | 0xb0c3 supports 0xb0c2 VBE_DISPI_ interfaces, interfaces updated for 40 | additional features: 41 | VBE_DISPI_INDEX_ENABLE supports new flags VBE_DISPI_GETCAPS and VBE_DISPI_8BIT_DAC 42 | 43 | 0xb0c4 VBE video memory increased to 8 MB 44 | 45 | 46 | History 47 | ------- 48 | Version 0.6 2002 Nov 23 Jeroen Janssen 49 | - Added LFB support 50 | - Added Virt width, height and x,y offset 51 | 52 | Version 0.5 2002 March 08 Jeroen Janssen 53 | - Added documentation about panic behaviour / current limits of the data values. 54 | - Changed BPP API (in order to include future (A)RGB formats) 55 | - Initial version (based upon extended display text of the vbe bochs display patch) 56 | 57 | 58 | Todo 59 | ---- 60 | Version 0.6+ [random order] 61 | - Add lots of different (A)RGB formats 62 | 63 | References 64 | ---------- 65 | [VBE3] VBE 3 Specification at 66 | http://www.vesa.org/vbe3.pdf 67 | 68 | [BOCHS] Bochs Open Source IA-32 Emulator at 69 | http://bochs.sourceforge.net 70 | 71 | [VBEBIOS] VBE Bios for Bochs at 72 | http://savannah.gnu.org/projects/vgabios/ 73 | 74 | [Screenshots] Screenshots of programs using the VBE Bios at 75 | http://japj.org/projects/bochs_plex86/screenshots.html 76 | 77 | Abbreviations 78 | ------------- 79 | VBE Vesa Bios Extension 80 | DISPI (Bochs) Display Interface 81 | BPP Bits Per Pixel 82 | LFB Linear Frame Buffer 83 | 84 | 85 | #defines 86 | -------- 87 | vbetables-gen.c 88 | #define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 8 89 | 90 | vbe.h 91 | #define VBE_DISPI_BANK_ADDRESS 0xA0000 92 | #define VBE_DISPI_BANK_SIZE_KB 64 93 | 94 | #define VBE_DISPI_MAX_XRES 1024 95 | #define VBE_DISPI_MAX_YRES 768 96 | 97 | #define VBE_DISPI_IOPORT_INDEX 0x01CE 98 | #define VBE_DISPI_IOPORT_DATA 0x01CF 99 | 100 | #define VBE_DISPI_INDEX_ID 0x0 101 | #define VBE_DISPI_INDEX_XRES 0x1 102 | #define VBE_DISPI_INDEX_YRES 0x2 103 | #define VBE_DISPI_INDEX_BPP 0x3 104 | #define VBE_DISPI_INDEX_ENABLE 0x4 105 | #define VBE_DISPI_INDEX_BANK 0x5 106 | #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 107 | #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 108 | #define VBE_DISPI_INDEX_X_OFFSET 0x8 109 | #define VBE_DISPI_INDEX_Y_OFFSET 0x9 110 | 111 | #define VBE_DISPI_ID0 0xB0C0 112 | #define VBE_DISPI_ID1 0xB0C1 113 | #define VBE_DISPI_ID2 0xB0C2 114 | #define VBE_DISPI_ID3 0xB0C3 115 | #define VBE_DISPI_ID4 0xB0C4 116 | 117 | #define VBE_DISPI_DISABLED 0x00 118 | #define VBE_DISPI_ENABLED 0x01 119 | #define VBE_DISPI_VBE_ENABLED 0x40 120 | #define VBE_DISPI_NOCLEARMEM 0x80 121 | 122 | #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 123 | 124 | API 125 | --- 126 | The display api works by using a index (VBE_DISPI_IOPORT_INDEX) and 127 | data (VBE_DISPI_IOPORT_DATA) ioport. One writes the index of the parameter to the index port. 128 | Next, the parameter value can be read or written. 129 | 130 | [0xb0c0] 131 | * VBE_DISPI_INDEX_ID : WORD {R,W} 132 | This parameter can be used to detect the current display API (both bochs & vbebios). 133 | The bios writes VBE_DISPI_ID0 to the dataport and reads it back again. 134 | This way, the display code knows the vbebios 'ID' and the vbebios can check if the correct 135 | display code is present. 136 | As a result, a PANIC can be generated if an incompatible vbebios/display code combination is detected. 137 | This panic can be generated from the bochs display code (NOT the bios, see Notes). 138 | 139 | Example values: VBE_DISPI_ID0 140 | 141 | * VBE_DISPI_INDEX_XRES : WORD {R,W} 142 | This parameter can be used to read/write the vbe display X resolution (in pixels). 143 | It's illegal to set the XRES when the VBE is enabled (display code should generate PANIC). 144 | 145 | If the value written exceeds VBE_DISPI_MAX_XRES, the display code needs to generate a PANIC. 146 | 147 | Example values: 320,640,800,1024 148 | 149 | * VBE_DISPI_INDEX_YRES : WORD {R,W} 150 | This parameter can be used to read/write the vbe display Y resolution (in pixels). 151 | It's illegal to set the YRES when the VBE is enabled (display code should generate PANIC). 152 | 153 | If the value written exceeds VBE_DISPI_MAX_YRES, the display code needs to generate a PANIC. 154 | 155 | Example values: 200,400,480,600,768 156 | 157 | * VBE_DISPI_INDEX_BPP : WORD {R,W} 158 | This parameter can be used to read/write the vbe display BPP. 159 | It's illegal to set the BPP when the VBE is enabled (display code should generate PANIC). 160 | 161 | If the value written is an incompatible BPP, the display code needs to generate a PANIC. 162 | 163 | Example values: VBE_DISPI_BPP_8 164 | 165 | * VBE_DISPI_INDEX_ENABLE : WORD {R,W} 166 | This parameter can be used to read/write the vbe ENABLED state. 167 | If the bios writes VBE_DISPI_ENABLED then the display code will setup a hostside display mode 168 | with the current XRES, YRES and BPP settings. 169 | If the bios write VBE_DISPI_DISABLED then the display code will switch back to normal vga mode behaviour. 170 | 171 | Example values: VBE_DISPI_ENABLED, VBE_DISPI_DISABLED 172 | 173 | * VBE_DISPI_INDEX_BANK : WORD {R,W} 174 | This parameter can be used to read/write the current selected BANK (at 0xA0000). 175 | This can be used for switching banks in banked mode. 176 | 177 | [0xb0c1] 178 | * VBE_DISPI_INDEX_VIRT_WIDTH : WORD {R,W} 179 | This parameter can be used to read/write the current virtual width. 180 | Upon enabling a mode, this will be set to the current xres 181 | Setting this field during enabled mode will result in the virtual width to be changed. 182 | Value will be adjusted if current setting is not possible. 183 | 184 | * VBE_DISPI_INDEX_VIRT_HEIGHT : WORD {R} 185 | This parameter can be read in order to obtain the current virtual height. 186 | This setting will be adjusted after setting a virtual width in order to stay within limit of video memory. 187 | 188 | * VBE_DISPI_INDEX_X_OFFSET : WORD {R,W} 189 | The current X offset (in pixels!) of the visible screen part. 190 | Writing a new offset will also result in a complete screen refresh. 191 | 192 | * VBE_DISPI_INDEX_Y_OFFSET : WORD {R,W} 193 | The current Y offset (in pixels!) of the visible screen part. 194 | Writing a new offset will also result in a complete screen refresh. 195 | 196 | 197 | [0xb0c2] 198 | * VBE_DISPI_INDEX_BPP : WORD {R,W} 199 | The value written is now the number of bits per pixel. A value of 0 is treated 200 | the same as 8 for backward compatibilty. These values are supported: 8, 15, 201 | 16, 24 and 32. The value of 4 is not yet handled in the VBE code. 202 | * VBE_DISPI_INDEX_ENABLE : WORD {R,W} 203 | The new flag VBE_DISPI_NOCLEARMEM allows to preserve the VBE video memory. 204 | The new flag VBE_DISPI_LFB_ENABLED indicates the usage of the LFB. 205 | 206 | [0xb0c3] 207 | * VBE_DISPI_INDEX_ENABLE : WORD {R,W} 208 | If the new flag VBE_DISPI_GETCAPS is enabled, the xres, yres and bpp registers 209 | return the gui capabilities. 210 | The new flag VBE_DISPI_8BIT_DAC switches the DAC to 8 bit mode. 211 | 212 | [0xb0c4] 213 | * VBE_DISPI_TOTAL_VIDEO_MEMORY_MB set to 8 (moved to auto-generated vbetables.h) 214 | 215 | Displaying GFX (banked mode) 216 | -------------- 217 | What happens is that the total screen is devided in banks of 'VBE_DISPI_BANK_SIZE_KB' KiloByte in size. 218 | If you want to set a pixel you can calculate its bank by doing: 219 | 220 | offset = pixel_x + pixel_y * resolution_x; 221 | bank = offset / 64 Kb (rounded 1.9999 -> 1) 222 | 223 | bank_pixel_pos = offset - bank * 64Kb 224 | 225 | Now you can set the current bank and put the pixel at VBE_DISPI_BANK_ADDRESS + bank_pixel_pos 226 | 227 | Displaying GFX (linear frame buffer mode) 228 | -------------- 229 | NOT WRITTEN YET 230 | 231 | Notes 232 | ----- 233 | * Since the XRES/YRES/BPP may not be written when VBE is enabled, if you want to switch from one VBE mode 234 | to another, you will need to disable VBE first. 235 | 236 | * Note when the bios doesn't find a valid DISPI_ID, it can disable the VBE functions. This allows people to 237 | use the same bios for both vbe enabled and disabled bochs executables. 238 | -------------------------------------------------------------------------------- /vbetables-gen.c: -------------------------------------------------------------------------------- 1 | /* Generate the VGABIOS VBE Tables */ 2 | #include 3 | #include 4 | 5 | #define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 16 6 | 7 | typedef struct { 8 | int width; 9 | int height; 10 | int depth; 11 | int mode; 12 | } ModeInfo; 13 | 14 | ModeInfo modes[] = { 15 | /* standard VESA modes */ 16 | { 640, 400, 8 , 0x100}, 17 | { 640, 480, 8 , 0x101}, 18 | { 800, 600, 4 , 0x102}, 19 | { 800, 600, 8 , 0x103}, 20 | { 1024, 768, 4 , 0x104}, 21 | { 1024, 768, 8 , 0x105}, 22 | { 1280, 1024, 4 , 0x106}, 23 | { 1280, 1024, 8 , 0x107}, 24 | { 320, 200, 15 , 0x10D}, 25 | { 320, 200, 16 , 0x10E}, 26 | { 320, 200, 24 , 0x10F}, 27 | { 640, 480, 15 , 0x110}, 28 | { 640, 480, 16 , 0x111}, 29 | { 640, 480, 24 , 0x112}, 30 | { 800, 600, 15 , 0x113}, 31 | { 800, 600, 16 , 0x114}, 32 | { 800, 600, 24 , 0x115}, 33 | { 1024, 768, 15 , 0x116}, 34 | { 1024, 768, 16 , 0x117}, 35 | { 1024, 768, 24 , 0x118}, 36 | { 1280, 1024, 15 , 0x119}, 37 | { 1280, 1024, 16 , 0x11A}, 38 | { 1280, 1024, 24 , 0x11B}, 39 | { 1600, 1200, 8 , 0x11C}, 40 | { 1600, 1200, 15 , 0x11D}, 41 | { 1600, 1200, 16 , 0x11E}, 42 | { 1600, 1200, 24 , 0x11F}, 43 | 44 | /* BOCHS/PLEX86 'own' mode numbers */ 45 | { 320, 200, 32 , 0x140}, 46 | { 640, 400, 32 , 0x141}, 47 | { 640, 480, 32 , 0x142}, 48 | { 800, 600, 32 , 0x143}, 49 | { 1024, 768, 32 , 0x144}, 50 | { 1280, 1024, 32 , 0x145}, 51 | { 320, 200, 8 , 0x146}, 52 | { 1600, 1200, 32 , 0x147}, 53 | { 1152, 864, 8 , 0x148}, 54 | { 1152, 864, 15 , 0x149}, 55 | { 1152, 864, 16 , 0x14a}, 56 | { 1152, 864, 24 , 0x14b}, 57 | { 1152, 864, 32 , 0x14c}, 58 | { 1280, 800, 16 , 0x178}, 59 | { 1280, 800, 24 , 0x179}, 60 | { 1280, 800, 32 , 0x17a}, 61 | { 1280, 960, 16 , 0x17b}, 62 | { 1280, 960, 24 , 0x17c}, 63 | { 1280, 960, 32 , 0x17d}, 64 | { 1440, 900, 16 , 0x17e}, 65 | { 1440, 900, 24 , 0x17f}, 66 | { 1440, 900, 32 , 0x180}, 67 | { 1400, 1050, 16 , 0x181}, 68 | { 1400, 1050, 24 , 0x182}, 69 | { 1400, 1050, 32 , 0x183}, 70 | { 1680, 1050, 16 , 0x184}, 71 | { 1680, 1050, 24 , 0x185}, 72 | { 1680, 1050, 32 , 0x186}, 73 | { 1920, 1200, 16 , 0x187}, 74 | { 1920, 1200, 24 , 0x188}, 75 | { 1920, 1200, 32 , 0x189}, 76 | { 2560, 1600, 16 , 0x18a}, 77 | { 2560, 1600, 24 , 0x18b}, 78 | { 2560, 1600, 32 , 0x18c}, 79 | { 0, }, 80 | }; 81 | 82 | int main(int argc, char **argv) 83 | { 84 | const ModeInfo *pm; 85 | int pages, pitch; 86 | int r_size, r_pos, g_size, g_pos, b_size, b_pos, a_size, a_pos; 87 | const char *str; 88 | long vram_size = VBE_DISPI_TOTAL_VIDEO_MEMORY_MB * 1024 * 1024; 89 | 90 | printf("/* THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT */\n\n"); 91 | printf("#define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB %d\n\n", VBE_DISPI_TOTAL_VIDEO_MEMORY_MB); 92 | printf("static ModeInfoListItem mode_info_list[]=\n"); 93 | printf("{\n"); 94 | for (pm = modes; pm->mode != 0; pm++) { 95 | if (pm->depth == 4) 96 | pitch = (pm->width + 7) / 8; 97 | else 98 | pitch = pm->width * ((pm->depth + 7) / 8); 99 | pages = vram_size / (pm->height * pitch); 100 | if (pages > 0) { 101 | printf("{ 0x%04x, /* %dx%dx%d */\n", 102 | pm->mode, pm->width, pm->height, pm->depth); 103 | if (pm->depth == 4) 104 | printf("{ /*Bit16u ModeAttributes*/ %s,\n", 105 | "VBE_MODE_ATTRIBUTE_SUPPORTED | " 106 | "VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE | " 107 | "VBE_MODE_ATTRIBUTE_COLOR_MODE | " 108 | "VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT | " 109 | "VBE_MODE_ATTRIBUTE_GRAPHICS_MODE"); 110 | else 111 | printf("{ /*Bit16u ModeAttributes*/ %s,\n", 112 | "VBE_MODE_ATTRIBUTE_SUPPORTED | " 113 | "VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE | " 114 | "VBE_MODE_ATTRIBUTE_COLOR_MODE | " 115 | "VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE | " 116 | "VBE_MODE_ATTRIBUTE_GRAPHICS_MODE"); 117 | printf("/*Bit8u WinAAttributes*/ %s,\n", 118 | "VBE_WINDOW_ATTRIBUTE_RELOCATABLE | " 119 | "VBE_WINDOW_ATTRIBUTE_READABLE | " 120 | "VBE_WINDOW_ATTRIBUTE_WRITEABLE"); 121 | 122 | printf("/*Bit8u WinBAttributes*/ %d,\n", 0); 123 | 124 | printf("/*Bit16u WinGranularity*/ %s,\n", "VBE_DISPI_BANK_SIZE_KB"); 125 | 126 | printf("/*Bit16u WinSize*/ %s,\n", "VBE_DISPI_BANK_SIZE_KB"); 127 | 128 | printf("/*Bit16u WinASegment*/ %s,\n", "VGAMEM_GRAPH"); 129 | 130 | printf("/*Bit16u WinBSegment*/ 0x%04x,\n", 0); 131 | 132 | printf("/*Bit32u WinFuncPtr*/ %d,\n", 0); 133 | 134 | printf("/*Bit16u BytesPerScanLine*/ %d,\n", pitch); 135 | 136 | // Mandatory information for VBE 1.2 and above 137 | printf("/*Bit16u XResolution*/ %d,\n", pm->width); 138 | printf("/*Bit16u YResolution*/ %d,\n", pm->height); 139 | printf("/*Bit8u XCharSize*/ %d,\n", 8); 140 | printf("/*Bit8u YCharSize*/ %d,\n", 16); 141 | if (pm->depth == 4) { 142 | printf("/*Bit8u NumberOfPlanes*/ %d,\n", 4); 143 | } else { 144 | printf("/*Bit8u NumberOfPlanes*/ %d,\n", 1); 145 | } 146 | printf("/*Bit8u BitsPerPixel*/ %d,\n", pm->depth); 147 | printf("/*Bit8u NumberOfBanks*/ %d,\n", 148 | (pm->height * pitch + 65535) / 65536); 149 | 150 | if (pm->depth == 4) 151 | str = "VBE_MEMORYMODEL_PLANAR"; 152 | else if (pm->depth == 8) 153 | str = "VBE_MEMORYMODEL_PACKED_PIXEL"; 154 | else 155 | str = "VBE_MEMORYMODEL_DIRECT_COLOR"; 156 | printf("/*Bit8u MemoryModel*/ %s,\n", str); 157 | printf("/*Bit8u BankSize*/ %d,\n", 0); 158 | if (pm->depth == 4) 159 | printf("/*Bit8u NumberOfImagePages*/ %d,\n", (pages / 4) - 1); 160 | else 161 | printf("/*Bit8u NumberOfImagePages*/ %d,\n", pages - 1); 162 | printf("/*Bit8u Reserved_page*/ %d,\n", 0); 163 | 164 | // Direct Color fields (required for direct/6 and YUV/7 memory models) 165 | switch(pm->depth) { 166 | case 15: 167 | r_size = 5; 168 | r_pos = 10; 169 | g_size = 5; 170 | g_pos = 5; 171 | b_size = 5; 172 | b_pos = 0; 173 | a_size = 1; 174 | a_pos = 15; 175 | break; 176 | case 16: 177 | r_size = 5; 178 | r_pos = 11; 179 | g_size = 6; 180 | g_pos = 5; 181 | b_size = 5; 182 | b_pos = 0; 183 | a_size = 0; 184 | a_pos = 0; 185 | break; 186 | case 24: 187 | r_size = 8; 188 | r_pos = 16; 189 | g_size = 8; 190 | g_pos = 8; 191 | b_size = 8; 192 | b_pos = 0; 193 | a_size = 0; 194 | a_pos = 0; 195 | break; 196 | case 32: 197 | r_size = 8; 198 | r_pos = 16; 199 | g_size = 8; 200 | g_pos = 8; 201 | b_size = 8; 202 | b_pos = 0; 203 | a_size = 8; 204 | a_pos = 24; 205 | break; 206 | default: 207 | r_size = 0; 208 | r_pos = 0; 209 | g_size = 0; 210 | g_pos = 0; 211 | b_size = 0; 212 | b_pos = 0; 213 | a_size = 0; 214 | a_pos = 0; 215 | break; 216 | } 217 | 218 | printf("/*Bit8u RedMaskSize*/ %d,\n", r_size); 219 | printf("/*Bit8u RedFieldPosition*/ %d,\n", r_pos); 220 | printf("/*Bit8u GreenMaskSize*/ %d,\n", g_size); 221 | printf("/*Bit8u GreenFieldPosition*/ %d,\n", g_pos); 222 | printf("/*Bit8u BlueMaskSize*/ %d,\n", b_size); 223 | printf("/*Bit8u BlueFieldPosition*/ %d,\n", b_pos); 224 | printf("/*Bit8u RsvdMaskSize*/ %d,\n", a_size); 225 | printf("/*Bit8u RsvdFieldPosition*/ %d,\n", a_pos); 226 | if (pm->depth == 32) 227 | printf("/*Bit8u DirectColorModeInfo*/ %s,\n", 228 | "VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE"); 229 | else 230 | printf("/*Bit8u DirectColorModeInfo*/ %s,\n", "0"); 231 | 232 | // Mandatory information for VBE 2.0 and above 233 | if (pm->depth > 4) 234 | printf("/*Bit32u PhysBasePtr*/ %s,\n", 235 | "VBE_DISPI_LFB_PHYSICAL_ADDRESS"); 236 | else 237 | printf("/*Bit32u PhysBasePtr*/ %s,\n", "0"); 238 | printf("/*Bit32u OffScreenMemOffset*/ %d,\n", 0); 239 | printf("/*Bit16u OffScreenMemSize*/ %d,\n", 0); 240 | // Mandatory information for VBE 3.0 and above 241 | printf("/*Bit16u LinBytesPerScanLine*/ %d,\n", pitch); 242 | printf("/*Bit8u BnkNumberOfPages*/ %d,\n", 0); 243 | printf("/*Bit8u LinNumberOfPages*/ %d,\n", 0); 244 | printf("/*Bit8u LinRedMaskSize*/ %d,\n", r_size); 245 | printf("/*Bit8u LinRedFieldPosition*/ %d,\n", r_pos); 246 | printf("/*Bit8u LinGreenMaskSize*/ %d,\n", g_size); 247 | printf("/*Bit8u LinGreenFieldPosition*/ %d,\n", g_pos); 248 | printf("/*Bit8u LinBlueMaskSize*/ %d,\n", b_size); 249 | printf("/*Bit8u LinBlueFieldPosition*/ %d,\n", b_pos); 250 | printf("/*Bit8u LinRsvdMaskSize*/ %d,\n", a_size); 251 | printf("/*Bit8u LinRsvdFieldPosition*/ %d,\n", a_pos); 252 | printf("/*Bit32u MaxPixelClock*/ %d,\n", 0); 253 | printf("} },\n"); 254 | } 255 | } 256 | printf("{ VBE_VESA_MODE_END_OF_LIST,\n"); 257 | printf("{ 0,\n"); 258 | printf("} },\n"); 259 | printf("};\n"); 260 | return 0; 261 | } 262 | -------------------------------------------------------------------------------- /vgabios.h: -------------------------------------------------------------------------------- 1 | #ifndef vgabios_h_included 2 | #define vgabios_h_included 3 | 4 | /* Types */ 5 | typedef unsigned char Bit8u; 6 | typedef unsigned short Bit16u; 7 | typedef unsigned long Bit32u; 8 | typedef unsigned short Boolean; 9 | 10 | /* Defines */ 11 | 12 | #define SET_AL(val8) AX = ((AX & 0xff00) | (val8)) 13 | #define SET_BL(val8) BX = ((BX & 0xff00) | (val8)) 14 | #define SET_CL(val8) CX = ((CX & 0xff00) | (val8)) 15 | #define SET_DL(val8) DX = ((DX & 0xff00) | (val8)) 16 | #define SET_AH(val8) AX = ((AX & 0x00ff) | ((val8) << 8)) 17 | #define SET_BH(val8) BX = ((BX & 0x00ff) | ((val8) << 8)) 18 | #define SET_CH(val8) CX = ((CX & 0x00ff) | ((val8) << 8)) 19 | #define SET_DH(val8) DX = ((DX & 0x00ff) | ((val8) << 8)) 20 | 21 | #define GET_AL() ( AX & 0x00ff ) 22 | #define GET_BL() ( BX & 0x00ff ) 23 | #define GET_CL() ( CX & 0x00ff ) 24 | #define GET_DL() ( DX & 0x00ff ) 25 | #define GET_AH() ( AX >> 8 ) 26 | #define GET_BH() ( BX >> 8 ) 27 | #define GET_CH() ( CX >> 8 ) 28 | #define GET_DH() ( DX >> 8 ) 29 | 30 | #define SET_CF() FLAGS |= 0x0001 31 | #define CLEAR_CF() FLAGS &= 0xfffe 32 | #define GET_CF() (FLAGS & 0x0001) 33 | 34 | #define SET_ZF() FLAGS |= 0x0040 35 | #define CLEAR_ZF() FLAGS &= 0xffbf 36 | #define GET_ZF() (FLAGS & 0x0040) 37 | 38 | #define SCROLL_DOWN 0 39 | #define SCROLL_UP 1 40 | #define NO_ATTR 2 41 | #define WITH_ATTR 3 42 | 43 | #define SCREEN_SIZE(x,y) (((x*y*2)|0x00ff)+1) 44 | #define SCREEN_MEM_START(x,y,p) ((((x*y*2)|0x00ff)+1)*p) 45 | #define SCREEN_IO_START(x,y,p) ((((x*y)|0x00ff)+1)*p) 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /vgatables.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * BIOS Memory 4 | * 5 | */ 6 | #define BIOSMEM_SEG 0x40 7 | 8 | #define BIOSMEM_INITIAL_MODE 0x10 9 | #define BIOSMEM_CURRENT_MODE 0x49 10 | #define BIOSMEM_NB_COLS 0x4A 11 | #define BIOSMEM_PAGE_SIZE 0x4C 12 | #define BIOSMEM_CURRENT_START 0x4E 13 | #define BIOSMEM_CURSOR_POS 0x50 14 | #define BIOSMEM_CURSOR_TYPE 0x60 15 | #define BIOSMEM_CURRENT_PAGE 0x62 16 | #define BIOSMEM_CRTC_ADDRESS 0x63 17 | #define BIOSMEM_CURRENT_MSR 0x65 18 | #define BIOSMEM_CURRENT_PAL 0x66 19 | #define BIOSMEM_NB_ROWS 0x84 20 | #define BIOSMEM_CHAR_HEIGHT 0x85 21 | #define BIOSMEM_VIDEO_CTL 0x87 22 | #define BIOSMEM_SWITCHES 0x88 23 | #define BIOSMEM_MODESET_CTL 0x89 24 | #define BIOSMEM_DCC_INDEX 0x8A 25 | #define BIOSMEM_VS_POINTER 0xA8 26 | #define BIOSMEM_VBE_FLAG 0xB9 27 | #define BIOSMEM_VBE_MODE 0xBA 28 | 29 | 30 | /* 31 | * 32 | * VGA registers 33 | * 34 | */ 35 | #define VGAREG_ACTL_ADDRESS 0x3c0 36 | #define VGAREG_ACTL_WRITE_DATA 0x3c0 37 | #define VGAREG_ACTL_READ_DATA 0x3c1 38 | 39 | #define VGAREG_INPUT_STATUS 0x3c2 40 | #define VGAREG_WRITE_MISC_OUTPUT 0x3c2 41 | #define VGAREG_VIDEO_ENABLE 0x3c3 42 | #define VGAREG_SEQU_ADDRESS 0x3c4 43 | #define VGAREG_SEQU_DATA 0x3c5 44 | 45 | #define VGAREG_PEL_MASK 0x3c6 46 | #define VGAREG_DAC_STATE 0x3c7 47 | #define VGAREG_DAC_READ_ADDRESS 0x3c7 48 | #define VGAREG_DAC_WRITE_ADDRESS 0x3c8 49 | #define VGAREG_DAC_DATA 0x3c9 50 | 51 | #define VGAREG_READ_FEATURE_CTL 0x3ca 52 | #define VGAREG_READ_MISC_OUTPUT 0x3cc 53 | 54 | #define VGAREG_GRDC_ADDRESS 0x3ce 55 | #define VGAREG_GRDC_DATA 0x3cf 56 | 57 | #define VGAREG_MDA_CRTC_ADDRESS 0x3b4 58 | #define VGAREG_MDA_CRTC_DATA 0x3b5 59 | #define VGAREG_VGA_CRTC_ADDRESS 0x3d4 60 | #define VGAREG_VGA_CRTC_DATA 0x3d5 61 | 62 | #define VGAREG_MDA_WRITE_FEATURE_CTL 0x3ba 63 | #define VGAREG_VGA_WRITE_FEATURE_CTL 0x3da 64 | #define VGAREG_ACTL_RESET 0x3da 65 | 66 | #define VGAREG_MDA_MODECTL 0x3b8 67 | #define VGAREG_CGA_MODECTL 0x3d8 68 | #define VGAREG_CGA_PALETTE 0x3d9 69 | 70 | /* Video memory */ 71 | #define VGAMEM_GRAPH 0xA000 72 | #define VGAMEM_CTEXT 0xB800 73 | #define VGAMEM_MTEXT 0xB000 74 | 75 | /* 76 | * 77 | * Tables of default values for each mode 78 | * 79 | */ 80 | #define MODE_MAX 15 81 | #define TEXT 0x00 82 | #define GRAPH 0x01 83 | 84 | #define CTEXT 0x00 85 | #define MTEXT 0x01 86 | #define CGA 0x02 87 | #define PLANAR1 0x03 88 | #define PLANAR4 0x04 89 | #define LINEAR8 0x05 90 | 91 | // for SVGA 92 | #define LINEAR15 0x10 93 | #define LINEAR16 0x11 94 | #define LINEAR24 0x12 95 | #define LINEAR32 0x13 96 | 97 | typedef struct 98 | {Bit8u svgamode; 99 | Bit8u class; /* TEXT, GRAPH */ 100 | Bit8u memmodel; /* CTEXT,MTEXT,CGA,PL1,PL2,PL4,P8,P15,P16,P24,P32 */ 101 | Bit8u pixbits; 102 | Bit16u sstart; 103 | Bit8u pelmask; 104 | Bit8u dacmodel; /* 0 1 2 3 */ 105 | } VGAMODES; 106 | 107 | static VGAMODES vga_modes[MODE_MAX+1]= 108 | {//mode class model bits sstart pelm dac 109 | {0x00, TEXT, CTEXT, 4, 0xB800, 0xFF, 0x02}, 110 | {0x01, TEXT, CTEXT, 4, 0xB800, 0xFF, 0x02}, 111 | {0x02, TEXT, CTEXT, 4, 0xB800, 0xFF, 0x02}, 112 | {0x03, TEXT, CTEXT, 4, 0xB800, 0xFF, 0x02}, 113 | {0x04, GRAPH, CGA, 2, 0xB800, 0xFF, 0x01}, 114 | {0x05, GRAPH, CGA, 2, 0xB800, 0xFF, 0x01}, 115 | {0x06, GRAPH, CGA, 1, 0xB800, 0xFF, 0x01}, 116 | {0x07, TEXT, MTEXT, 4, 0xB000, 0xFF, 0x00}, 117 | {0x0D, GRAPH, PLANAR4, 4, 0xA000, 0xFF, 0x01}, 118 | {0x0E, GRAPH, PLANAR4, 4, 0xA000, 0xFF, 0x01}, 119 | {0x0F, GRAPH, PLANAR1, 1, 0xA000, 0xFF, 0x00}, 120 | {0x10, GRAPH, PLANAR4, 4, 0xA000, 0xFF, 0x02}, 121 | {0x11, GRAPH, PLANAR1, 1, 0xA000, 0xFF, 0x02}, 122 | {0x12, GRAPH, PLANAR4, 4, 0xA000, 0xFF, 0x02}, 123 | {0x13, GRAPH, LINEAR8, 8, 0xA000, 0xFF, 0x03}, 124 | {0x6A, GRAPH, PLANAR4, 4, 0xA000, 0xFF, 0x02} 125 | }; 126 | 127 | /* convert index in vga_modes[] to index in video_param_table[] */ 128 | static Bit8u line_to_vpti[MODE_MAX+1]={ 129 | 0x17, 0x17, 0x18, 0x18, 0x04, 0x05, 0x06, 0x07, 130 | 0x0d, 0x0e, 0x11, 0x12, 0x1a, 0x1b, 0x1c, 0x1d, 131 | }; 132 | 133 | /* Default Palette */ 134 | #define DAC_MAX_MODEL 3 135 | 136 | static Bit8u dac_regs[DAC_MAX_MODEL+1]= 137 | {0x3f,0x3f,0x3f,0xff}; 138 | 139 | /* standard BIOS Video Parameter Table */ 140 | typedef struct { 141 | Bit8u twidth; 142 | Bit8u theightm1; 143 | Bit8u cheight; 144 | Bit8u slength_l; 145 | Bit8u slength_h; 146 | Bit8u sequ_regs[4]; 147 | Bit8u miscreg; 148 | Bit8u crtc_regs[25]; 149 | Bit8u actl_regs[20]; 150 | Bit8u grdc_regs[9]; 151 | } VideoParamTableEntry; 152 | 153 | static VideoParamTableEntry video_param_table[30] = { 154 | { 155 | /* index=0x00 no mode defined */ 156 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 157 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 158 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 159 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 160 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 161 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 162 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 163 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 164 | }, 165 | { 166 | /* index=0x01 no mode defined */ 167 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 168 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 169 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 170 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 171 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 172 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 173 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 174 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 175 | }, 176 | { 177 | /* index=0x02 no mode defined */ 178 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 179 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 180 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 181 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 182 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 183 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 184 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 185 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 186 | }, 187 | { 188 | /* index=0x03 no mode defined */ 189 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 190 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 191 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 193 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 194 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 195 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 196 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 197 | }, 198 | { 199 | /* index=0x04 vga mode 0x04 */ 200 | 40, 24, 8, 0x00, 0x08, /* tw, th-1, ch, slength */ 201 | 0x09, 0x03, 0x00, 0x02, /* sequ_regs */ 202 | 0x63, /* miscreg */ 203 | 0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f, 204 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 205 | 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2, 206 | 0xff, /* crtc_regs */ 207 | 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 208 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 209 | 0x01, 0x00, 0x03, 0x00, /* actl_regs */ 210 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff, /* grdc_regs */ 211 | }, 212 | { 213 | /* index=0x05 vga mode 0x05 */ 214 | 40, 24, 8, 0x00, 0x08, /* tw, th-1, ch, slength */ 215 | 0x09, 0x03, 0x00, 0x02, /* sequ_regs */ 216 | 0x63, /* miscreg */ 217 | 0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f, 218 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 219 | 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2, 220 | 0xff, /* crtc_regs */ 221 | 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 222 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 223 | 0x01, 0x00, 0x03, 0x00, /* actl_regs */ 224 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff, /* grdc_regs */ 225 | }, 226 | { 227 | /* index=0x06 vga mode 0x06 */ 228 | 80, 24, 8, 0x00, 0x10, /* tw, th-1, ch, slength */ 229 | 0x01, 0x01, 0x00, 0x06, /* sequ_regs */ 230 | 0x63, /* miscreg */ 231 | 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, 232 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 233 | 0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xc2, 234 | 0xff, /* crtc_regs */ 235 | 0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 236 | 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 237 | 0x01, 0x00, 0x01, 0x00, /* actl_regs */ 238 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0f, 0xff, /* grdc_regs */ 239 | }, 240 | { 241 | /* index=0x07 vga mode 0x07 */ 242 | 80, 24, 16, 0x00, 0x10, /* tw, th-1, ch, slength */ 243 | 0x00, 0x03, 0x00, 0x02, /* sequ_regs */ 244 | 0x66, /* miscreg */ 245 | 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 246 | 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, 247 | 0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3, 248 | 0xff, /* crtc_regs */ 249 | 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 250 | 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 251 | 0x0e, 0x00, 0x0f, 0x08, /* actl_regs */ 252 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x0f, 0xff, /* grdc_regs */ 253 | }, 254 | { 255 | /* index=0x08 no mode defined */ 256 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 257 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 258 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 259 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 260 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 261 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 262 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 263 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 264 | }, 265 | { 266 | /* index=0x09 no mode defined */ 267 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 268 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 269 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 270 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 271 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 272 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 273 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 274 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 275 | }, 276 | { 277 | /* index=0x0a no mode defined */ 278 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 279 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 280 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 281 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 282 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 283 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 284 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 285 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 286 | }, 287 | { 288 | /* index=0x0b no mode defined */ 289 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 290 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 291 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 292 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 293 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 294 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 295 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 296 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 297 | }, 298 | { 299 | /* index=0x0c no mode defined */ 300 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 301 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 302 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 303 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 304 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 305 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 306 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 307 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 308 | }, 309 | { 310 | /* index=0x0d vga mode 0x0d */ 311 | 40, 24, 8, 0x00, 0x20, /* tw, th-1, ch, slength */ 312 | 0x09, 0x0f, 0x00, 0x06, /* sequ_regs */ 313 | 0x63, /* miscreg */ 314 | 0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f, 315 | 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 316 | 0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xe3, 317 | 0xff, /* crtc_regs */ 318 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 319 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 320 | 0x01, 0x00, 0x0f, 0x00, /* actl_regs */ 321 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ 322 | }, 323 | { 324 | /* index=0x0e vga mode 0x0e */ 325 | 80, 24, 8, 0x00, 0x40, /* tw, th-1, ch, slength */ 326 | 0x01, 0x0f, 0x00, 0x06, /* sequ_regs */ 327 | 0x63, /* miscreg */ 328 | 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, 329 | 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 330 | 0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xe3, 331 | 0xff, /* crtc_regs */ 332 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 333 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 334 | 0x01, 0x00, 0x0f, 0x00, /* actl_regs */ 335 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ 336 | }, 337 | { 338 | /* index=0x0f no mode defined */ 339 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 340 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 341 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 342 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 343 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 344 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 345 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 346 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 347 | }, 348 | { 349 | /* index=0x10 no mode defined */ 350 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 351 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 352 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 353 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 354 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 355 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 356 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 357 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 358 | }, 359 | { 360 | /* index=0x11 vga mode 0x0f */ 361 | 80, 24, 14, 0x00, 0x80, /* tw, th-1, ch, slength */ 362 | 0x01, 0x0f, 0x00, 0x06, /* sequ_regs */ 363 | 0xa3, /* miscreg */ 364 | 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, 365 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 366 | 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3, 367 | 0xff, /* crtc_regs */ 368 | 0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 369 | 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 370 | 0x01, 0x00, 0x01, 0x00, /* actl_regs */ 371 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ 372 | }, 373 | { 374 | /* index=0x12 vga mode 0x10 */ 375 | 80, 24, 14, 0x00, 0x80, /* tw, th-1, ch, slength */ 376 | 0x01, 0x0f, 0x00, 0x06, /* sequ_regs */ 377 | 0xa3, /* miscreg */ 378 | 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, 379 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 380 | 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3, 381 | 0xff, /* crtc_regs */ 382 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 383 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 384 | 0x01, 0x00, 0x0f, 0x00, /* actl_regs */ 385 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ 386 | }, 387 | { 388 | /* index=0x13 no mode defined */ 389 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 390 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 391 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 392 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 393 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 394 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 395 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 396 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 397 | }, 398 | { 399 | /* index=0x14 no mode defined */ 400 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 401 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 402 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 403 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 404 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 405 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 406 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 407 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 408 | }, 409 | { 410 | /* index=0x15 no mode defined */ 411 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 412 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 413 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 414 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 415 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 416 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 417 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 418 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 419 | }, 420 | { 421 | /* index=0x16 no mode defined */ 422 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 423 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 424 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 425 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 426 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 427 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 428 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 429 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 430 | }, 431 | { 432 | /* index=0x17 vga mode 0x01 */ 433 | 40, 24, 16, 0x00, 0x08, /* tw, th-1, ch, slength */ 434 | 0x08, 0x03, 0x00, 0x02, /* sequ_regs */ 435 | 0x67, /* miscreg */ 436 | 0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f, 437 | 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, 438 | 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3, 439 | 0xff, /* crtc_regs */ 440 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 441 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 442 | 0x0c, 0x00, 0x0f, 0x08, /* actl_regs */ 443 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff, /* grdc_regs */ 444 | }, 445 | { 446 | /* index=0x18 vga mode 0x03 */ 447 | 80, 24, 16, 0x00, 0x10, /* tw, th-1, ch, slength */ 448 | 0x00, 0x03, 0x00, 0x02, /* sequ_regs */ 449 | 0x67, /* miscreg */ 450 | 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 451 | 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, 452 | 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, 453 | 0xff, /* crtc_regs */ 454 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 455 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 456 | 0x0c, 0x00, 0x0f, 0x08, /* actl_regs */ 457 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff, /* grdc_regs */ 458 | }, 459 | { 460 | /* index=0x19 vga mode 0x07 */ 461 | 80, 24, 16, 0x00, 0x10, /* tw, th-1, ch, slength */ 462 | 0x00, 0x03, 0x00, 0x02, /* sequ_regs */ 463 | 0x66, /* miscreg */ 464 | 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 465 | 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, 466 | 0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3, 467 | 0xff, /* crtc_regs */ 468 | 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 469 | 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 470 | 0x0e, 0x00, 0x0f, 0x08, /* actl_regs */ 471 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x0f, 0xff, /* grdc_regs */ 472 | }, 473 | { 474 | /* index=0x1a vga mode 0x11 */ 475 | 80, 29, 16, 0x00, 0x00, /* tw, th-1, ch, slength */ 476 | 0x01, 0x0f, 0x00, 0x06, /* sequ_regs */ 477 | 0xe3, /* miscreg */ 478 | 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, 479 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 480 | 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, 481 | 0xff, /* crtc_regs */ 482 | 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 483 | 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 484 | 0x01, 0x00, 0x0f, 0x00, /* actl_regs */ 485 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ 486 | }, 487 | { 488 | /* index=0x1b vga mode 0x12 */ 489 | 80, 29, 16, 0x00, 0x00, /* tw, th-1, ch, slength */ 490 | 0x01, 0x0f, 0x00, 0x06, /* sequ_regs */ 491 | 0xe3, /* miscreg */ 492 | 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, 493 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 494 | 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, 495 | 0xff, /* crtc_regs */ 496 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 497 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 498 | 0x01, 0x00, 0x0f, 0x00, /* actl_regs */ 499 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ 500 | }, 501 | { 502 | /* index=0x1c vga mode 0x13 */ 503 | 40, 24, 8, 0x00, 0x00, /* tw, th-1, ch, slength */ 504 | 0x01, 0x0f, 0x00, 0x0e, /* sequ_regs */ 505 | 0x63, /* miscreg */ 506 | 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, 507 | 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 508 | 0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3, 509 | 0xff, /* crtc_regs */ 510 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 511 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 512 | 0x41, 0x00, 0x0f, 0x00, /* actl_regs */ 513 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff, /* grdc_regs */ 514 | }, 515 | { 516 | /* index=0x1d vga mode 0x6a */ 517 | 100, 36, 16, 0x00, 0x00, /* tw, th-1, ch, slength */ 518 | 0x01, 0x0f, 0x00, 0x06, /* sequ_regs */ 519 | 0xe3, /* miscreg */ 520 | 0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0, 521 | 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 522 | 0x59, 0x8d, 0x57, 0x32, 0x00, 0x57, 0x73, 0xe3, 523 | 0xff, /* crtc_regs */ 524 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 525 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 526 | 0x01, 0x00, 0x0f, 0x00, /* actl_regs */ 527 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, /* grdc_regs */ 528 | }, 529 | }; 530 | 531 | /* Mono */ 532 | static Bit8u palette0[63+1][3]= 533 | { 534 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 535 | 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 536 | 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 537 | 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 538 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 539 | 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 540 | 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 541 | 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f 542 | }; 543 | 544 | static Bit8u palette1[63+1][3]= 545 | { 546 | 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, 547 | 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, 548 | 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, 549 | 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, 550 | 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, 551 | 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, 552 | 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, 553 | 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f 554 | }; 555 | 556 | static Bit8u palette2[63+1][3]= 557 | { 558 | 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a, 559 | 0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f, 0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f, 560 | 0x00,0x15,0x00, 0x00,0x15,0x2a, 0x00,0x3f,0x00, 0x00,0x3f,0x2a, 0x2a,0x15,0x00, 0x2a,0x15,0x2a, 0x2a,0x3f,0x00, 0x2a,0x3f,0x2a, 561 | 0x00,0x15,0x15, 0x00,0x15,0x3f, 0x00,0x3f,0x15, 0x00,0x3f,0x3f, 0x2a,0x15,0x15, 0x2a,0x15,0x3f, 0x2a,0x3f,0x15, 0x2a,0x3f,0x3f, 562 | 0x15,0x00,0x00, 0x15,0x00,0x2a, 0x15,0x2a,0x00, 0x15,0x2a,0x2a, 0x3f,0x00,0x00, 0x3f,0x00,0x2a, 0x3f,0x2a,0x00, 0x3f,0x2a,0x2a, 563 | 0x15,0x00,0x15, 0x15,0x00,0x3f, 0x15,0x2a,0x15, 0x15,0x2a,0x3f, 0x3f,0x00,0x15, 0x3f,0x00,0x3f, 0x3f,0x2a,0x15, 0x3f,0x2a,0x3f, 564 | 0x15,0x15,0x00, 0x15,0x15,0x2a, 0x15,0x3f,0x00, 0x15,0x3f,0x2a, 0x3f,0x15,0x00, 0x3f,0x15,0x2a, 0x3f,0x3f,0x00, 0x3f,0x3f,0x2a, 565 | 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f 566 | }; 567 | 568 | static Bit8u palette3[256][3]= 569 | { 570 | 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, 571 | 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, 572 | 0x00,0x00,0x00, 0x05,0x05,0x05, 0x08,0x08,0x08, 0x0b,0x0b,0x0b, 0x0e,0x0e,0x0e, 0x11,0x11,0x11, 0x14,0x14,0x14, 0x18,0x18,0x18, 573 | 0x1c,0x1c,0x1c, 0x20,0x20,0x20, 0x24,0x24,0x24, 0x28,0x28,0x28, 0x2d,0x2d,0x2d, 0x32,0x32,0x32, 0x38,0x38,0x38, 0x3f,0x3f,0x3f, 574 | 0x00,0x00,0x3f, 0x10,0x00,0x3f, 0x1f,0x00,0x3f, 0x2f,0x00,0x3f, 0x3f,0x00,0x3f, 0x3f,0x00,0x2f, 0x3f,0x00,0x1f, 0x3f,0x00,0x10, 575 | 0x3f,0x00,0x00, 0x3f,0x10,0x00, 0x3f,0x1f,0x00, 0x3f,0x2f,0x00, 0x3f,0x3f,0x00, 0x2f,0x3f,0x00, 0x1f,0x3f,0x00, 0x10,0x3f,0x00, 576 | 0x00,0x3f,0x00, 0x00,0x3f,0x10, 0x00,0x3f,0x1f, 0x00,0x3f,0x2f, 0x00,0x3f,0x3f, 0x00,0x2f,0x3f, 0x00,0x1f,0x3f, 0x00,0x10,0x3f, 577 | 0x1f,0x1f,0x3f, 0x27,0x1f,0x3f, 0x2f,0x1f,0x3f, 0x37,0x1f,0x3f, 0x3f,0x1f,0x3f, 0x3f,0x1f,0x37, 0x3f,0x1f,0x2f, 0x3f,0x1f,0x27, 578 | 579 | 0x3f,0x1f,0x1f, 0x3f,0x27,0x1f, 0x3f,0x2f,0x1f, 0x3f,0x37,0x1f, 0x3f,0x3f,0x1f, 0x37,0x3f,0x1f, 0x2f,0x3f,0x1f, 0x27,0x3f,0x1f, 580 | 0x1f,0x3f,0x1f, 0x1f,0x3f,0x27, 0x1f,0x3f,0x2f, 0x1f,0x3f,0x37, 0x1f,0x3f,0x3f, 0x1f,0x37,0x3f, 0x1f,0x2f,0x3f, 0x1f,0x27,0x3f, 581 | 0x2d,0x2d,0x3f, 0x31,0x2d,0x3f, 0x36,0x2d,0x3f, 0x3a,0x2d,0x3f, 0x3f,0x2d,0x3f, 0x3f,0x2d,0x3a, 0x3f,0x2d,0x36, 0x3f,0x2d,0x31, 582 | 0x3f,0x2d,0x2d, 0x3f,0x31,0x2d, 0x3f,0x36,0x2d, 0x3f,0x3a,0x2d, 0x3f,0x3f,0x2d, 0x3a,0x3f,0x2d, 0x36,0x3f,0x2d, 0x31,0x3f,0x2d, 583 | 0x2d,0x3f,0x2d, 0x2d,0x3f,0x31, 0x2d,0x3f,0x36, 0x2d,0x3f,0x3a, 0x2d,0x3f,0x3f, 0x2d,0x3a,0x3f, 0x2d,0x36,0x3f, 0x2d,0x31,0x3f, 584 | 0x00,0x00,0x1c, 0x07,0x00,0x1c, 0x0e,0x00,0x1c, 0x15,0x00,0x1c, 0x1c,0x00,0x1c, 0x1c,0x00,0x15, 0x1c,0x00,0x0e, 0x1c,0x00,0x07, 585 | 0x1c,0x00,0x00, 0x1c,0x07,0x00, 0x1c,0x0e,0x00, 0x1c,0x15,0x00, 0x1c,0x1c,0x00, 0x15,0x1c,0x00, 0x0e,0x1c,0x00, 0x07,0x1c,0x00, 586 | 0x00,0x1c,0x00, 0x00,0x1c,0x07, 0x00,0x1c,0x0e, 0x00,0x1c,0x15, 0x00,0x1c,0x1c, 0x00,0x15,0x1c, 0x00,0x0e,0x1c, 0x00,0x07,0x1c, 587 | 588 | 0x0e,0x0e,0x1c, 0x11,0x0e,0x1c, 0x15,0x0e,0x1c, 0x18,0x0e,0x1c, 0x1c,0x0e,0x1c, 0x1c,0x0e,0x18, 0x1c,0x0e,0x15, 0x1c,0x0e,0x11, 589 | 0x1c,0x0e,0x0e, 0x1c,0x11,0x0e, 0x1c,0x15,0x0e, 0x1c,0x18,0x0e, 0x1c,0x1c,0x0e, 0x18,0x1c,0x0e, 0x15,0x1c,0x0e, 0x11,0x1c,0x0e, 590 | 0x0e,0x1c,0x0e, 0x0e,0x1c,0x11, 0x0e,0x1c,0x15, 0x0e,0x1c,0x18, 0x0e,0x1c,0x1c, 0x0e,0x18,0x1c, 0x0e,0x15,0x1c, 0x0e,0x11,0x1c, 591 | 0x14,0x14,0x1c, 0x16,0x14,0x1c, 0x18,0x14,0x1c, 0x1a,0x14,0x1c, 0x1c,0x14,0x1c, 0x1c,0x14,0x1a, 0x1c,0x14,0x18, 0x1c,0x14,0x16, 592 | 0x1c,0x14,0x14, 0x1c,0x16,0x14, 0x1c,0x18,0x14, 0x1c,0x1a,0x14, 0x1c,0x1c,0x14, 0x1a,0x1c,0x14, 0x18,0x1c,0x14, 0x16,0x1c,0x14, 593 | 0x14,0x1c,0x14, 0x14,0x1c,0x16, 0x14,0x1c,0x18, 0x14,0x1c,0x1a, 0x14,0x1c,0x1c, 0x14,0x1a,0x1c, 0x14,0x18,0x1c, 0x14,0x16,0x1c, 594 | 0x00,0x00,0x10, 0x04,0x00,0x10, 0x08,0x00,0x10, 0x0c,0x00,0x10, 0x10,0x00,0x10, 0x10,0x00,0x0c, 0x10,0x00,0x08, 0x10,0x00,0x04, 595 | 0x10,0x00,0x00, 0x10,0x04,0x00, 0x10,0x08,0x00, 0x10,0x0c,0x00, 0x10,0x10,0x00, 0x0c,0x10,0x00, 0x08,0x10,0x00, 0x04,0x10,0x00, 596 | 597 | 0x00,0x10,0x00, 0x00,0x10,0x04, 0x00,0x10,0x08, 0x00,0x10,0x0c, 0x00,0x10,0x10, 0x00,0x0c,0x10, 0x00,0x08,0x10, 0x00,0x04,0x10, 598 | 0x08,0x08,0x10, 0x0a,0x08,0x10, 0x0c,0x08,0x10, 0x0e,0x08,0x10, 0x10,0x08,0x10, 0x10,0x08,0x0e, 0x10,0x08,0x0c, 0x10,0x08,0x0a, 599 | 0x10,0x08,0x08, 0x10,0x0a,0x08, 0x10,0x0c,0x08, 0x10,0x0e,0x08, 0x10,0x10,0x08, 0x0e,0x10,0x08, 0x0c,0x10,0x08, 0x0a,0x10,0x08, 600 | 0x08,0x10,0x08, 0x08,0x10,0x0a, 0x08,0x10,0x0c, 0x08,0x10,0x0e, 0x08,0x10,0x10, 0x08,0x0e,0x10, 0x08,0x0c,0x10, 0x08,0x0a,0x10, 601 | 0x0b,0x0b,0x10, 0x0c,0x0b,0x10, 0x0d,0x0b,0x10, 0x0f,0x0b,0x10, 0x10,0x0b,0x10, 0x10,0x0b,0x0f, 0x10,0x0b,0x0d, 0x10,0x0b,0x0c, 602 | 0x10,0x0b,0x0b, 0x10,0x0c,0x0b, 0x10,0x0d,0x0b, 0x10,0x0f,0x0b, 0x10,0x10,0x0b, 0x0f,0x10,0x0b, 0x0d,0x10,0x0b, 0x0c,0x10,0x0b, 603 | 0x0b,0x10,0x0b, 0x0b,0x10,0x0c, 0x0b,0x10,0x0d, 0x0b,0x10,0x0f, 0x0b,0x10,0x10, 0x0b,0x0f,0x10, 0x0b,0x0d,0x10, 0x0b,0x0c,0x10, 604 | 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00 605 | }; 606 | 607 | static Bit8u static_functionality[0x10]= 608 | { 609 | /* 0 */ 0xff, // All modes supported #1 610 | /* 1 */ 0xe0, // All modes supported #2 611 | /* 2 */ 0x0f, // All modes supported #3 612 | /* 3 */ 0x00, 0x00, 0x00, 0x00, // reserved 613 | /* 7 */ 0x07, // 200, 350, 400 scan lines 614 | /* 8 */ 0x02, // mamimum number of visible charsets in text mode 615 | /* 9 */ 0x08, // total number of charset blocks in text mode 616 | /* a */ 0xe7, // Change to add new functions 617 | /* b */ 0x0c, // Change to add new functions 618 | /* c */ 0x00, // reserved 619 | /* d */ 0x00, // reserved 620 | /* e */ 0x00, // Change to add new functions 621 | /* f */ 0x00 // reserved 622 | }; 623 | --------------------------------------------------------------------------------